aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am22
-rw-r--r--examples/Makefile2
-rw-r--r--java/pom.xml10
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java730
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessageLite.java24
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractParser.java8
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java52
-rw-r--r--java/src/main/java/com/google/protobuf/CodedInputStream.java671
-rw-r--r--java/src/main/java/com/google/protobuf/CodedOutputStream.java230
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java364
-rw-r--r--java/src/main/java/com/google/protobuf/DynamicMessage.java118
-rw-r--r--java/src/main/java/com/google/protobuf/Extension.java96
-rw-r--r--java/src/main/java/com/google/protobuf/ExtensionRegistry.java186
-rw-r--r--java/src/main/java/com/google/protobuf/FieldSet.java100
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java388
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java228
-rw-r--r--java/src/main/java/com/google/protobuf/Internal.java238
-rw-r--r--java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java8
-rw-r--r--java/src/main/java/com/google/protobuf/LazyField.java106
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringArrayList.java215
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringList.java110
-rw-r--r--java/src/main/java/com/google/protobuf/LiteralByteString.java25
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java7
-rw-r--r--java/src/main/java/com/google/protobuf/MessageLite.java1
-rw-r--r--java/src/main/java/com/google/protobuf/MessageOrBuilder.java16
-rw-r--r--java/src/main/java/com/google/protobuf/MessageReflection.java931
-rw-r--r--java/src/main/java/com/google/protobuf/Parser.java2
-rw-r--r--java/src/main/java/com/google/protobuf/ProtocolStringList.java48
-rw-r--r--java/src/main/java/com/google/protobuf/RopeByteString.java14
-rw-r--r--java/src/main/java/com/google/protobuf/RpcUtil.java5
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java792
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSet.java17
-rw-r--r--java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java57
-rw-r--r--java/src/test/java/com/google/protobuf/AbstractMessageTest.java18
-rw-r--r--java/src/test/java/com/google/protobuf/ByteStringTest.java67
-rw-r--r--java/src/test/java/com/google/protobuf/CheckUtf8Test.java141
-rw-r--r--java/src/test/java/com/google/protobuf/CodedInputStreamTest.java279
-rw-r--r--java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java84
-rw-r--r--java/src/test/java/com/google/protobuf/DescriptorsTest.java66
-rw-r--r--java/src/test/java/com/google/protobuf/DynamicMessageTest.java46
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java371
-rw-r--r--java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java134
-rw-r--r--java/src/test/java/com/google/protobuf/LazyFieldTest.java121
-rw-r--r--java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java319
-rw-r--r--java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java12
-rw-r--r--java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java85
-rw-r--r--java/src/test/java/com/google/protobuf/ParserTest.java24
-rw-r--r--java/src/test/java/com/google/protobuf/TestBadIdentifiers.java33
-rw-r--r--java/src/test/java/com/google/protobuf/TestUtil.java175
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java325
-rw-r--r--java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java216
-rw-r--r--java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java75
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java30
-rw-r--r--java/src/test/java/com/google/protobuf/lazy_fields_lite.proto61
-rw-r--r--java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto (renamed from python/google/protobuf/pyext/python_protobuf.cc)42
-rw-r--r--java/src/test/java/com/google/protobuf/multiple_files_test.proto8
-rw-r--r--java/src/test/java/com/google/protobuf/nested_extension.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/non_nested_extension.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/outer_class_name_test.proto38
-rw-r--r--java/src/test/java/com/google/protobuf/outer_class_name_test2.proto42
-rw-r--r--java/src/test/java/com/google/protobuf/outer_class_name_test3.proto43
-rw-r--r--java/src/test/java/com/google/protobuf/test_bad_identifiers.proto49
-rw-r--r--java/src/test/java/com/google/protobuf/test_check_utf8.proto50
-rw-r--r--java/src/test/java/com/google/protobuf/test_check_utf8_size.proto51
-rw-r--r--java/src/test/java/com/google/protobuf/test_custom_options.proto43
-rw-r--r--java/src/test/java/com/google/protobuf/test_extra_interfaces.proto (renamed from python/google/protobuf/pyext/python_descriptor.h)71
-rw-r--r--python/google/protobuf/pyext/python-proto2.cc1717
-rw-r--r--python/google/protobuf/pyext/python_descriptor.cc337
-rwxr-xr-xpython/setup.py38
-rw-r--r--src/Makefile.am24
-rw-r--r--src/google/protobuf/compiler/code_generator.cc8
-rw-r--r--src/google/protobuf/compiler/code_generator.h3
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc194
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h29
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc127
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc52
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc73
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h19
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc28
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc61
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc120
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h24
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc985
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc83
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h19
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc18
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc64
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h20
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_service.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc183
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc732
-rw-r--r--src/google/protobuf/compiler/importer.cc39
-rw-r--r--src/google/protobuf/compiler/importer.h15
-rw-r--r--src/google/protobuf/compiler/importer_unittest.cc55
-rw-r--r--src/google/protobuf/compiler/java/java_context.cc195
-rw-r--r--src/google/protobuf/compiler/java/java_context.h95
-rw-r--r--src/google/protobuf/compiler/java/java_doc_comment.cc13
-rw-r--r--src/google/protobuf/compiler/java/java_doc_comment_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc80
-rw-r--r--src/google/protobuf/compiler/java/java_enum.h15
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc399
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.h61
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc97
-rw-r--r--src/google/protobuf/compiler/java/java_extension.h46
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc206
-rw-r--r--src/google/protobuf/compiler/java/java_field.h79
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc306
-rw-r--r--src/google/protobuf/compiler/java/java_file.h32
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc85
-rw-r--r--src/google/protobuf/compiler/java/java_generator_factory.cc77
-rw-r--r--src/google/protobuf/compiler/java/java_generator_factory.h101
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc307
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h128
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field.cc826
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field.h121
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc763
-rw-r--r--src/google/protobuf/compiler/java/java_message.h50
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc631
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.h69
-rw-r--r--src/google/protobuf/compiler/java/java_name_resolver.cc266
-rw-r--r--src/google/protobuf/compiler/java/java_name_resolver.h124
-rw-r--r--src/google/protobuf/compiler/java/java_plugin_unittest.cc24
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc460
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.h63
-rw-r--r--src/google/protobuf/compiler/java/java_service.cc74
-rw-r--r--src/google/protobuf/compiler/java/java_service.h38
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc223
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.h91
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc574
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.h64
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc25
-rw-r--r--src/google/protobuf/compiler/parser.cc275
-rw-r--r--src/google/protobuf/compiler/parser.h91
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc252
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc278
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h161
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc149
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h9
-rw-r--r--src/google/protobuf/compiler/python/python_plugin_unittest.cc18
-rw-r--r--src/google/protobuf/compiler/subprocess.cc2
-rw-r--r--src/google/protobuf/descriptor.cc737
-rw-r--r--src/google/protobuf/descriptor.h202
-rw-r--r--src/google/protobuf/descriptor.pb.cc2603
-rw-r--r--src/google/protobuf/descriptor.pb.h1435
-rw-r--r--src/google/protobuf/descriptor.proto79
-rw-r--r--src/google/protobuf/descriptor_database.cc4
-rw-r--r--src/google/protobuf/descriptor_database.h2
-rw-r--r--src/google/protobuf/descriptor_pb2_test.py54
-rw-r--r--src/google/protobuf/descriptor_unittest.cc895
-rw-r--r--src/google/protobuf/dynamic_message.cc231
-rw-r--r--src/google/protobuf/dynamic_message.h12
-rw-r--r--src/google/protobuf/dynamic_message_unittest.cc64
-rw-r--r--src/google/protobuf/extension_set.cc241
-rw-r--r--src/google/protobuf/extension_set.h263
-rw-r--r--src/google/protobuf/extension_set_heavy.cc65
-rw-r--r--src/google/protobuf/extension_set_unittest.cc379
-rw-r--r--src/google/protobuf/generated_enum_reflection.h6
-rw-r--r--src/google/protobuf/generated_message_reflection.cc542
-rw-r--r--src/google/protobuf/generated_message_reflection.h93
-rw-r--r--src/google/protobuf/generated_message_reflection_unittest.cc311
-rw-r--r--src/google/protobuf/generated_message_util.cc6
-rw-r--r--src/google/protobuf/generated_message_util.h34
-rw-r--r--src/google/protobuf/io/coded_stream.cc101
-rw-r--r--src/google/protobuf/io/coded_stream.h94
-rw-r--r--src/google/protobuf/io/coded_stream_inl.h3
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc193
-rw-r--r--src/google/protobuf/io/gzip_stream.h2
-rw-r--r--src/google/protobuf/io/printer_unittest.cc2
-rw-r--r--src/google/protobuf/io/strtod.cc113
-rw-r--r--src/google/protobuf/io/strtod.h (renamed from python/google/protobuf/pyext/python_protobuf.h)29
-rw-r--r--src/google/protobuf/io/tokenizer.cc44
-rw-r--r--src/google/protobuf/io/tokenizer.h17
-rw-r--r--src/google/protobuf/io/tokenizer_unittest.cc24
-rw-r--r--src/google/protobuf/io/zero_copy_stream.cc9
-rw-r--r--src/google/protobuf/io/zero_copy_stream.h10
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl.cc8
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl.h1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.cc20
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h14
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc27
-rw-r--r--src/google/protobuf/lite_unittest.cc169
-rw-r--r--src/google/protobuf/message.cc10
-rw-r--r--src/google/protobuf/message.h61
-rw-r--r--src/google/protobuf/message_lite.cc3
-rw-r--r--src/google/protobuf/message_lite.h3
-rw-r--r--src/google/protobuf/message_unittest.cc77
-rw-r--r--src/google/protobuf/reflection_ops.cc4
-rw-r--r--src/google/protobuf/reflection_ops_unittest.cc72
-rw-r--r--src/google/protobuf/repeated_field.h95
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc97
-rw-r--r--src/google/protobuf/stubs/common.h2
-rw-r--r--src/google/protobuf/stubs/map-util.h143
-rw-r--r--src/google/protobuf/stubs/map_util.h771
-rw-r--r--src/google/protobuf/stubs/once.h18
-rw-r--r--src/google/protobuf/stubs/strutil.cc186
-rw-r--r--src/google/protobuf/stubs/strutil.h103
-rw-r--r--src/google/protobuf/stubs/strutil_unittest.cc10
-rw-r--r--src/google/protobuf/test_util.cc298
-rw-r--r--src/google/protobuf/test_util.h22
-rw-r--r--src/google/protobuf/test_util_lite.cc37
-rw-r--r--src/google/protobuf/testdata/bad_utf8_string1
-rw-r--r--src/google/protobuf/testdata/golden_messagebin509 -> 531 bytes
-rw-r--r--src/google/protobuf/testdata/golden_message_oneof_implementedbin0 -> 515 bytes
-rw-r--r--src/google/protobuf/testdata/text_format_unittest_data.txt6
-rw-r--r--src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt129
-rw-r--r--src/google/protobuf/testdata/text_format_unittest_data_pointy.txt134
-rw-r--r--src/google/protobuf/testdata/text_format_unittest_extensions_data.txt6
-rw-r--r--src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt134
-rw-r--r--src/google/protobuf/testing/file.cc18
-rw-r--r--src/google/protobuf/testing/file.h14
-rw-r--r--src/google/protobuf/text_format.cc541
-rw-r--r--src/google/protobuf/text_format.h114
-rw-r--r--src/google/protobuf/text_format_unittest.cc259
-rw-r--r--src/google/protobuf/unittest.proto142
-rw-r--r--src/google/protobuf/unittest_custom_options.proto6
-rw-r--r--src/google/protobuf/unittest_lite.proto24
-rw-r--r--src/google/protobuf/unittest_mset.proto11
-rw-r--r--src/google/protobuf/unittest_no_generic_services.proto1
-rw-r--r--src/google/protobuf/unittest_optimize_for.proto7
-rw-r--r--src/google/protobuf/unknown_field_set.cc25
-rw-r--r--src/google/protobuf/unknown_field_set.h41
-rw-r--r--src/google/protobuf/unknown_field_set_unittest.cc7
-rw-r--r--src/google/protobuf/wire_format.cc74
-rw-r--r--src/google/protobuf/wire_format.h36
-rw-r--r--src/google/protobuf/wire_format_lite.cc112
-rw-r--r--src/google/protobuf/wire_format_lite.h39
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h101
-rw-r--r--src/google/protobuf/wire_format_unittest.cc160
236 files changed, 27852 insertions, 7557 deletions
diff --git a/Makefile.am b/Makefile.am
index c9286132..5246e548 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,7 @@ EXTRA_DIST = \
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 \
@@ -86,6 +87,7 @@ EXTRA_DIST = \
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 \
@@ -93,8 +95,10 @@ EXTRA_DIST = \
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 \
@@ -114,6 +118,7 @@ EXTRA_DIST = \
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 \
@@ -123,8 +128,12 @@ EXTRA_DIST = \
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 \
@@ -142,13 +151,21 @@ EXTRA_DIST = \
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 \
@@ -182,11 +199,6 @@ EXTRA_DIST = \
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/python-proto2.cc \
- python/google/protobuf/pyext/python_descriptor.cc \
- python/google/protobuf/pyext/python_descriptor.h \
- python/google/protobuf/pyext/python_protobuf.cc \
- python/google/protobuf/pyext/python_protobuf.h \
python/google/protobuf/descriptor.py \
python/google/protobuf/descriptor_database.py \
python/google/protobuf/descriptor_pool.py \
diff --git a/examples/Makefile b/examples/Makefile
index 8dc90836..bdfeae68 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -30,7 +30,7 @@ list_people_cpp: list_people.cc protoc_middleman
c++ list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
javac_middleman: AddPerson.java ListPeople.java protoc_middleman
- javac AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java
+ javac AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java com/example/tutorial/AddressBookProtosInternalDescriptors.java
@touch javac_middleman
add_person_java: javac_middleman
diff --git a/java/pom.xml b/java/pom.xml
index 7d5d081c..dc3f63f2 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -104,6 +104,8 @@
<arg value="../src/google/protobuf/unittest_import.proto" />
<arg value="../src/google/protobuf/unittest_import_public.proto" />
<arg value="../src/google/protobuf/unittest_mset.proto" />
+ <arg value="src/test/java/com/google/protobuf/lazy_fields_lite.proto" />
+ <arg value="src/test/java/com/google/protobuf/lite_equals_and_hash.proto" />
<arg
value="src/test/java/com/google/protobuf/multiple_files_test.proto" />
<arg value="src/test/java/com/google/protobuf/nested_builders_test.proto" />
@@ -111,7 +113,13 @@
<arg value="src/test/java/com/google/protobuf/nested_extension_lite.proto" />
<arg value="src/test/java/com/google/protobuf/non_nested_extension.proto" />
<arg value="src/test/java/com/google/protobuf/non_nested_extension_lite.proto" />
+ <arg value="src/test/java/com/google/protobuf/outer_class_name_test.proto" />
+ <arg value="src/test/java/com/google/protobuf/outer_class_name_test2.proto" />
+ <arg value="src/test/java/com/google/protobuf/outer_class_name_test3.proto" />
<arg value="src/test/java/com/google/protobuf/test_bad_identifiers.proto" />
+ <arg value="src/test/java/com/google/protobuf/test_check_utf8.proto" />
+ <arg value="src/test/java/com/google/protobuf/test_check_utf8_size.proto" />
+ <arg value="src/test/java/com/google/protobuf/test_custom_options.proto" />
<arg
value="../src/google/protobuf/unittest_optimize_for.proto" />
<arg
@@ -179,6 +187,8 @@
<include>**/RopeByteString.java</include>
<include>**/Utf8.java</include>
<include>**/LazyField.java</include>
+ <include>**/LazyFieldLite.java</include>
+ <include>**/ProtocolStringList.java</include>
</includes>
<testIncludes>
<testInclude>**/LiteTest.java</testInclude>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index f4d115de..a645c205 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -30,14 +30,13 @@
package com.google.protobuf;
-import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
-import com.google.protobuf.GeneratedMessage.ExtendableBuilder;
+import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.Internal.EnumLite;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -49,56 +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;
- }
- }
- }
-
- // Check that embedded messages are initialized.
- for (final Map.Entry<FieldDescriptor, Object> entry :
- getAllFields().entrySet()) {
- final FieldDescriptor field = entry.getKey();
- if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- if (field.isRepeated()) {
- for (final Message element : (List<Message>) entry.getValue()) {
- if (!element.isInitialized()) {
- return false;
- }
- }
- } else {
- if (!((Message) entry.getValue()).isInitialized()) {
- return false;
- }
- }
- }
- }
-
- return true;
+ return MessageReflection.isInitialized(this);
}
+
public List<String> findInitializationErrors() {
- return Builder.findMissingFields(this);
+ return MessageReflection.findMissingFields(this);
}
public String getInitializationErrorString() {
- return delimitWithCommas(findInitializationErrors());
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
}
- private static String delimitWithCommas(List<String> parts) {
- StringBuilder result = new StringBuilder();
- for (String part : parts) {
- if (result.length() > 0) {
- result.append(", ");
- }
- result.append(part);
- }
- return result.toString();
+ /** 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
@@ -107,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<FieldDescriptor, Object> 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;
@@ -139,33 +91,8 @@ public abstract class AbstractMessage extends AbstractMessageLite
return size;
}
- size = 0;
- final boolean isMessageSet =
- getDescriptorForType().getOptions().getMessageSetWireFormat();
-
- for (final Map.Entry<FieldDescriptor, Object> 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
@@ -180,22 +107,93 @@ 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 = hashFields(hash, getAllFields());
- 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<FieldDescriptor, Object> a,
+ Map<FieldDescriptor, Object> 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 int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+ protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) {
for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
FieldDescriptor field = entry.getKey();
Object value = entry.getValue();
@@ -204,31 +202,15 @@ public abstract class AbstractMessage extends AbstractMessageLite
hash = (53 * hash) + value.hashCode();
} else if (field.isRepeated()) {
List<? extends EnumLite> list = (List<? extends EnumLite>) value;
- hash = (53 * hash) + hashEnumList(list);
+ hash = (53 * hash) + Internal.hashEnumList(list);
} else {
- hash = (53 * hash) + hashEnum((EnumLite) value);
+ hash = (53 * hash) + Internal.hashEnum((EnumLite) value);
}
}
return hash;
}
/**
- * Helper method for implementing {@link Message#hashCode()}.
- * @see Boolean#hashCode()
- */
- protected static int hashLong(long n) {
- return (int) (n ^ (n >>> 32));
- }
-
- /**
- * Helper method for implementing {@link Message#hashCode()}.
- * @see Boolean#hashCode()
- */
- protected static int hashBoolean(boolean b) {
- return b ? 1231 : 1237;
- }
-
- /**
* Package private helper method for AbstractParser to create
* UninitializedMessageException with missing field information.
*/
@@ -237,26 +219,6 @@ public abstract class AbstractMessage extends AbstractMessageLite
return Builder.newUninitializedMessageException(this);
}
- /**
- * Helper method for implementing {@link Message#hashCode()}.
- * <p>
- * 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.
- */
- protected static int hashEnum(EnumLite e) {
- return e.getNumber();
- }
-
- /** Helper method for implementing {@link Message#hashCode()}. */
- protected static int hashEnumList(List<? extends EnumLite> list) {
- int hash = 1;
- for (EnumLite e : list) {
- hash = 31 * hash + hashEnum(e);
- }
- return hash;
- }
-
// =================================================================
/**
@@ -272,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<FieldDescriptor, Object> entry :
getAllFields().entrySet()) {
@@ -281,11 +262,11 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
public List<String> findInitializationErrors() {
- return findMissingFields(this);
+ return MessageReflection.findMissingFields(this);
}
public String getInitializationErrorString() {
- return delimitWithCommas(findInitializationErrors());
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
}
public BuilderType mergeFrom(final Message other) {
@@ -350,8 +331,13 @@ public abstract class AbstractMessage extends AbstractMessageLite
break;
}
- if (!mergeFieldFrom(input, unknownFields, extensionRegistry,
- getDescriptorForType(), this, null, tag)) {
+ MessageReflection.BuilderAdapter builderAdapter =
+ new MessageReflection.BuilderAdapter(this);
+ if (!MessageReflection.mergeFieldFrom(input, unknownFields,
+ extensionRegistry,
+ getDescriptorForType(),
+ builderAdapter,
+ tag)) {
// end group tag
break;
}
@@ -360,394 +346,6 @@ public abstract class AbstractMessage extends AbstractMessageLite
return (BuilderType) this;
}
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static void addRepeatedField(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field,
- Object value) {
- if (builder != null) {
- builder.addRepeatedField(field, value);
- } else {
- extensions.addRepeatedField(field, value);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static void setField(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field,
- Object value) {
- if (builder != null) {
- builder.setField(field, value);
- } else {
- extensions.setField(field, value);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static boolean hasOriginalMessage(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field) {
- if (builder != null) {
- return builder.hasField(field);
- } else {
- return extensions.hasField(field);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static Message getOriginalMessage(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field) {
- if (builder != null) {
- return (Message) builder.getField(field);
- } else {
- return (Message) extensions.getField(field);
- }
- }
-
- /** helper method to handle {@code builder} and {@code extensions}. */
- private static void mergeOriginalMessage(
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- FieldDescriptor field,
- Message.Builder subBuilder) {
- Message originalMessage = getOriginalMessage(builder, extensions, field);
- if (originalMessage != null) {
- subBuilder.mergeFrom(originalMessage);
- }
- }
-
- /**
- * Like {@link #mergeFrom(CodedInputStream, ExtensionRegistryLite)}, but
- * parses a single field.
- *
- * When {@code builder} is not null, the method will parse and merge the
- * field into {@code builder}. Otherwise, it will try to parse the field
- * into {@code extensions}, when it's called by the parsing constructor in
- * generated classes.
- *
- * 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,
- Descriptor type,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions,
- int tag) throws IOException {
- if (type.getOptions().getMessageSetWireFormat() &&
- tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
- mergeMessageSetExtensionFromCodedStream(
- input, unknownFields, extensionRegistry, type, builder, extensions);
- 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 if (builder != null) {
- 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;
- }
- addRepeatedField(builder, extensions, field, value);
- }
- } else {
- while (input.getBytesUntilLimit() > 0) {
- final Object value =
- FieldSet.readPrimitiveField(input, field.getLiteType());
- addRepeatedField(builder, extensions, 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()) {
- mergeOriginalMessage(builder, extensions, field, subBuilder);
- }
- input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
- value = subBuilder.buildPartial();
- break;
- }
- case MESSAGE: {
- final Message.Builder subBuilder;
- if (defaultInstance != null) {
- subBuilder = defaultInstance.newBuilderForType();
- } else {
- subBuilder = builder.newBuilderForField(field);
- }
- if (!field.isRepeated()) {
- mergeOriginalMessage(builder, extensions, field, subBuilder);
- }
- input.readMessage(subBuilder, extensionRegistry);
- value = subBuilder.buildPartial();
- 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()) {
- addRepeatedField(builder, extensions, field, value);
- } else {
- setField(builder, extensions, field, value);
- }
- }
-
- return true;
- }
-
- /**
- * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension.
- * If {@code builder} is not null, this method will merge MessageSet into
- * the builder. Otherwise, it will merge the MessageSet into {@code
- * extensions}.
- */
- private static void mergeMessageSetExtensionFromCodedStream(
- CodedInputStream input,
- UnknownFieldSet.Builder unknownFields,
- ExtensionRegistryLite extensionRegistry,
- Descriptor type,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions) 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 = ((ExtensionRegistry) extensionRegistry)
- .findExtensionByNumber(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, builder, extensions);
- 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, builder, extensions);
- } 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 eagerlyMergeMessageSetExtension(
- CodedInputStream input,
- ExtensionRegistry.ExtensionInfo extension,
- ExtensionRegistryLite extensionRegistry,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions) throws IOException {
-
- FieldDescriptor field = extension.descriptor;
- Message value = null;
- if (hasOriginalMessage(builder, extensions, field)) {
- Message originalMessage =
- getOriginalMessage(builder, extensions, field);
- Message.Builder subBuilder = originalMessage.toBuilder();
- input.readMessage(subBuilder, extensionRegistry);
- value = subBuilder.buildPartial();
- } else {
- value = input.readMessage(extension.defaultInstance.getParserForType(),
- extensionRegistry);
- }
-
- if (builder != null) {
- builder.setField(field, value);
- } else {
- extensions.setField(field, value);
- }
- }
-
- private static void mergeMessageSetExtensionFromBytes(
- ByteString rawBytes,
- ExtensionRegistry.ExtensionInfo extension,
- ExtensionRegistryLite extensionRegistry,
- Message.Builder builder,
- FieldSet<FieldDescriptor> extensions) throws IOException {
-
- FieldDescriptor field = extension.descriptor;
- boolean hasOriginalValue = hasOriginalMessage(builder, extensions, field);
-
- if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
- // If the field already exists, we just parse the field.
- Message value = null;
- if (hasOriginalValue) {
- Message originalMessage =
- getOriginalMessage(builder, extensions, field);
- Message.Builder subBuilder= originalMessage.toBuilder();
- subBuilder.mergeFrom(rawBytes, extensionRegistry);
- value = subBuilder.buildPartial();
- } else {
- value = extension.defaultInstance.getParserForType()
- .parsePartialFrom(rawBytes, extensionRegistry);
- }
- setField(builder, extensions, field, value);
- } else {
- // Use LazyField to load MessageSet lazily.
- LazyField lazyField = new LazyField(
- extension.defaultInstance, extensionRegistry, rawBytes);
- if (builder != null) {
- // TODO(xiangl): it looks like this method can only be invoked by
- // ExtendableBuilder, but I'm not sure. So I double check the type of
- // builder here. It may be useless and need more investigation.
- if (builder instanceof ExtendableBuilder) {
- builder.setField(field, lazyField);
- } else {
- builder.setField(field, lazyField.getValue());
- }
- } else {
- extensions.setField(field, lazyField);
- }
- }
- }
-
public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
setUnknownFields(
UnknownFieldSet.newBuilder(getUnknownFields())
@@ -761,79 +359,18 @@ public abstract class AbstractMessage extends AbstractMessageLite
"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<String> findMissingFields(
- final MessageOrBuilder message) {
- final List<String> results = new ArrayList<String>();
- findMissingFields(message, "", results);
- return results;
- }
-
- /** Recursive helper implementing {@link #findMissingFields(Message)}. */
- private static void findMissingFields(final MessageOrBuilder message,
- final String prefix,
- final List<String> results) {
- for (final FieldDescriptor field :
- message.getDescriptorForType().getFields()) {
- if (field.isRequired() && !message.hasField(field)) {
- results.add(prefix + field.getName());
- }
- }
-
- for (final Map.Entry<FieldDescriptor, Object> 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((MessageOrBuilder) element,
- subMessagePrefix(prefix, field, i++),
- results);
- }
- } else {
- if (message.hasField(field)) {
- findMissingFields((MessageOrBuilder) 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));
}
// ===============================================================
@@ -925,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 9926f3db..bce713b0 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,7 @@ public abstract class AbstractMessageLite implements MessageLite {
codedOutput.flush();
}
+
/**
* Package private helper method for AbstractParser to create
* UninitializedMessageException.
@@ -99,6 +102,13 @@ public abstract class AbstractMessageLite implements MessageLite {
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
@@ -311,7 +321,8 @@ 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 <T> void addAll(final Iterable<T> values,
final Collection<? super T> list) {
@@ -319,14 +330,15 @@ public abstract class AbstractMessageLite implements MessageLite {
// For StringOrByteStringLists, check the underlying elements to avoid
// forcing conversions of ByteStrings to Strings.
checkForNullValues(((LazyStringList) values).getUnderlyingElements());
- } else {
+ list.addAll((Collection<T>) values);
+ } else if (values instanceof Collection) {
checkForNullValues(values);
- }
- if (values instanceof Collection) {
- final Collection<T> collection = (Collection<T>) values;
- list.addAll(collection);
+ list.addAll((Collection<T>) values);
} else {
for (final T value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
list.add(value);
}
}
diff --git a/java/src/main/java/com/google/protobuf/AbstractParser.java b/java/src/main/java/com/google/protobuf/AbstractParser.java
index 9bd9d397..3f30124f 100644
--- a/java/src/main/java/com/google/protobuf/AbstractParser.java
+++ b/java/src/main/java/com/google/protobuf/AbstractParser.java
@@ -110,10 +110,6 @@ public abstract class AbstractParser<MessageType extends MessageLite>
return message;
} catch (InvalidProtocolBufferException e) {
throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a ByteString threw an IOException (should " +
- "never happen).", e);
}
}
@@ -147,10 +143,6 @@ public abstract class AbstractParser<MessageType extends MessageLite>
return message;
} catch (InvalidProtocolBufferException e) {
throw e;
- } catch (IOException e) {
- throw new RuntimeException(
- "Reading from a byte array threw an IOException (should " +
- "never happen).", e);
}
}
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index 73d831f6..89b57897 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -177,6 +177,20 @@ public abstract class ByteString implements Iterable<Byte> {
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 <code>true</code> if the byte sequence represented by the
+ * argument is a suffix of the byte sequence represented by
+ * this string; <code>false</code> otherwise.
+ */
+ public boolean endsWith(ByteString suffix) {
+ return size() >= suffix.size() &&
+ substring(size() - suffix.size()).equals(suffix);
+ }
+
// =================================================================
// byte[] -> ByteString
@@ -512,6 +526,9 @@ public abstract class ByteString implements Iterable<Byte> {
*/
public byte[] toByteArray() {
int size = size();
+ if (size == 0) {
+ return Internal.EMPTY_BYTE_ARRAY;
+ }
byte[] result = new byte[size];
copyToInternal(result, 0, 0, size);
return result;
@@ -525,6 +542,41 @@ public abstract class ByteString implements Iterable<Byte> {
* @throws IOException if an I/O error occurs.
*/
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
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index 33417a7f..b25b9713 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;
/**
@@ -88,6 +91,53 @@ public final class CodedInputStream {
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;
+ }
+
// -----------------------------------------------------------------
/**
@@ -125,6 +175,10 @@ public final class CodedInputStream {
}
}
+ public int getLastTag() {
+ return lastTag;
+ }
+
/**
* Reads and discards a single field, given its tag value.
*
@@ -134,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());
@@ -151,8 +205,59 @@ public final class CodedInputStream {
case WireFormat.WIRETYPE_END_GROUP:
return false;
case WireFormat.WIRETYPE_FIXED32:
- readRawLittleEndian32();
+ skipRawBytes(4);
+ return true;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ /**
+ * 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();
}
@@ -171,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. */
@@ -210,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) {
@@ -222,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(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.
- return new String(readRawBytes(size), "UTF-8");
+ 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. */
@@ -243,6 +427,7 @@ public final class CodedInputStream {
--recursionDepth;
}
+
/** Read a {@code group} field value from the stream. */
public <T extends MessageLite> T readGroup(
final int fieldNumber,
@@ -295,6 +480,7 @@ public final class CodedInputStream {
popLimit(oldLimit);
}
+
/** Read an embedded message field value from the stream. */
public <T extends MessageLite> T readMessage(
final Parser<T> parser,
@@ -316,17 +502,58 @@ public final class CodedInputStream {
/** Read a {@code bytes} field value from the stream. */
public ByteString readBytes() throws IOException {
final int size = readRawVarint32();
- if (size == 0) {
- return ByteString.EMPTY;
- } else if (size <= (bufferSize - bufferPos) && size > 0) {
+ 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));
}
}
@@ -370,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();
}
/**
@@ -456,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));
}
/**
@@ -532,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
@@ -567,6 +892,7 @@ public final class CodedInputStream {
bufferPos = off;
totalBytesRetired = -off;
input = null;
+ bufferIsImmutable = false;
}
private CodedInputStream(final InputStream input) {
@@ -575,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;
}
/**
@@ -698,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);
}
/**
@@ -709,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);
+ }
+ }
+
/**
- * Called with {@code this.buffer} is empty to read more bytes from the
- * input. If {@code mustSucceed} is true, refillBuffer() guarantees 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.
+ * 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 boolean refillBuffer(final boolean mustSucceed) throws IOException {
- if (bufferPos < bufferSize) {
+ private void refillBuffer(int n) throws IOException {
+ if (!tryRefillBuffer(n)) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ }
+
+ /**
+ * 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 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;
}
/**
@@ -766,7 +1146,7 @@ public final class CodedInputStream {
*/
public byte readRawByte() throws IOException {
if (bufferPos == bufferSize) {
- refillBuffer(true);
+ refillBuffer(1);
}
return buffer[bufferPos++];
}
@@ -778,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) {
@@ -789,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.
@@ -805,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;
@@ -885,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();
}
@@ -896,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;
- bufferPos = bufferSize;
-
- // 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(true);
- while (size - pos > bufferSize) {
- pos += bufferSize;
- bufferPos = bufferSize;
- refillBuffer(true);
- }
+ // Skipping more bytes than are in the buffer. First skip what we have.
+ int pos = bufferSize - bufferPos;
+ bufferPos = bufferSize;
- bufferPos = size - pos;
+ // 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 ca24638d..0f232071 100644
--- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -31,9 +31,9 @@
package com.google.protobuf;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
/**
* Encodes and writes protocol message fields.
@@ -53,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;
@@ -129,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. */
@@ -202,6 +235,7 @@ public final class CodedOutputStream {
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
+
/**
* Write a group represented by an {@link UnknownFieldSet}.
*
@@ -222,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 {
@@ -229,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 {
@@ -362,6 +430,7 @@ public final class CodedOutputStream {
value.writeTo(this);
}
+
/**
* Write a group represented by an {@link UnknownFieldSet}.
*
@@ -380,12 +449,41 @@ public final class CodedOutputStream {
value.writeTo(this);
}
+
/** Write a {@code bytes} field to the stream. */
public void writeBytesNoTag(final ByteString value) throws IOException {
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. */
public void writeUInt32NoTag(final int value) throws IOException {
writeRawVarint32(value);
@@ -540,11 +638,29 @@ 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 LazyField value) {
+ final LazyFieldLite value) {
return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
}
@@ -629,7 +745,7 @@ public final class CodedOutputStream {
* historical reasons, the wire format differs from normal fields.
*/
public static int computeLazyFieldMessageSetExtensionSize(
- final int fieldNumber, final LazyField value) {
+ 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);
@@ -754,7 +870,7 @@ 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 LazyField value) {
+ public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) {
final int size = value.getSerializedSize();
return computeRawVarint32Size(size) + size;
}
@@ -770,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) {
@@ -886,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) {
@@ -893,6 +1034,7 @@ public final class CodedOutputStream {
}
buffer[position++] = value;
+ ++totalBytesWritten;
}
/** Write a single byte, represented by an integer value. */
@@ -910,6 +1052,61 @@ public final class CodedOutputStream {
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 {
@@ -917,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.
@@ -925,6 +1123,7 @@ public final class CodedOutputStream {
offset += bytesWritten;
length -= bytesWritten;
position = limit;
+ totalBytesWritten += bytesWritten;
refreshBuffer();
// Now deal with the rest.
@@ -938,6 +1137,7 @@ public final class CodedOutputStream {
// Write is very big. Let's do it all at once.
output.write(value, offset, length);
}
+ totalBytesWritten += length;
}
}
@@ -948,6 +1148,7 @@ public final class CodedOutputStream {
// 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.
@@ -956,6 +1157,7 @@ public final class CodedOutputStream {
offset += bytesWritten;
length -= bytesWritten;
position = limit;
+ totalBytesWritten += bytesWritten;
refreshBuffer();
// Now deal with the rest.
@@ -966,25 +1168,9 @@ public final class CodedOutputStream {
value.copyTo(buffer, offset, 0, length);
position = length;
} else {
- // Write is very big, but we can't do it all at once without allocating
- // an a copy of the byte array since ByteString does not give us access
- // to the underlying bytes. Use the InputStream interface on the
- // ByteString and our buffer to copy between the two.
- InputStream inputStreamFrom = value.newInput();
- if (offset != inputStreamFrom.skip(offset)) {
- throw new IllegalStateException("Skip failed? Should never happen.");
- }
- // Use the buffer as the temporary buffer to avoid allocating memory.
- while (length > 0) {
- int bytesToRead = Math.min(length, limit);
- int bytesRead = inputStreamFrom.read(buffer, 0, bytesToRead);
- if (bytesRead != bytesToRead) {
- throw new IllegalStateException("Read failed? Should never happen");
- }
- output.write(buffer, 0, bytesRead);
- length -= bytesRead;
- }
+ 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 a4913053..98e52320 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -32,6 +32,7 @@ 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;
@@ -39,6 +40,7 @@ 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;
/**
@@ -60,19 +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
@@ -213,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
@@ -223,6 +232,28 @@ public final class Descriptors {
public static FileDescriptor buildFrom(final FileDescriptorProto proto,
final FileDescriptor[] dependencies)
throws DescriptorValidationException {
+ 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
@@ -232,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;
}
@@ -296,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);
@@ -320,6 +340,56 @@ 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<FileDescriptor> descriptors = new ArrayList<FileDescriptor>();
+ 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
@@ -346,22 +416,38 @@ public final class Descriptors {
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();
- this.publicDependencies =
- new FileDescriptor[proto.getPublicDependencyCount()];
+ HashMap<String, FileDescriptor> nameToFileMap =
+ new HashMap<String, FileDescriptor>();
+ for (FileDescriptor file : dependencies) {
+ nameToFileMap.put(file.getName(), file);
+ }
+ List<FileDescriptor> publicDependencies = new ArrayList<FileDescriptor>();
for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
int index = proto.getPublicDependency(i);
- if (index < 0 || index >= this.dependencies.length) {
+ if (index < 0 || index >= proto.getDependencyCount()) {
throw new DescriptorValidationException(this,
"Invalid public dependency index.");
}
- this.publicDependencies[i] =
- this.dependencies[proto.getPublicDependency(i)];
+ 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);
@@ -387,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 {
@@ -437,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:
@@ -486,6 +593,11 @@ public final class Descriptors {
return Collections.unmodifiableList(Arrays.asList(fields));
}
+ /** Get a list of this message type's oneofs. */
+ public List<OneofDescriptor> getOneofs() {
+ return Collections.unmodifiableList(Arrays.asList(oneofs));
+ }
+
/** Get a list of this message type's extensions. */
public List<FieldDescriptor> getExtensions() {
return Collections.unmodifiableList(Arrays.asList(extensions));
@@ -513,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.
@@ -576,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,
@@ -588,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(
@@ -612,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);
}
@@ -656,7 +820,8 @@ public final class Descriptors {
/** Describes a field of a message type. */
public static final class FieldDescriptor
- implements GenericDescriptor, Comparable<FieldDescriptor>,
+ extends GenericDescriptor
+ implements Comparable<FieldDescriptor>,
FieldSet.FieldDescriptorLite<FieldDescriptor> {
/**
* Get the index of this descriptor within its parent.
@@ -700,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.
@@ -761,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
@@ -838,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;
@@ -946,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;
}
@@ -1161,13 +1355,14 @@ 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<EnumValueDescriptor> {
+ public static final class EnumDescriptor extends GenericDescriptor
+ implements Internal.EnumLiteMap<EnumValueDescriptor> {
/**
* Get the index of this descriptor within its parent.
* @see Descriptors.Descriptor#getIndex()
@@ -1278,8 +1473,8 @@ 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 Descriptors.Descriptor#getIndex()
@@ -1294,6 +1489,9 @@ 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.
@@ -1343,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()
@@ -1433,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()
@@ -1537,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}.<p>
+ *
+ * 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();
}
/**
@@ -1620,8 +1822,10 @@ public final class Descriptors {
TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS
}
- DescriptorPool(final FileDescriptor[] dependencies) {
+ DescriptorPool(final FileDescriptor[] dependencies,
+ boolean allowUnknownDependencies) {
this.dependencies = new HashSet<FileDescriptor>();
+ this.allowUnknownDependencies = allowUnknownDependencies;
for (int i = 0; i < dependencies.length; i++) {
this.dependencies.add(dependencies[i]);
@@ -1650,6 +1854,7 @@ public final class Descriptors {
}
private final Set<FileDescriptor> dependencies;
+ private boolean allowUnknownDependencies;
private final Map<String, GenericDescriptor> descriptorsByName =
new HashMap<String, GenericDescriptor>();
@@ -1718,9 +1923,11 @@ public final class Descriptors {
// 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), filter);
+ 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.
@@ -1752,6 +1959,7 @@ public final class Descriptors {
// Chop off the last component of the scope.
final int dotpos = scopeToTry.lastIndexOf(".");
if (dotpos == -1) {
+ fullname = name;
result = findSymbol(name, filter);
break;
} else {
@@ -1771,6 +1979,7 @@ public final class Descriptors {
scopeToTry.append(name);
result = findSymbol(scopeToTry.toString(), filter);
}
+ fullname = scopeToTry.toString();
break;
}
@@ -1781,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;
}
@@ -1826,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; }
@@ -1911,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() + "\".");
}
@@ -1967,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 c0c9fc94..f4aa26cf 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -32,6 +32,7 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
import java.io.InputStream;
import java.io.IOException;
@@ -47,16 +48,25 @@ import java.util.Map;
public final class DynamicMessage extends AbstractMessage {
private final Descriptor type;
private final FieldSet<FieldDescriptor> 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<FieldDescriptor> fields,
- UnknownFieldSet unknownFields) {
+ DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
+ FieldDescriptor[] oneofCases,
+ UnknownFieldSet unknownFields) {
this.type = type;
this.fields = fields;
+ this.oneofCases = oneofCases;
this.unknownFields = unknownFields;
}
@@ -65,10 +75,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.<FieldDescriptor>emptySet(),
+ oneofCases,
UnknownFieldSet.getDefaultInstance());
}
+
/** Parse a message of the given type from the given input stream. */
public static DynamicMessage parseFrom(Descriptor type,
CodedInputStream input)
@@ -152,6 +166,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);
@@ -186,8 +214,8 @@ public final class DynamicMessage extends AbstractMessage {
return unknownFields;
}
- private static boolean isInitialized(Descriptor type,
- FieldSet<FieldDescriptor> fields) {
+ static boolean isInitialized(Descriptor type,
+ FieldSet<FieldDescriptor> fields) {
// Check that all required fields are present.
for (final FieldDescriptor field : type.getFields()) {
if (field.isRequired()) {
@@ -270,6 +298,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.");
+ }
+ }
+
// =================================================================
/**
@@ -278,6 +314,7 @@ public final class DynamicMessage extends AbstractMessage {
public static final class Builder extends AbstractMessage.Builder<Builder> {
private final Descriptor type;
private FieldSet<FieldDescriptor> fields;
+ private final FieldDescriptor[] oneofCases;
private UnknownFieldSet unknownFields;
/** Construct a {@code Builder} for the given type. */
@@ -285,6 +322,7 @@ public final class DynamicMessage extends AbstractMessage {
this.type = type;
this.fields = FieldSet.newFieldSet();
this.unknownFields = UnknownFieldSet.getDefaultInstance();
+ this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()];
}
// ---------------------------------------------------------------
@@ -313,6 +351,17 @@ public final class DynamicMessage extends AbstractMessage {
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);
@@ -322,7 +371,8 @@ public final class DynamicMessage extends AbstractMessage {
public DynamicMessage build() {
if (!isInitialized()) {
throw newUninitializedMessageException(
- new DynamicMessage(type, fields, unknownFields));
+ new DynamicMessage(type, fields,
+ java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields));
}
return buildPartial();
}
@@ -335,7 +385,8 @@ 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();
@@ -344,7 +395,8 @@ public final class DynamicMessage extends AbstractMessage {
public DynamicMessage buildPartial() {
fields.makeImmutable();
DynamicMessage result =
- new DynamicMessage(type, fields, unknownFields);
+ new DynamicMessage(type, fields,
+ java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields);
return result;
}
@@ -353,6 +405,7 @@ public final class DynamicMessage extends AbstractMessage {
Builder result = new Builder(type);
result.fields.mergeFrom(fields);
result.mergeUnknownFields(unknownFields);
+ System.arraycopy(oneofCases, 0, result.oneofCases, 0 , oneofCases.length);
return result;
}
@@ -383,6 +436,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);
@@ -392,7 +468,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();
@@ -404,6 +482,15 @@ public final class DynamicMessage extends AbstractMessage {
public Builder setField(FieldDescriptor field, Object value) {
verifyContainingType(field);
ensureIsMutable();
+ 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;
}
@@ -411,6 +498,13 @@ public final class DynamicMessage extends AbstractMessage {
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;
}
@@ -466,6 +560,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.");
+ }
+ }
+
private void ensureIsMutable() {
if (fields.isImmutable()) {
fields = fields.clone();
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 00000000..4364e516
--- /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<ContainingType extends MessageLite, Type> {
+ /** 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 d4f6ba9e..2dfef3ca 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<ExtensionInfo> getAllMutableExtensionsByExtendedType(final String fullName) {
+ HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
+ 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<ExtensionInfo> getAllImmutableExtensionsByExtendedType(final String fullName) {
+ HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
+ 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<String, ExtensionInfo>();
- this.extensionsByNumber = new HashMap<DescriptorIntPair, ExtensionInfo>();
+ this.immutableExtensionsByName = new HashMap<String, ExtensionInfo>();
+ this.mutableExtensionsByName = new HashMap<String, ExtensionInfo>();
+ this.immutableExtensionsByNumber =
+ new HashMap<DescriptorIntPair, ExtensionInfo>();
+ this.mutableExtensionsByNumber =
+ new HashMap<DescriptorIntPair, ExtensionInfo>();
}
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<String, ExtensionInfo> extensionsByName;
- private final Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
+ private final Map<String, ExtensionInfo> immutableExtensionsByName;
+ private final Map<String, ExtensionInfo> mutableExtensionsByName;
+ private final Map<DescriptorIntPair, ExtensionInfo> immutableExtensionsByNumber;
+ private final Map<DescriptorIntPair, ExtensionInfo> mutableExtensionsByNumber;
- private ExtensionRegistry(boolean empty) {
+ ExtensionRegistry(boolean empty) {
super(ExtensionRegistryLite.getEmptyRegistry());
- this.extensionsByName = Collections.<String, ExtensionInfo>emptyMap();
- this.extensionsByNumber =
+ this.immutableExtensionsByName =
+ Collections.<String, ExtensionInfo>emptyMap();
+ this.mutableExtensionsByName =
+ Collections.<String, ExtensionInfo>emptyMap();
+ this.immutableExtensionsByNumber =
Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
+ this.mutableExtensionsByNumber =
+ Collections.<DescriptorIntPair, ExtensionInfo>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<String, ExtensionInfo> extensionsByName;
+ Map<DescriptorIntPair, ExtensionInfo> 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/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index 2663694f..01b6a35c 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -146,6 +146,7 @@ final class FieldSet<FieldDescriptorType extends
return clone;
}
+
// =================================================================
/** See {@link Message.Builder#clear()}. */
@@ -376,10 +377,13 @@ final class FieldSet<FieldDescriptorType extends
case DOUBLE: isValid = value instanceof Double ; break;
case BOOLEAN: isValid = value instanceof Boolean ; break;
case STRING: isValid = value instanceof String ; break;
- case BYTE_STRING: isValid = value instanceof ByteString; break;
+ case BYTE_STRING:
+ isValid = value instanceof ByteString || value instanceof byte[];
+ break;
case ENUM:
// TODO(kenton): Caller must do type checking here, I guess.
- isValid = value instanceof Internal.EnumLite;
+ isValid =
+ (value instanceof Integer || value instanceof Internal.EnumLite);
break;
case MESSAGE:
// TODO(kenton): Caller must do type checking here, I guess.
@@ -483,6 +487,17 @@ final class FieldSet<FieldDescriptorType extends
}
}
+ 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<FieldDescriptorType, Object> entry) {
@@ -495,28 +510,26 @@ final class FieldSet<FieldDescriptorType extends
if (descriptor.isRepeated()) {
Object value = getField(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);
+ 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, otherValue);
+ fields.put(descriptor, cloneIfMutable(otherValue));
} else {
// Merge the messages.
- fields.put(
- descriptor,
- descriptor.internalMergeFrom(
+ value = descriptor.internalMergeFrom(
((MessageLite) value).toBuilder(), (MessageLite) otherValue)
- .build());
+ .build();
+
+ fields.put(descriptor, value);
}
} else {
- fields.put(descriptor, otherValue);
+ fields.put(descriptor, cloneIfMutable(otherValue));
}
}
@@ -524,11 +537,13 @@ final class FieldSet<FieldDescriptorType extends
// other class. Probably WireFormat.
/**
- * Read a field of any primitive type from a CodedInputStream. Enums,
- * groups, and embedded messages are not handled by this method.
+ * Read a field of any primitive type for immutable messages from a
+ * CodedInputStream. Enums, groups, and embedded messages are not handled by
+ * this method.
*
* @param input The stream from which to read.
* @param type Declared type of the field.
+ * @param checkUtf8 When true, check that the input is valid utf8.
* @return An object representing the field's value, of the exact
* type which would be returned by
* {@link Message#getField(Descriptors.FieldDescriptor)} for
@@ -536,7 +551,8 @@ final class FieldSet<FieldDescriptorType extends
*/
public static Object readPrimitiveField(
CodedInputStream input,
- final WireFormat.FieldType type) throws IOException {
+ final WireFormat.FieldType type,
+ boolean checkUtf8) throws IOException {
switch (type) {
case DOUBLE : return input.readDouble ();
case FLOAT : return input.readFloat ();
@@ -546,7 +562,11 @@ final class FieldSet<FieldDescriptorType extends
case FIXED64 : return input.readFixed64 ();
case FIXED32 : return input.readFixed32 ();
case BOOL : return input.readBool ();
- case STRING : return input.readString ();
+ case STRING : if (checkUtf8) {
+ return input.readStringRequireUtf8();
+ } else {
+ return input.readString();
+ }
case BYTES : return input.readBytes ();
case UINT32 : return input.readUInt32 ();
case SFIXED32: return input.readSFixed32();
@@ -571,6 +591,7 @@ final class FieldSet<FieldDescriptorType extends
"There is no way to get here, but the compiler thinks otherwise.");
}
+
/** See {@link Message#writeTo(CodedOutputStream)}. */
public void writeTo(final CodedOutputStream output)
throws IOException {
@@ -605,8 +626,12 @@ final class FieldSet<FieldDescriptorType extends
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) entry.getValue());
+ (MessageLite) value);
} else {
writeField(descriptor, entry.getValue(), output);
}
@@ -630,7 +655,7 @@ final class FieldSet<FieldDescriptorType extends
// Special case for groups, which need a start and end tag; other fields
// can just use writeTag() and writeFieldNoTag().
if (type == WireFormat.FieldType.GROUP) {
- output.writeGroup(number, (MessageLite) value);
+ output.writeGroup(number, (MessageLite) value);
} else {
output.writeTag(number, getWireFormatForFieldType(type, false));
writeElementNoTag(output, type, value);
@@ -663,7 +688,13 @@ final class FieldSet<FieldDescriptorType extends
case STRING : output.writeStringNoTag ((String ) value); break;
case GROUP : output.writeGroupNoTag ((MessageLite) value); break;
case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break;
- case BYTES : output.writeBytesNoTag ((ByteString ) value); break;
+ case BYTES:
+ if (value instanceof ByteString) {
+ output.writeBytesNoTag((ByteString) value);
+ } else {
+ output.writeByteArrayNoTag((byte[]) value);
+ }
+ break;
case UINT32 : output.writeUInt32NoTag ((Integer ) value); break;
case SFIXED32: output.writeSFixed32NoTag((Integer ) value); break;
case SFIXED64: output.writeSFixed64NoTag((Long ) value); break;
@@ -671,7 +702,11 @@ final class FieldSet<FieldDescriptorType extends
case SINT64 : output.writeSInt64NoTag ((Long ) value); break;
case ENUM:
- output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
+ if (value instanceof Internal.EnumLite) {
+ output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
+ } else {
+ output.writeEnumNoTag(((Integer) value).intValue());
+ }
break;
}
}
@@ -778,7 +813,9 @@ final class FieldSet<FieldDescriptorType extends
final int number, final Object value) {
int tagSize = CodedOutputStream.computeTagSize(number);
if (type == WireFormat.FieldType.GROUP) {
- tagSize *= 2;
+ // Only count the end group tag for proto2 messages as for proto1 the end
+ // group tag will be counted as a part of getSerializedSize().
+ tagSize *= 2;
}
return tagSize + computeElementSizeNoTag(type, value);
}
@@ -808,7 +845,12 @@ final class FieldSet<FieldDescriptorType extends
case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value);
case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value);
case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value);
- case BYTES : return CodedOutputStream.computeBytesSizeNoTag ((ByteString )value);
+ case BYTES :
+ if (value instanceof ByteString) {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ } else {
+ return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value);
+ }
case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value);
case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value);
case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value);
@@ -823,8 +865,12 @@ final class FieldSet<FieldDescriptorType extends
}
case ENUM:
- return CodedOutputStream.computeEnumSizeNoTag(
- ((Internal.EnumLite) value).getNumber());
+ if (value instanceof Internal.EnumLite) {
+ return CodedOutputStream.computeEnumSizeNoTag(
+ ((Internal.EnumLite) value).getNumber());
+ } else {
+ return CodedOutputStream.computeEnumSizeNoTag((Integer) value);
+ }
}
throw new RuntimeException(
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 0c15ca84..b7cf2694 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -33,6 +33,8 @@ 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.io.ObjectStreamException;
@@ -71,7 +73,7 @@ public abstract class GeneratedMessage extends AbstractMessage
protected GeneratedMessage(Builder<?> builder) {
}
- public Parser<? extends Message> getParserForType() {
+ public Parser<? extends GeneratedMessage> getParserForType() {
throw new UnsupportedOperationException(
"This is supposed to be overridden by subclasses.");
}
@@ -154,6 +156,16 @@ public abstract class GeneratedMessage extends AbstractMessage
}
//@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);
}
@@ -193,6 +205,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return unknownFields.mergeFieldFrom(tag, input);
}
+
/**
* Used by parsing constructors in generated classes.
*/
@@ -345,6 +358,16 @@ public abstract class GeneratedMessage extends AbstractMessage
}
//@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);
}
@@ -374,6 +397,12 @@ public abstract class GeneratedMessage extends AbstractMessage
}
//@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 internalGetFieldAccessorTable().getField(field)
.getRepeatedCount(this);
@@ -507,21 +536,24 @@ public abstract class GeneratedMessage extends AbstractMessage
public interface ExtendableMessageOrBuilder<
MessageType extends ExtendableMessage> extends MessageOrBuilder {
+ // Re-define for return type covariance.
+ Message getDefaultInstanceForType();
/** Check if a singular extension is present. */
<Type> boolean hasExtension(
- GeneratedExtension<MessageType, Type> extension);
+ Extension<MessageType, Type> extension);
/** Get the number of elements in a repeated extension. */
<Type> int getExtensionCount(
- GeneratedExtension<MessageType, List<Type>> extension);
+ Extension<MessageType, List<Type>> extension);
/** Get the value of an extension. */
- <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension);
+ <Type> Type getExtension(
+ Extension<MessageType, Type> extension);
/** Get one element of a repeated extension. */
<Type> Type getExtension(
- GeneratedExtension<MessageType, List<Type>> extension,
+ Extension<MessageType, List<Type>> extension,
int index);
}
@@ -578,7 +610,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
private void verifyExtensionContainingType(
- final GeneratedExtension<MessageType, ?> extension) {
+ final Extension<MessageType, ?> extension) {
if (extension.getDescriptor().getContainingType() !=
getDescriptorForType()) {
// This can only happen if someone uses unchecked operations.
@@ -593,7 +625,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Check if a singular extension is present. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> boolean hasExtension(
- final GeneratedExtension<MessageType, Type> extension) {
+ final Extension<MessageType, Type> extension) {
verifyExtensionContainingType(extension);
return extensions.hasField(extension.getDescriptor());
}
@@ -601,7 +633,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Get the number of elements in a repeated extension. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> int getExtensionCount(
- final GeneratedExtension<MessageType, List<Type>> extension) {
+ final Extension<MessageType, List<Type>> extension) {
verifyExtensionContainingType(extension);
final FieldDescriptor descriptor = extension.getDescriptor();
return extensions.getRepeatedFieldCount(descriptor);
@@ -611,7 +643,7 @@ public abstract class GeneratedMessage extends AbstractMessage
//@Override (Java 1.6 override semantics, but we must support 1.5)
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- final GeneratedExtension<MessageType, Type> extension) {
+ final Extension<MessageType, Type> extension) {
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
final Object value = extensions.getField(descriptor);
@@ -634,7 +666,7 @@ public abstract class GeneratedMessage extends AbstractMessage
//@Override (Java 1.6 override semantics, but we must support 1.5)
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- final GeneratedExtension<MessageType, List<Type>> extension,
+ final Extension<MessageType, List<Type>> extension,
final int index) {
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
@@ -658,11 +690,12 @@ public abstract class GeneratedMessage extends AbstractMessage
UnknownFieldSet.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
- return AbstractMessage.Builder.mergeFieldFrom(
- input, unknownFields, extensionRegistry, getDescriptorForType(),
- null, extensions, tag);
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.ExtensionAdapter(extensions), tag);
}
+
/**
* Used by parsing constructors in generated classes.
*/
@@ -868,6 +901,11 @@ public abstract class GeneratedMessage extends AbstractMessage
super(parent);
}
+ // For immutable message conversion.
+ void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) {
+ this.extensions = extensions;
+ }
+
@Override
public BuilderType clear() {
extensions = FieldSet.emptySet();
@@ -890,7 +928,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
private void verifyExtensionContainingType(
- final GeneratedExtension<MessageType, ?> extension) {
+ final Extension<MessageType, ?> extension) {
if (extension.getDescriptor().getContainingType() !=
getDescriptorForType()) {
// This can only happen if someone uses unchecked operations.
@@ -905,7 +943,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Check if a singular extension is present. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> boolean hasExtension(
- final GeneratedExtension<MessageType, Type> extension) {
+ final Extension<MessageType, Type> extension) {
verifyExtensionContainingType(extension);
return extensions.hasField(extension.getDescriptor());
}
@@ -913,7 +951,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Get the number of elements in a repeated extension. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> int getExtensionCount(
- final GeneratedExtension<MessageType, List<Type>> extension) {
+ final Extension<MessageType, List<Type>> extension) {
verifyExtensionContainingType(extension);
final FieldDescriptor descriptor = extension.getDescriptor();
return extensions.getRepeatedFieldCount(descriptor);
@@ -922,7 +960,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Get the value of an extension. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> Type getExtension(
- final GeneratedExtension<MessageType, Type> extension) {
+ final Extension<MessageType, Type> extension) {
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
final Object value = extensions.getField(descriptor);
@@ -944,7 +982,7 @@ 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)
public final <Type> Type getExtension(
- final GeneratedExtension<MessageType, List<Type>> extension,
+ final Extension<MessageType, List<Type>> extension,
final int index) {
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
@@ -954,7 +992,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Set the value of an extension. */
public final <Type> BuilderType setExtension(
- final GeneratedExtension<MessageType, Type> extension,
+ final Extension<MessageType, Type> extension,
final Type value) {
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
@@ -966,7 +1004,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Set the value of one element of a repeated extension. */
public final <Type> BuilderType setExtension(
- final GeneratedExtension<MessageType, List<Type>> extension,
+ final Extension<MessageType, List<Type>> extension,
final int index, final Type value) {
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
@@ -980,7 +1018,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Append a value to a repeated extension. */
public final <Type> BuilderType addExtension(
- final GeneratedExtension<MessageType, List<Type>> extension,
+ final Extension<MessageType, List<Type>> extension,
final Type value) {
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
@@ -993,7 +1031,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Clear an extension. */
public final <Type> BuilderType clearExtension(
- final GeneratedExtension<MessageType, ?> extension) {
+ final Extension<MessageType, ?> extension) {
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
extensions.clearField(extension.getDescriptor());
@@ -1030,9 +1068,9 @@ public abstract class GeneratedMessage extends AbstractMessage
final UnknownFieldSet.Builder unknownFields,
final ExtensionRegistryLite extensionRegistry,
final int tag) throws IOException {
- return AbstractMessage.Builder.mergeFieldFrom(
- input, unknownFields, extensionRegistry, getDescriptorForType(),
- this, null, tag);
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.BuilderAdapter(this), tag);
}
// ---------------------------------------------------------------
@@ -1172,7 +1210,7 @@ public abstract class GeneratedMessage extends AbstractMessage
* 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.
*/
- private static interface ExtensionDescriptorRetriever {
+ static interface ExtensionDescriptorRetriever {
FieldDescriptor getDescriptor();
}
@@ -1187,15 +1225,16 @@ public abstract class GeneratedMessage extends AbstractMessage
// the outer class's descriptor, from which the extension descriptor is
// obtained.
return new GeneratedExtension<ContainingType, Type>(
- new ExtensionDescriptorRetriever() {
+ new CachedDescriptorRetriever() {
//@Override (Java 1.6 override semantics, but we must support 1.5)
- public FieldDescriptor getDescriptor() {
+ public FieldDescriptor loadDescriptor() {
return scope.getDescriptorForType().getExtensions()
.get(descriptorIndex);
}
},
singularType,
- defaultInstance);
+ defaultInstance,
+ Extension.ExtensionType.IMMUTABLE);
}
/** For use by generated code only. */
@@ -1209,7 +1248,87 @@ public abstract class GeneratedMessage extends AbstractMessage
return new GeneratedExtension<ContainingType, Type>(
null, // ExtensionDescriptorRetriever is initialized in internalInit();
singularType,
- defaultInstance);
+ 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 <ContainingType extends Message, Type>
+ GeneratedExtension<ContainingType, Type>
+ 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<ContainingType, Type>(
+ 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 <ContainingType extends Message, Type>
+ GeneratedExtension<ContainingType, Type>
+ 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<ContainingType, Type>(
+ 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);
}
/**
@@ -1237,8 +1356,9 @@ 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<ContainingType, Type> {
// TODO(kenton): Find ways to avoid using Java reflection within this
// class. Also try to avoid suppressing unchecked warnings.
@@ -1254,9 +1374,10 @@ public abstract class GeneratedMessage extends AbstractMessage
// 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.
- private GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever,
- Class singularType,
- Message messageDefaultInstance) {
+ GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever,
+ Class singularType,
+ Message messageDefaultInstance,
+ ExtensionType extensionType) {
if (Message.class.isAssignableFrom(singularType) &&
!singularType.isInstance(messageDefaultInstance)) {
throw new IllegalArgumentException(
@@ -1275,6 +1396,7 @@ public abstract class GeneratedMessage extends AbstractMessage
this.enumValueOf = null;
this.enumGetValueDescriptor = null;
}
+ this.extensionType = extensionType;
}
/** For use by generated code only. */
@@ -1295,6 +1417,7 @@ public abstract class GeneratedMessage extends AbstractMessage
private final Message messageDefaultInstance;
private final Method enumValueOf;
private final Method enumGetValueDescriptor;
+ private final ExtensionType extensionType;
public FieldDescriptor getDescriptor() {
if (descriptorRetriever == null) {
@@ -1312,14 +1435,19 @@ public abstract class GeneratedMessage extends AbstractMessage
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 ||
@@ -1342,21 +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 (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);
@@ -1371,8 +1494,9 @@ 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) {
@@ -1394,7 +1518,8 @@ 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:
@@ -1403,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());
+ }
}
// =================================================================
@@ -1477,6 +1630,7 @@ public abstract class GeneratedMessage extends AbstractMessage
this.descriptor = descriptor;
this.camelCaseNames = camelCaseNames;
fields = new FieldAccessor[descriptor.getFields().size()];
+ oneofs = new OneofAccessor[descriptor.getOneofs().size()];
initialized = false;
}
@@ -1493,8 +1647,14 @@ public abstract class GeneratedMessage extends AbstractMessage
if (initialized) { return this; }
synchronized (this) {
if (initialized) { return this; }
- for (int i = 0; i < fields.length; i++) {
+ 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()];
+ }
if (field.isRepeated()) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
fields[i] = new RepeatedMessageFieldAccessor(
@@ -1509,16 +1669,26 @@ public abstract class GeneratedMessage extends AbstractMessage
} else {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
fields[i] = new SingularMessageFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
} else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
fields[i] = new SingularEnumFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
} else {
fields[i] = new SingularFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
+ 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;
@@ -1528,6 +1698,7 @@ public abstract class GeneratedMessage extends AbstractMessage
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. */
@@ -1544,6 +1715,15 @@ 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.
@@ -1566,22 +1746,89 @@ public abstract class GeneratedMessage extends AbstractMessage
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<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> 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;
+ }
+
// ---------------------------------------------------------------
private static class SingularFieldAccessor implements FieldAccessor {
SingularFieldAccessor(
final FieldDescriptor descriptor, final String camelCaseName,
final Class<? extends GeneratedMessage> messageClass,
- final Class<? extends Builder> builderClass) {
+ final Class<? extends Builder> 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 =
- getMethodOrDie(builderClass, "has" + camelCaseName);
+ 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
@@ -1594,6 +1841,19 @@ public abstract class GeneratedMessage extends AbstractMessage
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);
@@ -1623,9 +1883,21 @@ 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) {
@@ -1751,8 +2023,9 @@ public abstract class GeneratedMessage extends AbstractMessage
SingularEnumFieldAccessor(
final FieldDescriptor descriptor, final String camelCaseName,
final Class<? extends GeneratedMessage> messageClass,
- final Class<? extends Builder> builderClass) {
- super(descriptor, camelCaseName, messageClass, builderClass);
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
valueOfMethod = getMethodOrDie(type, "valueOf",
EnumValueDescriptor.class);
@@ -1847,8 +2120,9 @@ public abstract class GeneratedMessage extends AbstractMessage
SingularMessageFieldAccessor(
final FieldDescriptor descriptor, final String camelCaseName,
final Class<? extends GeneratedMessage> messageClass,
- final Class<? extends Builder> builderClass) {
- super(descriptor, camelCaseName, messageClass, builderClass);
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
newBuilderMethod = getMethodOrDie(type, "newBuilder");
getBuilderMethodBuilder =
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 437e3412..8c70505f 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -35,6 +35,7 @@ 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;
@@ -66,9 +67,10 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
*/
protected boolean parseUnknownField(
CodedInputStream input,
+ CodedOutputStream unknownFieldsCodedOutput,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
- return input.skipField(tag);
+ return input.skipField(tag, unknownFieldsCodedOutput);
}
/**
@@ -86,6 +88,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
//@Override (Java 1.6 override semantics, but we must support 1.5)
public BuilderType clear() {
+ unknownFields = ByteString.EMPTY;
return (BuilderType) this;
}
@@ -110,12 +113,25 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
*/
protected boolean parseUnknownField(
CodedInputStream input,
+ CodedOutputStream unknownFieldsCodedOutput,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
- return input.skipField(tag);
+ 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
@@ -197,7 +213,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
if (value == null) {
return extension.defaultValue;
} else {
- return (Type) value;
+ return (Type) extension.fromFieldSetType(value);
}
}
@@ -208,7 +224,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
final GeneratedExtension<MessageType, List<Type>> 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. */
@@ -223,16 +240,19 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
@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.
*/
@@ -314,6 +334,11 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
private boolean extensionsIsMutable;
+ // For immutable message conversion.
+ void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) {
+ this.extensions = extensions;
+ }
+
@Override
public BuilderType clear() {
extensions.clear();
@@ -375,7 +400,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
if (value == null) {
return extension.defaultValue;
} else {
- return (Type) value;
+ return (Type) extension.fromFieldSetType(value);
}
}
@@ -386,7 +411,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
final GeneratedExtension<MessageType, List<Type>> extension,
final int index) {
verifyExtensionContainingType(extension);
- return (Type) extensions.getRepeatedField(extension.descriptor, index);
+ return (Type) extension.singularFromFieldSetType(
+ extensions.getRepeatedField(extension.descriptor, index));
}
// This is implemented here only to work around an apparent bug in the
@@ -404,7 +430,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
final Type value) {
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
- extensions.setField(extension.descriptor, value);
+ extensions.setField(extension.descriptor,
+ extension.toFieldSetType(value));
return (BuilderType) this;
}
@@ -414,7 +441,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
final int index, final Type value) {
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
- extensions.setRepeatedField(extension.descriptor, index, value);
+ extensions.setRepeatedField(extension.descriptor, index,
+ extension.singularToFieldSetType(value));
return (BuilderType) this;
}
@@ -424,7 +452,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
final Type value) {
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
- extensions.addRepeatedField(extension.descriptor, value);
+ extensions.addRepeatedField(extension.descriptor,
+ extension.singularToFieldSetType(value));
return (BuilderType) this;
}
@@ -449,6 +478,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
@Override
protected boolean parseUnknownField(
CodedInputStream input,
+ CodedOutputStream unknownFieldsCodedOutput,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
ensureExtensionsIsMutable();
@@ -456,6 +486,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
extensions,
getDefaultInstanceForType(),
input,
+ unknownFieldsCodedOutput,
extensionRegistry,
tag);
}
@@ -477,6 +508,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
FieldSet<ExtensionDescriptor> extensions,
MessageType defaultInstance,
CodedInputStream input,
+ CodedOutputStream unknownFieldsCodedOutput,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
int wireType = WireFormat.getTagWireType(tag);
@@ -505,7 +537,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
}
if (unknown) { // Unknown field or wrong wire type. Skip.
- return input.skipField(tag);
+ return input.skipField(tag, unknownFieldsCodedOutput);
}
if (packed) {
@@ -521,13 +553,15 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
// enum, drop it (don't even add it to unknownFields).
return true;
}
- extensions.addRepeatedField(extension.descriptor, value);
+ extensions.addRepeatedField(extension.descriptor,
+ extension.singularToFieldSetType(value));
}
} else {
while (input.getBytesUntilLimit() > 0) {
Object value =
- FieldSet.readPrimitiveField(input,
- extension.descriptor.getLiteType());
+ FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType(),
+ /*checkUtf8=*/ false);
extensions.addRepeatedField(extension.descriptor, value);
}
}
@@ -545,7 +579,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
}
}
if (subBuilder == null) {
- subBuilder = extension.messageDefaultInstance.newBuilderForType();
+ subBuilder = extension.getMessageDefaultInstance()
+ .newBuilderForType();
}
if (extension.descriptor.getLiteType() ==
WireFormat.FieldType.GROUP) {
@@ -562,21 +597,26 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
value = extension.descriptor.getEnumType()
.findValueByNumber(rawValue);
// If the number isn't recognized as a valid value for this enum,
- // drop it.
+ // 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());
+ extension.descriptor.getLiteType(),
+ /*checkUtf8=*/ false);
break;
}
if (extension.descriptor.isRepeated()) {
- extensions.addRepeatedField(extension.descriptor, value);
+ extensions.addRepeatedField(extension.descriptor,
+ extension.singularToFieldSetType(value));
} else {
- extensions.setField(extension.descriptor, value);
+ extensions.setField(extension.descriptor,
+ extension.singularToFieldSetType(value));
}
}
@@ -594,14 +634,16 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
final MessageLite messageDefaultInstance,
final Internal.EnumLiteMap<?> enumTypeMap,
final int number,
- final WireFormat.FieldType type) {
+ final WireFormat.FieldType type,
+ final Class singularType) {
return new GeneratedExtension<ContainingType, Type>(
containingTypeDefaultInstance,
defaultValue,
messageDefaultInstance,
new ExtensionDescriptor(enumTypeMap, number, type,
false /* isRepeated */,
- false /* isPacked */));
+ false /* isPacked */),
+ singularType);
}
/** For use by generated code only. */
@@ -613,7 +655,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
final Internal.EnumLiteMap<?> enumTypeMap,
final int number,
final WireFormat.FieldType type,
- final boolean isPacked) {
+ final boolean isPacked,
+ final Class singularType) {
@SuppressWarnings("unchecked") // Subclasses ensure Type is a List
Type emptyList = (Type) Collections.emptyList();
return new GeneratedExtension<ContainingType, Type>(
@@ -621,13 +664,14 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
emptyList,
messageDefaultInstance,
new ExtensionDescriptor(
- enumTypeMap, number, type, true /* isRepeated */, isPacked));
+ enumTypeMap, number, type, true /* isRepeated */, isPacked),
+ singularType);
}
- private static final class ExtensionDescriptor
+ static final class ExtensionDescriptor
implements FieldSet.FieldDescriptorLite<
ExtensionDescriptor> {
- private ExtensionDescriptor(
+ ExtensionDescriptor(
final Internal.EnumLiteMap<?> enumTypeMap,
final int number,
final WireFormat.FieldType type,
@@ -640,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;
@@ -676,25 +720,70 @@ 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> {
- private GeneratedExtension(
+ /**
+ * 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) {
@@ -710,12 +799,24 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
this.defaultValue = defaultValue;
this.messageDefaultInstance = messageDefaultInstance;
this.descriptor = descriptor;
+
+ // 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 final ContainingType containingTypeDefaultInstance;
- private final Type defaultValue;
- private final MessageLite messageDefaultInstance;
- private final 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.
@@ -729,13 +830,64 @@ 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;
+ }
+ }
}
/**
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
index 81af2583..5c234c54 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,51 @@ 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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
@@ -130,6 +179,35 @@ public class Internal {
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.
@@ -150,4 +228,164 @@ public class Internal {
public interface EnumLiteMap<T extends EnumLite> {
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.
+ * <p>
+ * 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<? extends EnumLite> 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<byte[]> a, List<byte[]> 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<byte[]> 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<ByteBuffer> a, List<ByteBuffer> 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<ByteBuffer> 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 72d7ff7d..ae320beb 100644
--- a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -111,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
index c4f9201c..0cb65d6b 100644
--- a/java/src/main/java/com/google/protobuf/LazyField.java
+++ b/java/src/main/java/com/google/protobuf/LazyField.java
@@ -30,7 +30,6 @@
package com.google.protobuf;
-import java.io.IOException;
import java.util.Iterator;
import java.util.Map.Entry;
@@ -38,110 +37,49 @@ 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.
*
- * LazyField is thread-compatible e.g. concurrent read are safe, however,
- * synchronizations are needed under read/write situations.
- *
- * Now LazyField is only used to lazily load MessageSet.
- * TODO(xiangl): Use LazyField to lazily load all messages.
+ * 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)
*/
-class LazyField {
-
- final private MessageLite defaultInstance;
- final private ExtensionRegistryLite extensionRegistry;
+public class LazyField extends LazyFieldLite {
- // Mutable because it is initialized lazily.
- private ByteString bytes;
- private volatile MessageLite value;
- private volatile boolean isDirty = false;
+ /**
+ * 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) {
- this.defaultInstance = defaultInstance;
- this.extensionRegistry = extensionRegistry;
- this.bytes = bytes;
- }
+ super(extensionRegistry, bytes);
- public MessageLite getValue() {
- ensureInitialized();
- 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;
+ this.defaultInstance = defaultInstance;
}
- /**
- * 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();
+ @Override
+ public boolean containsDefaultInstance() {
+ return super.containsDefaultInstance() || value == defaultInstance;
}
- public ByteString toByteString() {
- if (!isDirty) {
- return bytes;
- }
- synchronized (this) {
- if (!isDirty) {
- return bytes;
- }
- bytes = value.toByteString();
- isDirty = false;
- return bytes;
- }
+ public MessageLite getValue() {
+ return getValue(defaultInstance);
}
@Override
public int hashCode() {
- ensureInitialized();
- return value.hashCode();
+ return getValue().hashCode();
}
@Override
public boolean equals(Object obj) {
- ensureInitialized();
- return value.equals(obj);
+ return getValue().equals(obj);
}
@Override
public String toString() {
- ensureInitialized();
- return value.toString();
- }
-
- private void ensureInitialized() {
- if (value != null) {
- return;
- }
- synchronized (this) {
- if (value != null) {
- return;
- }
- try {
- if (bytes != null) {
- value = defaultInstance.getParserForType()
- .parseFrom(bytes, extensionRegistry);
- }
- } catch (IOException e) {
- // TODO(xiangl): Refactory the API to support the exception thrown from
- // lazily load messages.
- }
- }
+ return getValue().toString();
}
// ====================================================
@@ -157,10 +95,12 @@ class LazyField {
this.entry = entry;
}
+ // @Override
public K getKey() {
return entry.getKey();
}
+ // @Override
public Object getValue() {
LazyField field = entry.getValue();
if (field == null) {
@@ -173,6 +113,7 @@ class LazyField {
return entry.getValue();
}
+ // @Override
public Object setValue(Object value) {
if (!(value instanceof MessageLite)) {
throw new IllegalArgumentException(
@@ -190,11 +131,13 @@ class LazyField {
this.iterator = iterator;
}
+ // @Override
public boolean hasNext() {
return iterator.hasNext();
}
@SuppressWarnings("unchecked")
+ // @Override
public Entry<K, Object> next() {
Entry<K, ?> entry = iterator.next();
if (entry.getValue() instanceof LazyField) {
@@ -203,6 +146,7 @@ class LazyField {
return (Entry<K, Object>) entry;
}
+ // @Override
public void remove() {
iterator.remove();
}
diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
index a5f0bd90..5599c7fb 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -30,6 +30,7 @@
package com.google.protobuf;
+import java.util.Arrays;
import java.util.List;
import java.util.AbstractList;
import java.util.ArrayList;
@@ -39,9 +40,9 @@ import java.util.RandomAccess;
/**
* An implementation of {@link LazyStringList} that wraps an ArrayList. Each
- * element is either a ByteString or a String. 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.
+ * 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.
* <p>
* <strong>Note that this implementation is not synchronized.</strong>
* If multiple threads access an <tt>ArrayList</tt> instance concurrently,
@@ -64,8 +65,8 @@ import java.util.RandomAccess;
public class LazyStringArrayList extends AbstractList<String>
implements LazyStringList, RandomAccess {
- public final static LazyStringList EMPTY = new UnmodifiableLazyStringList(
- new LazyStringArrayList());
+ public static final LazyStringList EMPTY =
+ new LazyStringArrayList().getUnmodifiableView();
private final List<Object> list;
@@ -87,13 +88,20 @@ public class LazyStringArrayList extends AbstractList<String>
Object o = list.get(index);
if (o instanceof String) {
return (String) o;
- } else {
+ } 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;
}
}
@@ -134,6 +142,20 @@ public class LazyStringArrayList extends AbstractList<String>
return ret;
}
+ // @Override
+ public boolean addAllByteString(Collection<? extends ByteString> values) {
+ boolean ret = list.addAll(values);
+ modCount++;
+ return ret;
+ }
+
+ // @Override
+ public boolean addAllByteArray(Collection<byte[]> c) {
+ boolean ret = list.addAll(c);
+ modCount++;
+ return ret;
+ }
+
@Override
public String remove(int index) {
Object o = list.remove(index);
@@ -141,6 +163,7 @@ public class LazyStringArrayList extends AbstractList<String>
return asString(o);
}
+ @Override
public void clear() {
list.clear();
modCount++;
@@ -151,28 +174,194 @@ public class LazyStringArrayList extends AbstractList<String>
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);
- if (o instanceof String) {
- ByteString b = ByteString.copyFromUtf8((String) o);
+ 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;
- } else {
- return (ByteString) o;
}
+ 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 String asString(Object o) {
+
+ private static String asString(Object o) {
if (o instanceof String) {
return (String) o;
- } else {
+ } 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<byte[]>
+ implements RandomAccess {
+ private final List<Object> list;
+
+ ByteArrayListView(List<Object> 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<byte[]> asByteArrayList() {
+ return new ByteArrayListView(list);
+ }
+
+ private static class ByteStringListView extends AbstractList<ByteString>
+ implements RandomAccess {
+ private final List<Object> list;
+
+ ByteStringListView(List<Object> 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<ByteString> 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
index 630932fe..7418c925 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringList.java
@@ -30,25 +30,22 @@
package com.google.protobuf;
+import java.util.Collection;
import java.util.List;
/**
* An interface extending {@code List<String>} that also provides access to the
- * items of the list as UTF8-encoded ByteString 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
+ * 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 is already cached.
- * <p>
- * This only adds additional methods that are required for the use in the
- * protocol buffer code in order to be able successfully round trip byte arrays
- * through parsing and serialization without conversion to strings. It's not
- * attempting to support the functionality of say {@code List<ByteString>}, hence
- * why only these two very specific methods are added.
+ * 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 List<String> {
+public interface LazyStringList extends ProtocolStringList {
/**
* Returns the element at the specified position in this list as a ByteString.
@@ -59,6 +56,16 @@ public interface LazyStringList extends List<String> {
* ({@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
@@ -71,11 +78,86 @@ public interface LazyStringList extends List<String> {
void add(ByteString element);
/**
- * Returns an unmodifiable List of the underlying elements, each of
- * which is either a {@code String} or its equivalent UTF-8 encoded
- * {@code ByteString}. It is an error for the caller to modify the returned
+ * 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 <tt>add</tt> 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 <tt>set</tt> 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 <tt>set</tt> 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 <tt>addAllByteString</tt>
+ * operation is not supported by this list
+ */
+ boolean addAllByteString(Collection<? extends ByteString> 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 <tt>addAllByteArray</tt>
+ * operation is not supported by this list
+ */
+ boolean addAllByteArray(Collection<byte[]> 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<byte[]> 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
index 93c53dce..543da52b 100644
--- a/java/src/main/java/com/google/protobuf/LiteralByteString.java
+++ b/java/src/main/java/com/google/protobuf/LiteralByteString.java
@@ -143,6 +143,13 @@ class LiteralByteString extends ByteString {
}
@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);
@@ -261,13 +268,20 @@ class LiteralByteString extends ByteString {
@Override
protected int partialHash(int h, int offset, int length) {
- byte[] thisBytes = bytes;
- for (int i = getOffsetIntoBytes() + offset, limit = i + length; i < limit;
- i++) {
- h = h * 31 + thisBytes[i];
+ 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
@@ -282,8 +296,7 @@ class LiteralByteString extends ByteString {
public CodedInputStream newCodedInput() {
// We trust CodedInputStream not to modify the bytes, or to give anyone
// else access to them.
- return CodedInputStream
- .newInstance(bytes, getOffsetIntoBytes(), size()); // No copy
+ return CodedInputStream.newInstance(this);
}
// =================================================================
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index 2b881413..19fc3b42 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -53,6 +53,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
Parser<? extends Message> getParserForType();
+
// -----------------------------------------------------------------
// Comparison and hashing
@@ -180,6 +181,12 @@ public interface Message extends MessageLite, MessageOrBuilder {
Builder clearField(Descriptors.FieldDescriptor field);
/**
+ * Clears the oneof. This is exactly equivalent to calling the generated
+ * "clear" accessor method corresponding to the oneof.
+ */
+ Builder clearOneof(Descriptors.OneofDescriptor oneof);
+
+ /**
* 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
diff --git a/java/src/main/java/com/google/protobuf/MessageLite.java b/java/src/main/java/com/google/protobuf/MessageLite.java
index e5b9a47b..86be04ed 100644
--- a/java/src/main/java/com/google/protobuf/MessageLite.java
+++ b/java/src/main/java/com/google/protobuf/MessageLite.java
@@ -128,6 +128,7 @@ public interface MessageLite extends MessageLiteOrBuilder {
*/
void writeDelimitedTo(OutputStream output) throws IOException;
+
// =================================================================
// Builders
diff --git a/java/src/main/java/com/google/protobuf/MessageOrBuilder.java b/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
index bf62d45e..886f5b44 100644
--- a/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
+++ b/java/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -76,7 +76,7 @@ public interface MessageOrBuilder extends MessageLiteOrBuilder {
* 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
+ * 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
@@ -89,6 +89,20 @@ public interface MessageOrBuilder extends MessageLiteOrBuilder {
Map<Descriptors.FieldDescriptor, Object> 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
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 00000000..021b9d58
--- /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<FieldDescriptor, Object> fields = message.getAllFields();
+ if (alwaysWriteRequiredFields) {
+ fields = new TreeMap<FieldDescriptor, Object>(fields);
+ for (final FieldDescriptor field :
+ message.getDescriptorForType().getFields()) {
+ if (field.isRequired() && !fields.containsKey(field)) {
+ fields.put(field, message.getField(field));
+ }
+ }
+ }
+ for (final Map.Entry<Descriptors.FieldDescriptor, Object> 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<Descriptors.FieldDescriptor, Object> 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<String> 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<Descriptors.FieldDescriptor, Object> 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<Message>) 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<String> results) {
+ for (final Descriptors.FieldDescriptor field :
+ message.getDescriptorForType().getFields()) {
+ if (field.isRequired() && !message.hasField(field)) {
+ results.add(prefix + field.getName());
+ }
+ }
+
+ for (final Map.Entry<Descriptors.FieldDescriptor, Object> 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<String> findMissingFields(
+ final MessageOrBuilder message) {
+ final List<String> results = new ArrayList<String>();
+ 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<Descriptors.FieldDescriptor> extensions;
+
+ ExtensionAdapter(FieldSet<Descriptors.FieldDescriptor> 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
index 7d8e8217..5fe969b1 100644
--- a/java/src/main/java/com/google/protobuf/Parser.java
+++ b/java/src/main/java/com/google/protobuf/Parser.java
@@ -35,6 +35,8 @@ 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<MessageType> {
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 00000000..41a1f90b
--- /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<String>} 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<String> {
+
+ /** Returns a view of the data as a list of ByteStrings. */
+ List<ByteString> asByteStringList();
+
+}
diff --git a/java/src/main/java/com/google/protobuf/RopeByteString.java b/java/src/main/java/com/google/protobuf/RopeByteString.java
index 46997823..a011df45 100644
--- a/java/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/src/main/java/com/google/protobuf/RopeByteString.java
@@ -402,6 +402,20 @@ class RopeByteString extends ByteString {
}
@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);
diff --git a/java/src/main/java/com/google/protobuf/RpcUtil.java b/java/src/main/java/com/google/protobuf/RpcUtil.java
index b1b959a8..856f0a51 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 extends Message> 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/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index ed462899..97da09bb 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -31,17 +31,18 @@
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;
@@ -55,6 +56,9 @@ import java.util.regex.Pattern;
public final class 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);
@@ -66,8 +70,9 @@ public final class TextFormat {
* 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 MessageOrBuilder message, final Appendable output)
- throws IOException {
+ public static void print(
+ final MessageOrBuilder message, final Appendable output)
+ throws IOException {
DEFAULT_PRINTER.print(message, new TextGenerator(output));
}
@@ -266,7 +271,8 @@ public final class TextFormat {
return this;
}
- private void print(final MessageOrBuilder message, final TextGenerator generator)
+ private void print(
+ final MessageOrBuilder message, final TextGenerator generator)
throws IOException {
for (Map.Entry<FieldDescriptor, Object> field
: message.getAllFields().entrySet()) {
@@ -385,13 +391,17 @@ public final class TextFormat {
generator.print("\"");
generator.print(escapeNonAscii ?
escapeText((String) value) :
- (String) value);
+ escapeDoubleQuotesAndBackslashes((String) value));
generator.print("\"");
break;
case BYTES:
generator.print("\"");
- generator.print(escapeBytes((ByteString) value));
+ if (value instanceof ByteString) {
+ generator.print(escapeBytes((ByteString) value));
+ } else {
+ generator.print(escapeBytes((byte[]) value));
+ }
generator.print("\"");
break;
@@ -455,16 +465,16 @@ public final class TextFormat {
}
/** 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 {
@@ -518,17 +528,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) {
@@ -705,6 +714,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}.
*/
@@ -717,7 +734,8 @@ public final class TextFormat {
(c == '_') || (c == '.')) {
// OK
} else {
- throw parseException("Expected identifier.");
+ throw parseException(
+ "Expected identifier. Found '" + currentToken + "'");
}
}
@@ -727,6 +745,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}.
*/
@@ -769,6 +800,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}.
*/
@@ -783,6 +827,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}.
*/
@@ -808,6 +865,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}.
*/
@@ -833,6 +903,19 @@ 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}.
*/
@@ -861,6 +944,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}.
@@ -880,7 +976,8 @@ public final class TextFormat {
* multiple adjacent tokens which are automatically concatenated, like in
* C or Python.
*/
- private void consumeByteString(List<ByteString> list) throws ParseException {
+ private void consumeByteString(List<ByteString> list)
+ throws ParseException {
final char quote = currentToken.length() > 0 ? currentToken.charAt(0)
: '\0';
if (quote != '\"' && quote != '\'') {
@@ -988,6 +1085,16 @@ public final class TextFormat {
}
}
+ 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}.
@@ -995,7 +1102,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);
}
/**
@@ -1005,7 +1112,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);
}
/**
@@ -1017,35 +1124,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
@@ -1056,187 +1137,481 @@ 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.
+ *
+ * <p>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":
+ * <li>
+ * <ul>"foo: 1 foo: 2"
+ * <ul>"baz: 1 qux: 2"
+ * <ul>merging "foo: 2" into a proto in which foo is already set, or
+ * <ul>merging "qux: 2" into a proto in which baz is already set.
+ * </li>
+ */
+ public enum SingularOverwritePolicy {
+ /** The last value is retained. */
+ ALLOW_SINGULAR_OVERWRITES,
+ /** An error is issued. */
+ FORBID_SINGULAR_OVERWRITES
+ }
+
+ private final boolean allowUnknownFields;
+ private final SingularOverwritePolicy singularOverwritePolicy;
+
+ private Parser(boolean allowUnknownFields,
+ SingularOverwritePolicy singularOverwritePolicy) {
+ this.allowUnknownFields = allowUnknownFields;
+ this.singularOverwritePolicy = singularOverwritePolicy;
+ }
- if (tokenizer.tryConsume("[")) {
- // An extension.
- final StringBuilder name =
- new StringBuilder(tokenizer.consumeIdentifier());
- while (tokenizer.tryConsume(".")) {
- name.append('.');
- name.append(tokenizer.consumeIdentifier());
+ /**
+ * Returns a new instance of {@link Builder}.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * 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;
+
+ /**
+ * Set whether this parser will allow unknown fields. By default, an
+ * exception is thrown if an unknown field is encountered. If this is
+ * set, the parser will only log a warning.
+ *
+ * <p>Use of this parameter is discouraged. See:
+ * https://sites.google.com/a/google.com/protocol-buffers/migration/
+ * proto2-faq#How_do_I_ignore_unknown_fields_w
+ * for more details.
+ */
+ public Builder setAllowUnknownFields(boolean allowUnknownFields) {
+ this.allowUnknownFields = allowUnknownFields;
+ return this;
}
- extension = extensionRegistry.findExtensionByName(name.toString());
+ /**
+ * 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.buildPartial();
+ // 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;
+ }
- } else {
- tokenizer.consume(":");
+ // 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);
+ }
+ }
- switch (field.getType()) {
- case INT32:
- case SINT32:
- case SFIXED32:
- value = tokenizer.consumeInt32();
- 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;
- case INT64:
- case SINT64:
- case SFIXED64:
- value = tokenizer.consumeInt64();
- break;
+ 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);
+ }
}
}
@@ -1246,6 +1621,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
@@ -1254,7 +1634,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);
@@ -1289,6 +1669,39 @@ 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.
@@ -1394,6 +1807,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.
*/
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 45e2e6e4..81432b40 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -91,6 +91,7 @@ public final class UnknownFieldSet implements MessageLite {
}
private Map<Integer, Field> 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
diff --git a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
index 591bca54..6f9905fc 100644
--- a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
+++ b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -31,10 +31,12 @@
package com.google.protobuf;
import java.util.AbstractList;
-import java.util.RandomAccess;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
-import java.util.Iterator;
+import java.util.RandomAccess;
/**
* An implementation of {@link LazyStringList} that wraps another
@@ -72,6 +74,36 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
}
//@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<? extends ByteString> 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<byte[]> element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public ListIterator<String> listIterator(final int index) {
return new ListIterator<String>() {
ListIterator<String> iter = list.listIterator(index);
@@ -145,8 +177,29 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
};
}
+ //@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<byte[]> asByteArrayList() {
+ return Collections.unmodifiableList(list.asByteArrayList());
+ }
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
+ public List<ByteString> 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/test/java/com/google/protobuf/AbstractMessageTest.java b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
index 3d05cb7d..fcbf019d 100644
--- a/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -506,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/ByteStringTest.java b/java/src/test/java/com/google/protobuf/ByteStringTest.java
index 7a1d6823..88d7e779 100644
--- a/java/src/test/java/com/google/protobuf/ByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -35,6 +35,7 @@ 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;
@@ -676,6 +677,21 @@ public class ByteStringTest extends TestCase {
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<ByteString> makeConcretePieces(byte[] referenceBytes) {
List<ByteString> pieces = new ArrayList<ByteString>();
// Starting length should be small enough that we'll do some concatenating by
@@ -689,4 +705,55 @@ public class ByteStringTest extends TestCase {
}
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 00000000..97bf1c7a
--- /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 83f7f8da..3b50e497 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.
@@ -350,7 +390,7 @@ public class CodedInputStreamTest extends TestCase {
// 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.
@@ -437,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);
}
}
@@ -460,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();
@@ -469,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();
@@ -499,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());
@@ -525,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 86255029..da70be42 100644
--- a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -38,6 +38,7 @@ import protobuf_unittest.UnittestProto.TestSparseEnum;
import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
@@ -314,4 +315,87 @@ public class CodedOutputStreamTest extends TestCase {
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/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index 9c310919..30e01493 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -39,6 +39,7 @@ 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;
@@ -53,10 +54,13 @@ 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;
@@ -308,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));
@@ -324,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());
@@ -351,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));
@@ -511,9 +519,35 @@ public class DescriptorsTest extends TestCase {
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();
+ .setName("foo.proto").build();
FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
.setName("boo.proto")
.addDependency("foo.proto")
@@ -645,4 +679,30 @@ public class DescriptorsTest extends TestCase {
"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 990e8ca6..ee3769ce 100644
--- a/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -30,6 +30,9 @@
package com.google.protobuf;
+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;
@@ -241,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 {
@@ -261,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/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index bf9db75b..eb9e6322 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -45,6 +45,9 @@ 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;
@@ -58,6 +61,7 @@ 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;
@@ -69,6 +73,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
/**
@@ -399,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<String> stringIterable = new Iterable<String>() {
+ private boolean called = false;
+ @Override
+ public Iterator<String> 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()
@@ -496,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);
@@ -697,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 =
@@ -795,7 +875,7 @@ 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);
}
@@ -1143,4 +1223,293 @@ public class GeneratedMessageTest extends TestCase {
// 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/LazyFieldLiteTest.java b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
new file mode 100644
index 00000000..33a7297b
--- /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 00000000..5aedc32a
--- /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 00000000..63028db9
--- /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<LazyInnerMessageLite> 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<LazyInnerMessageLite> inners = new ArrayList<LazyInnerMessageLite>();
+ 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
index d500595f..850658ca 100644
--- a/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -67,6 +67,14 @@ public class LazyStringArrayListTest extends TestCase {
list.remove(1);
assertSame(STRING_A, list.get(0));
assertSame(STRING_C, list.get(1));
+
+ List<ByteString> 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() {
@@ -83,6 +91,10 @@ public class LazyStringArrayListTest extends TestCase {
list.remove(1);
assertSame(BYTE_STRING_A, list.getByteString(0));
assertSame(BYTE_STRING_C, list.getByteString(1));
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ assertSame(BYTE_STRING_A, byteStringList.get(0));
+ assertSame(BYTE_STRING_C, byteStringList.get(1));
}
public void testConversionBackAndForth() {
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 00000000..471acbb6
--- /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/ParserTest.java b/java/src/test/java/com/google/protobuf/ParserTest.java
index 396902cf..8cc4693e 100644
--- a/java/src/test/java/com/google/protobuf/ParserTest.java
+++ b/java/src/test/java/com/google/protobuf/ParserTest.java
@@ -33,15 +33,14 @@ package com.google.protobuf;
import com.google.protobuf.UnittestLite.TestAllTypesLite;
import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
import com.google.protobuf.UnittestLite.TestParsingMergeLite;
-import com.google.protobuf.UnittestLite;
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.TestRequired;
import protobuf_unittest.UnittestProto.TestParsingMerge;
+import protobuf_unittest.UnittestProto.TestRequired;
import protobuf_unittest.UnittestProto;
import junit.framework.TestCase;
@@ -84,12 +83,15 @@ public class ParserTest extends TestCase {
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<? extends MessageLite> parser = message.getParserForType();
+
+ Parser<MessageLite> parser =
+ (Parser<MessageLite>) message.getParserForType();
assertMessageEquals(message, parser.parseFrom(data));
assertMessageEquals(message, parser.parseFrom(
generatePaddingArray(data, offset, padding),
@@ -101,7 +103,8 @@ public class ParserTest extends TestCase {
CodedInputStream.newInstance(data)));
}
- private void assertMessageEquals(MessageLite expected, MessageLite actual)
+ private void assertMessageEquals(
+ MessageLite expected, MessageLite actual)
throws Exception {
if (expected instanceof Message) {
assertEquals(expected, actual);
@@ -120,15 +123,17 @@ public class ParserTest extends TestCase {
assertRoundTripEquals(TestUtil.getAllSet());
}
+
public void testParsePartial() throws Exception {
- Parser<TestRequired> parser = TestRequired.PARSER;
+ assertParsePartial(TestRequired.PARSER,
+ TestRequired.newBuilder().setA(1).buildPartial());
+ }
+
+ private <T extends MessageLite> void assertParsePartial(
+ Parser<T> parser, T partialMessage) throws Exception {
final String errorString =
"Should throw exceptions when the parsed message isn't initialized.";
- // TestRequired.b and TestRequired.c are not set.
- TestRequired partialMessage = TestRequired.newBuilder()
- .setA(1).buildPartial();
-
// parsePartialFrom should pass.
byte[] data = partialMessage.toByteArray();
assertEquals(partialMessage, parser.parsePartialFrom(data));
@@ -218,6 +223,7 @@ public class ParserTest extends TestCase {
emptyMessage.toByteString());
}
+
public void testOptimizeForSize() throws Exception {
TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
diff --git a/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
index 382acf0f..84f16947 100644
--- a/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -60,4 +60,37 @@ public class TestBadIdentifiers extends TestCase {
.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 76f5c602..e3cf8a63 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;
@@ -148,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;
@@ -223,6 +233,7 @@ 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;
@@ -469,6 +480,12 @@ public final 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"));
}
// -------------------------------------------------------------------
@@ -718,6 +735,13 @@ public final 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());
}
// -------------------------------------------------------------------
@@ -872,6 +896,11 @@ public final 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());
}
// -------------------------------------------------------------------
@@ -1358,6 +1387,12 @@ public final 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"));
}
// -------------------------------------------------------------------
@@ -1621,6 +1656,10 @@ public final class TestUtil {
assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension));
assertEqualsExactType("425", message.getExtension(defaultCordExtension));
+
+ Assert.assertTrue(message.hasExtension(oneofBytesExtension));
+
+ assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtension));
}
// -------------------------------------------------------------------
@@ -1807,6 +1846,11 @@ public final 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));
}
// -------------------------------------------------------------------
@@ -2133,6 +2177,12 @@ public final 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"));
}
// -------------------------------------------------------------------
@@ -2397,6 +2447,10 @@ public final class TestUtil {
assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite));
assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite));
+
+ Assert.assertTrue(message.hasExtension(oneofBytesExtensionLite));
+
+ assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtensionLite));
}
// -------------------------------------------------------------------
@@ -2562,6 +2616,11 @@ public final 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));
}
// -------------------------------------------------------------------
@@ -2749,6 +2808,82 @@ public final 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;
+ }
+ }
+
// =================================================================
/**
@@ -2915,8 +3050,8 @@ public final 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();
@@ -3078,6 +3213,13 @@ public final 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"));
}
// -------------------------------------------------------------------
@@ -3372,6 +3514,24 @@ public final 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")));
+ }
}
// -------------------------------------------------------------------
@@ -3549,6 +3709,15 @@ public final 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")));
}
@@ -3910,7 +4079,7 @@ public final class TestUtil {
*/
public static ByteString getGoldenMessage() {
if (goldenMessage == null) {
- goldenMessage = readBytesFromFile("golden_message");
+ goldenMessage = readBytesFromFile("golden_message_oneof_implemented");
}
return goldenMessage;
}
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 5323d70e..7cb70021 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
@@ -39,6 +40,7 @@ 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;
@@ -64,7 +66,7 @@ public class TextFormatTest extends TestCase {
+ "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,26 @@ 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 parserAllowingUnknownFields =
+ TextFormat.Parser.newBuilder().setAllowUnknownFields(true).build();
+
+ 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());
@@ -250,8 +272,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)
@@ -371,6 +393,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 {
@@ -407,12 +463,51 @@ public class TextFormatTest extends TestCase {
}
}
+ private void assertParseErrorWithUnknownFields(String error, String text) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ parserAllowingUnknownFields.merge(
+ text, TestUtil.getExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals(error, e.getMessage());
+ }
+ }
+
+ private TestAllTypes assertParseSuccessWithUnknownFields(String text)
+ throws TextFormat.ParseException {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ parserAllowingUnknownFields.merge(
+ text, TestUtil.getExtensionRegistry(), builder);
+ return builder.build();
+ }
+
+ 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",
@@ -469,10 +564,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 >");
}
@@ -762,7 +857,7 @@ public class TextFormatTest extends TestCase {
TextFormat.shortDebugString(makeUnknownFieldSet()));
}
- public void testPrintToUnicodeString() {
+ public void testPrintToUnicodeString() throws Exception {
assertEquals(
"optional_string: \"abc\u3042efg\"\n" +
"optional_bytes: \"\\343\\201\\202\"\n" +
@@ -772,6 +867,49 @@ public class TextFormatTest extends TestCase {
.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() {
@@ -783,4 +921,177 @@ public class TextFormatTest extends TestCase {
.addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
.build()));
}
+
+ public void testParseUnknownFields() throws Exception {
+ assertParseSuccessWithUnknownFields("unknown_field: 12345");
+ assertParseSuccessWithUnknownFields("unknown_field: -12345");
+ assertParseSuccessWithUnknownFields("unknown_field: 1.2345");
+ assertParseSuccessWithUnknownFields("unknown_field: -1.2345");
+ assertParseSuccessWithUnknownFields("unknown_field: 1.2345f");
+ assertParseSuccessWithUnknownFields("unknown_field: -1.2345f");
+ assertParseSuccessWithUnknownFields("unknown_field: inf");
+ assertParseSuccessWithUnknownFields("unknown_field: -inf");
+ assertParseSuccessWithUnknownFields("unknown_field: TYPE_STRING");
+ assertParseSuccessWithUnknownFields("unknown_field: \"string value\"");
+ // Invalid field value
+ assertParseErrorWithUnknownFields(
+ "1:16: Invalid field value: -TYPE_STRING",
+ "unknown_field: -TYPE_STRING");
+ // Two or more unknown fields
+ assertParseSuccessWithUnknownFields("unknown_field1: TYPE_STRING\n" +
+ "unknown_field2: 12345");
+ // Unknown nested message
+ assertParseSuccessWithUnknownFields("unknown_message1: {}\n" +
+ "unknown_message2 {\n" +
+ " unknown_field: 12345\n" +
+ "}\n" +
+ "unknown_message3 <\n" +
+ " unknown_nested_message {\n" +
+ " unknown_field: 12345\n" +
+ " }\n" +
+ ">");
+ // Unmatched delimeters for message body
+ assertParseErrorWithUnknownFields(
+ "1:19: Expected \"}\".", "unknown_message: {>");
+ // Unknown extension
+ assertParseSuccessWithUnknownFields(
+ "[somewhere.unknown_extension1]: 12345\n" +
+ "[somewhere.unknown_extension2] {\n" +
+ " unknown_field: 12345\n" +
+ "}");
+ // Unknown fields between known fields.
+ TestAllTypes expected = TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("string")
+ .setOptionalNestedMessage(NestedMessage.newBuilder()
+ .setBb(2))
+ .build();
+ assertEquals(expected, assertParseSuccessWithUnknownFields(
+ "optional_int32: 1\n" +
+ "unknown_field: 12345\n" +
+ "optional_string: \"string\"\n" +
+ "unknown_message { unknown : 0 }\n" +
+ "optional_nested_message { bb: 2 }"));
+ // Nested unknown extensions.
+ assertParseSuccessWithUnknownFields(
+ "[test.extension1] <\n" +
+ " unknown_nested_message <\n" +
+ " [test.extension2] <\n" +
+ " unknown_field: 12345\n" +
+ " >\n" +
+ " >\n" +
+ ">");
+ assertParseSuccessWithUnknownFields(
+ "[test.extension1] {\n" +
+ " unknown_nested_message {\n" +
+ " [test.extension2] {\n" +
+ " unknown_field: 12345\n" +
+ " }\n" +
+ " }\n" +
+ "}");
+ assertParseSuccessWithUnknownFields(
+ "[test.extension1] <\n" +
+ " some_unknown_fields: <\n" +
+ " unknown_field: 12345\n" +
+ " >\n" +
+ ">");
+ assertParseSuccessWithUnknownFields(
+ "[test.extension1] {\n" +
+ " some_unknown_fields: {\n" +
+ " unknown_field: 12345\n" +
+ " }\n" +
+ "}");
+ }
+
+ 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 ea088b32..d4139d20 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
index ed5d069e..ad4bbf8d 100644
--- a/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
+++ b/java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
@@ -33,6 +33,7 @@ package com.google.protobuf;
import junit.framework.TestCase;
import java.util.Iterator;
+import java.util.List;
import java.util.ListIterator;
/**
@@ -60,6 +61,11 @@ public class UnmodifiableLazyStringListTest extends TestCase {
assertEquals(BYTE_STRING_A, list.getByteString(0));
assertEquals(BYTE_STRING_B, list.getByteString(1));
assertEquals(BYTE_STRING_C, list.getByteString(2));
+
+ List<ByteString> 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() {
@@ -88,6 +94,35 @@ public class UnmodifiableLazyStringListTest extends TestCase {
} catch (UnsupportedOperationException e) {
// expected
}
+ assertEquals(3, list.size());
+
+ List<ByteString> 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() {
@@ -108,6 +143,20 @@ public class UnmodifiableLazyStringListTest extends TestCase {
}
assertEquals(3, count);
+ List<ByteString> byteStringList = list.asByteStringList();
+ Iterator<ByteString> 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() {
@@ -140,6 +189,32 @@ public class UnmodifiableLazyStringListTest extends TestCase {
}
assertEquals(3, count);
+ List<ByteString> byteStringList = list.asByteStringList();
+ ListIterator<ByteString> 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() {
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 94f62134..146029df 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -40,6 +40,8 @@ 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;
@@ -218,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 {
@@ -577,4 +579,28 @@ public class WireFormatTest extends TestCase {
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 00000000..8801db90
--- /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/python/google/protobuf/pyext/python_protobuf.cc b/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto
index 1b1ab5d1..8b18f078 100644
--- a/python/google/protobuf/pyext/python_protobuf.cc
+++ b/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto
@@ -28,36 +28,28 @@
// (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)
+// Author: pbogle@google.com (Phil Bogle)
-#include <google/protobuf/pyext/python_protobuf.h>
-namespace google {
-namespace protobuf {
-namespace python {
+package protobuf_unittest.lite_equals_and_hash;
-static const Message* GetCProtoInsidePyProtoStub(PyObject* msg) {
- return NULL;
-}
-static Message* MutableCProtoInsidePyProtoStub(PyObject* msg) {
- return NULL;
-}
+// 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;
-// This is initialized with a default, stub implementation.
-// If python-google.protobuf.cc is loaded, the function pointer is overridden
-// with a full implementation.
-const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg) =
- GetCProtoInsidePyProtoStub;
-Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg) =
- MutableCProtoInsidePyProtoStub;
+message Foo {
+ optional int32 value = 1;
+ repeated Bar bar = 2;
+}
-const Message* GetCProtoInsidePyProto(PyObject* msg) {
- return GetCProtoInsidePyProtoPtr(msg);
+message Bar {
+ optional string name = 1;
}
-Message* MutableCProtoInsidePyProto(PyObject* msg) {
- return MutableCProtoInsidePyProtoPtr(msg);
+
+message BarPrime {
+ optional string name = 1;
}
-} // namespace python
-} // namespace protobuf
-} // namespace google
+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 9a040145..401e1681 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
@@ -38,12 +38,14 @@
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;
@@ -57,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_extension.proto b/java/src/test/java/com/google/protobuf/nested_extension.proto
index 9fe5d560..777db032 100644
--- a/java/src/test/java/com/google/protobuf/nested_extension.proto
+++ b/java/src/test/java/com/google/protobuf/nested_extension.proto
@@ -38,6 +38,7 @@ 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/non_nested_extension.proto b/java/src/test/java/com/google/protobuf/non_nested_extension.proto
index f61b419b..17c0b623 100644
--- a/java/src/test/java/com/google/protobuf/non_nested_extension.proto
+++ b/java/src/test/java/com/google/protobuf/non_nested_extension.proto
@@ -35,6 +35,7 @@
package protobuf_unittest;
+
message MessageToBeExtended {
extensions 1 to max;
}
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 00000000..2c251e5d
--- /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 00000000..98b5b7a9
--- /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 00000000..22fb1e65
--- /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
index 6e67d97a..97f27129 100644
--- a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
+++ b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
@@ -42,8 +42,12 @@ 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 {
@@ -54,6 +58,9 @@ message Descriptor {
optional string descriptor = 1;
}
optional NestedDescriptor nested_descriptor = 2;
+ enum NestedEnum {
+ FOO = 1;
+ }
}
message Parser {
@@ -66,6 +73,9 @@ message Parser {
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];
@@ -106,3 +116,42 @@ 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 00000000..c327ed67
--- /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 00000000..591bc563
--- /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 00000000..f509d29e
--- /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/python/google/protobuf/pyext/python_descriptor.h b/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto
index 5232680f..3d6ce0c7 100644
--- a/python/google/protobuf/pyext/python_descriptor.h
+++ b/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto
@@ -28,60 +28,33 @@
// (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)
+// Author: Darick Tong (darick@google.com)
-#ifndef GOOGLE_PROTOBUF_PYTHON_DESCRIPTOR_H__
-#define GOOGLE_PROTOBUF_PYTHON_DESCRIPTOR_H__
+package protobuf_unittest;
-#include <Python.h>
-#include <structmember.h>
+message Proto1 {
+ option experimental_java_message_interface =
+ "com.google.protobuf.ExtraInterfaces.HasBoolValue";
-#include <google/protobuf/descriptor.h>
+ option experimental_java_interface_extends =
+ "com.google.protobuf.ExtraInterfaces.HasByteValue";
-#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
+ option experimental_java_message_interface =
+ "com.google.protobuf.ExtraInterfaces.HasStringValue<Proto1>";
-namespace google {
-namespace protobuf {
-namespace python {
+ option experimental_java_builder_interface =
+ "com.google.protobuf.ExtraInterfaces.HasStringValueBuilder"
+ "<Proto1, Builder>";
-typedef struct {
- PyObject_HEAD
+ optional string string_value = 1;
+ optional bool bool_value = 2;
+ optional bytes byte_value = 3;
+ optional int32 int_value = 4;
+}
- // The proto2 descriptor that this object represents.
- const google::protobuf::FieldDescriptor* descriptor;
+message Proto2 {
+ option experimental_java_message_interface =
+ "com.google.protobuf.ExtraInterfaces.HasBoolValue";
- // Full name of the field (PyString).
- PyObject* full_name;
-
- // Name of the field (PyString).
- PyObject* name;
-
- // C++ type of the field (PyLong).
- PyObject* cpp_type;
-
- // Name of the field (PyLong).
- PyObject* label;
-
- // Identity of the descriptor (PyLong used as a poiner).
- PyObject* id;
-} CFieldDescriptor;
-
-extern PyTypeObject CFieldDescriptor_Type;
-
-extern PyTypeObject CDescriptorPool_Type;
-
-
-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_DESCRIPTOR_H__
+ optional bool bool_value = 1;
+}
diff --git a/python/google/protobuf/pyext/python-proto2.cc b/python/google/protobuf/pyext/python-proto2.cc
deleted file mode 100644
index eebb752b..00000000
--- a/python/google/protobuf/pyext/python-proto2.cc
+++ /dev/null
@@ -1,1717 +0,0 @@
-// 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 <Python.h>
-#include <map>
-#include <string>
-#include <vector>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/pyext/python_descriptor.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/pyext/python_protobuf.h>
-
-/* 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) \
- int32 value; \
- if (!CheckAndGetInteger(arg, &value, kint32min_py, kint32max_py)) { \
- return NULL; \
- }
-
-#define GOOGLE_CHECK_GET_INT64(arg, value) \
- int64 value; \
- if (!CheckAndGetInteger(arg, &value, kint64min_py, kint64max_py)) { \
- return NULL; \
- }
-
-#define GOOGLE_CHECK_GET_UINT32(arg, value) \
- uint32 value; \
- if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint32max_py)) { \
- return NULL; \
- }
-
-#define GOOGLE_CHECK_GET_UINT64(arg, value) \
- uint64 value; \
- if (!CheckAndGetInteger(arg, &value, kPythonZero, kuint64max_py)) { \
- return NULL; \
- }
-
-#define GOOGLE_CHECK_GET_FLOAT(arg, value) \
- float value; \
- if (!CheckAndGetFloat(arg, &value)) { \
- return NULL; \
- } \
-
-#define GOOGLE_CHECK_GET_DOUBLE(arg, value) \
- double value; \
- if (!CheckAndGetDouble(arg, &value)) { \
- return NULL; \
- }
-
-#define GOOGLE_CHECK_GET_BOOL(arg, value) \
- bool value; \
- if (!CheckAndGetBool(arg, &value)) { \
- return NULL; \
- }
-
-#define C(str) const_cast<char*>(str)
-
-// --- Globals:
-
-// Constants used for integer type range checking.
-static PyObject* kPythonZero;
-static PyObject* kint32min_py;
-static PyObject* kint32max_py;
-static PyObject* kuint32max_py;
-static PyObject* kint64min_py;
-static PyObject* kint64max_py;
-static PyObject* kuint64max_py;
-
-namespace google {
-namespace protobuf {
-namespace python {
-
-// --- Support Routines:
-
-static void AddConstants(PyObject* module) {
- struct NameValue {
- char* name;
- int32 value;
- } constants[] = {
- // Labels:
- {"LABEL_OPTIONAL", google::protobuf::FieldDescriptor::LABEL_OPTIONAL},
- {"LABEL_REQUIRED", google::protobuf::FieldDescriptor::LABEL_REQUIRED},
- {"LABEL_REPEATED", google::protobuf::FieldDescriptor::LABEL_REPEATED},
- // CPP types:
- {"CPPTYPE_MESSAGE", google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE},
- // Field Types:
- {"TYPE_MESSAGE", google::protobuf::FieldDescriptor::TYPE_MESSAGE},
- // End.
- {NULL, 0}
- };
-
- for (NameValue* constant = constants;
- constant->name != NULL; constant++) {
- PyModule_AddIntConstant(module, constant->name, constant->value);
- }
-}
-
-// --- CMessage Custom Type:
-
-// ------ Type Forward Declaration:
-
-struct CMessage;
-struct CMessage_Type;
-
-static void CMessageDealloc(CMessage* self);
-static int CMessageInit(CMessage* self, PyObject *args, PyObject *kwds);
-static PyObject* CMessageStr(CMessage* self);
-
-static PyObject* CMessage_AddMessage(CMessage* self, PyObject* args);
-static PyObject* CMessage_AddRepeatedScalar(CMessage* self, PyObject* args);
-static PyObject* CMessage_AssignRepeatedScalar(CMessage* self, PyObject* args);
-static PyObject* CMessage_ByteSize(CMessage* self, PyObject* args);
-static PyObject* CMessage_Clear(CMessage* self, PyObject* args);
-static PyObject* CMessage_ClearField(CMessage* self, PyObject* args);
-static PyObject* CMessage_ClearFieldByDescriptor(
- CMessage* self, PyObject* args);
-static PyObject* CMessage_CopyFrom(CMessage* self, PyObject* args);
-static PyObject* CMessage_DebugString(CMessage* self, PyObject* args);
-static PyObject* CMessage_DeleteRepeatedField(CMessage* self, PyObject* args);
-static PyObject* CMessage_Equals(CMessage* self, PyObject* args);
-static PyObject* CMessage_FieldLength(CMessage* self, PyObject* args);
-static PyObject* CMessage_FindInitializationErrors(CMessage* self);
-static PyObject* CMessage_GetRepeatedMessage(CMessage* self, PyObject* args);
-static PyObject* CMessage_GetRepeatedScalar(CMessage* self, PyObject* args);
-static PyObject* CMessage_GetScalar(CMessage* self, PyObject* args);
-static PyObject* CMessage_HasField(CMessage* self, PyObject* args);
-static PyObject* CMessage_HasFieldByDescriptor(CMessage* self, PyObject* args);
-static PyObject* CMessage_IsInitialized(CMessage* self, PyObject* args);
-static PyObject* CMessage_ListFields(CMessage* self, PyObject* args);
-static PyObject* CMessage_MergeFrom(CMessage* self, PyObject* args);
-static PyObject* CMessage_MergeFromString(CMessage* self, PyObject* args);
-static PyObject* CMessage_MutableMessage(CMessage* self, PyObject* args);
-static PyObject* CMessage_NewSubMessage(CMessage* self, PyObject* args);
-static PyObject* CMessage_SetScalar(CMessage* self, PyObject* args);
-static PyObject* CMessage_SerializePartialToString(
- CMessage* self, PyObject* args);
-static PyObject* CMessage_SerializeToString(CMessage* self, PyObject* args);
-static PyObject* CMessage_SetInParent(CMessage* self, PyObject* args);
-static PyObject* CMessage_SwapRepeatedFieldElements(
- CMessage* self, PyObject* args);
-
-// ------ Object Definition:
-
-typedef struct CMessage {
- PyObject_HEAD
-
- struct CMessage* parent; // NULL if wasn't created from another message.
- CFieldDescriptor* parent_field;
- const char* full_name;
- google::protobuf::Message* message;
- bool free_message;
- bool read_only;
-} CMessage;
-
-// ------ Method Table:
-
-#define CMETHOD(name, args, doc) \
- { C(#name), (PyCFunction)CMessage_##name, args, C(doc) }
-static PyMethodDef CMessageMethods[] = {
- CMETHOD(AddMessage, METH_O,
- "Adds a new message to a repeated composite field."),
- CMETHOD(AddRepeatedScalar, METH_VARARGS,
- "Adds a scalar to a repeated scalar field."),
- CMETHOD(AssignRepeatedScalar, METH_VARARGS,
- "Clears and sets the values of a repeated scalar field."),
- CMETHOD(ByteSize, METH_NOARGS,
- "Returns the size of the message in bytes."),
- CMETHOD(Clear, METH_O,
- "Clears a protocol message."),
- CMETHOD(ClearField, METH_VARARGS,
- "Clears a protocol message field by name."),
- CMETHOD(ClearFieldByDescriptor, METH_O,
- "Clears a protocol message field by descriptor."),
- CMETHOD(CopyFrom, METH_O,
- "Copies a protocol message into the current message."),
- CMETHOD(DebugString, METH_NOARGS,
- "Returns the debug string of a protocol message."),
- CMETHOD(DeleteRepeatedField, METH_VARARGS,
- "Deletes a slice of values from a repeated field."),
- CMETHOD(Equals, METH_O,
- "Checks if two protocol messages are equal (by identity)."),
- CMETHOD(FieldLength, METH_O,
- "Returns the number of elements in a repeated field."),
- CMETHOD(FindInitializationErrors, METH_NOARGS,
- "Returns the initialization errors of a message."),
- CMETHOD(GetRepeatedMessage, METH_VARARGS,
- "Returns a message from a repeated composite field."),
- CMETHOD(GetRepeatedScalar, METH_VARARGS,
- "Returns a scalar value from a repeated scalar field."),
- CMETHOD(GetScalar, METH_O,
- "Returns the scalar value of a field."),
- CMETHOD(HasField, METH_O,
- "Checks if a message field is set."),
- CMETHOD(HasFieldByDescriptor, METH_O,
- "Checks if a message field is set by given its descriptor"),
- CMETHOD(IsInitialized, METH_NOARGS,
- "Checks if all required fields of a protocol message are set."),
- CMETHOD(ListFields, METH_NOARGS,
- "Lists all set fields of a message."),
- CMETHOD(MergeFrom, METH_O,
- "Merges a protocol message into the current message."),
- CMETHOD(MergeFromString, METH_O,
- "Merges a serialized message into the current message."),
- CMETHOD(MutableMessage, METH_O,
- "Returns a new instance of a nested protocol message."),
- CMETHOD(NewSubMessage, METH_O,
- "Creates and returns a python message given the descriptor of a "
- "composite field of the current message."),
- CMETHOD(SetScalar, METH_VARARGS,
- "Sets the value of a singular scalar field."),
- CMETHOD(SerializePartialToString, METH_VARARGS,
- "Serializes the message to a string, even if it isn't initialized."),
- CMETHOD(SerializeToString, METH_NOARGS,
- "Serializes the message to a string, only for initialized messages."),
- CMETHOD(SetInParent, METH_NOARGS,
- "Sets the has bit of the given field in its parent message."),
- CMETHOD(SwapRepeatedFieldElements, METH_VARARGS,
- "Swaps the elements in two positions in a repeated field."),
- { NULL, NULL }
-};
-#undef CMETHOD
-
-static PyMemberDef CMessageMembers[] = {
- { C("full_name"), T_STRING, offsetof(CMessage, full_name), 0, "Full name" },
- { NULL }
-};
-
-// ------ Type Definition:
-
-// The definition for the type object that captures the type of CMessage
-// in Python.
-PyTypeObject CMessage_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- C("google.protobuf.internal."
- "_net_proto2___python."
- "CMessage"), // tp_name
- sizeof(CMessage), // tp_basicsize
- 0, // tp_itemsize
- (destructor)CMessageDealloc, // 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)CMessageStr, // tp_str
- 0, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT, // tp_flags
- C("A ProtocolMessage"), // tp_doc
- 0, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- 0, // tp_weaklistoffset
- 0, // tp_iter
- 0, // tp_iternext
- CMessageMethods, // tp_methods
- CMessageMembers, // tp_members
- 0, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- (initproc)CMessageInit, // tp_init
- PyType_GenericAlloc, // tp_alloc
- PyType_GenericNew, // tp_new
- PyObject_Del, // tp_free
-};
-
-// ------ Helper Functions:
-
-static void FormatTypeError(PyObject* arg, char* expected_types) {
- PyObject* repr = PyObject_Repr(arg);
- PyErr_Format(PyExc_TypeError,
- "%.100s has type %.100s, but expected one of: %s",
- PyString_AS_STRING(repr),
- arg->ob_type->tp_name,
- expected_types);
- Py_DECREF(repr);
-}
-
-template <class T>
-static bool CheckAndGetInteger(
- PyObject* arg, T* value, PyObject* min, PyObject* max) {
- bool is_long = PyLong_Check(arg);
- if (!PyInt_Check(arg) && !is_long) {
- FormatTypeError(arg, "int, long");
- return false;
- }
-
- if (PyObject_Compare(min, arg) > 0 || PyObject_Compare(max, arg) < 0) {
- PyObject* s = PyObject_Str(arg);
- PyErr_Format(PyExc_ValueError,
- "Value out of range: %s",
- PyString_AS_STRING(s));
- Py_DECREF(s);
- return false;
- }
- if (is_long) {
- if (min == kPythonZero) {
- *value = static_cast<T>(PyLong_AsUnsignedLongLong(arg));
- } else {
- *value = static_cast<T>(PyLong_AsLongLong(arg));
- }
- } else {
- *value = static_cast<T>(PyInt_AsLong(arg));
- }
- return true;
-}
-
-static 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;
-}
-
-static bool CheckAndGetFloat(PyObject* arg, float* value) {
- double double_value;
- if (!CheckAndGetDouble(arg, &double_value)) {
- return false;
- }
- *value = static_cast<float>(double_value);
- return true;
-}
-
-static 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<bool>(PyInt_AsLong(arg));
- return true;
-}
-
-google::protobuf::DynamicMessageFactory* global_message_factory = NULL;
-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) {
- return NULL;
- }
- return global_message_factory->GetPrototype(descriptor);
-}
-
-static void ReleaseSubMessage(google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* field_descriptor,
- CMessage* child_cmessage) {
- Message* released_message = message->GetReflection()->ReleaseMessage(
- message, field_descriptor, global_message_factory);
- GOOGLE_DCHECK(child_cmessage->message != NULL);
- // 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(
- child_cmessage->message->GetDescriptor());
- GOOGLE_DCHECK(prototype != NULL);
- child_cmessage->message = prototype->New();
- }
- child_cmessage->parent = NULL;
- child_cmessage->parent_field = NULL;
- child_cmessage->free_message = true;
- child_cmessage->read_only = false;
-}
-
-static 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 (!PyString_Check(arg) && !PyUnicode_Check(arg)) {
- FormatTypeError(arg, "str, unicode");
- return false;
- }
-
- if (PyString_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_AS_STRING(repr));
- Py_DECREF(repr);
- return false;
- } else {
- Py_DECREF(unicode);
- }
- }
- } else if (!PyString_Check(arg)) {
- FormatTypeError(arg, "str");
- return false;
- }
-
- PyObject* encoded_string = NULL;
- if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
- if (PyString_Check(arg)) {
- encoded_string = PyString_AsEncodedObject(arg, "utf-8", NULL);
- } 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 (PyString_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;
-}
-
-static PyObject* ToStringObject(
- const google::protobuf::FieldDescriptor* descriptor, string value) {
- if (descriptor->type() != google::protobuf::FieldDescriptor::TYPE_STRING) {
- return PyString_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 = PyString_FromStringAndSize(value.c_str(), value.length());
- }
- return result;
-}
-
-static void AssureWritable(CMessage* self) {
- if (self == NULL ||
- self->parent == NULL ||
- self->parent_field == NULL) {
- return;
- }
-
- if (!self->read_only) {
- return;
- }
-
- AssureWritable(self->parent);
-
- google::protobuf::Message* message = self->parent->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
- self->message = reflection->MutableMessage(
- message, self->parent_field->descriptor, global_message_factory);
- self->read_only = false;
-}
-
-static PyObject* InternalGetScalar(
- google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* field_descriptor) {
- 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);
-#if IS_64BIT
- result = PyInt_FromLong(value);
-#else
- result = PyLong_FromLongLong(value);
-#endif
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
- uint32 value = reflection->GetUInt32(*message, field_descriptor);
-#if IS_64BIT
- result = PyInt_FromLong(value);
-#else
- result = PyLong_FromLongLong(value);
-#endif
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
- uint64 value = reflection->GetUInt64(*message, field_descriptor);
-#if IS_64BIT
- if (value <= static_cast<uint64>(kint64max)) {
- result = PyInt_FromLong(static_cast<uint64>(value));
- }
-#else
- if (value <= static_cast<uint32>(kint32max)) {
- result = PyInt_FromLong(static_cast<uint32>(value));
- }
-#endif
- else { // NOLINT
- 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;
-}
-
-static PyObject* InternalSetScalar(
- google::protobuf::Message* message, const google::protobuf::FieldDescriptor* field_descriptor,
- PyObject* arg) {
- 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;
- }
-
- switch (field_descriptor->cpp_type()) {
- case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
- GOOGLE_CHECK_GET_INT32(arg, value);
- reflection->SetInt32(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
- GOOGLE_CHECK_GET_INT64(arg, value);
- reflection->SetInt64(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
- GOOGLE_CHECK_GET_UINT32(arg, value);
- reflection->SetUInt32(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
- GOOGLE_CHECK_GET_UINT64(arg, value);
- reflection->SetUInt64(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
- GOOGLE_CHECK_GET_FLOAT(arg, value);
- reflection->SetFloat(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
- GOOGLE_CHECK_GET_DOUBLE(arg, value);
- reflection->SetDouble(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
- GOOGLE_CHECK_GET_BOOL(arg, value);
- reflection->SetBool(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
- if (!CheckAndSetString(
- arg, message, field_descriptor, reflection, false, -1)) {
- return NULL;
- }
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
- GOOGLE_CHECK_GET_INT32(arg, value);
- 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 {
- bool added = false;
- // Add the value to 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()) {
- unknown_field_set->mutable_field(i)->set_varint(value);
- added = true;
- break;
- }
- }
-
- if (!added) {
- unknown_field_set->AddVarint(field_descriptor->number(), value);
- }
- reflection->ClearField(message, field_descriptor);
- }
- break;
- }
- default:
- PyErr_Format(
- PyExc_SystemError, "Setting value to a field of unknown type %d",
- field_descriptor->cpp_type());
- }
-
- Py_RETURN_NONE;
-}
-
-static PyObject* InternalAddRepeatedScalar(
- google::protobuf::Message* message, const google::protobuf::FieldDescriptor* field_descriptor,
- PyObject* arg) {
-
- 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(arg, value);
- reflection->AddInt32(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
- GOOGLE_CHECK_GET_INT64(arg, value);
- reflection->AddInt64(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
- GOOGLE_CHECK_GET_UINT32(arg, value);
- reflection->AddUInt32(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
- GOOGLE_CHECK_GET_UINT64(arg, value);
- reflection->AddUInt64(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
- GOOGLE_CHECK_GET_FLOAT(arg, value);
- reflection->AddFloat(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
- GOOGLE_CHECK_GET_DOUBLE(arg, value);
- reflection->AddDouble(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
- GOOGLE_CHECK_GET_BOOL(arg, value);
- reflection->AddBool(message, field_descriptor, value);
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
- if (!CheckAndSetString(
- arg, message, field_descriptor, reflection, true, -1)) {
- return NULL;
- }
- break;
- }
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
- GOOGLE_CHECK_GET_INT32(arg, value);
- 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 {
- PyObject* s = PyObject_Str(arg);
- PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
- PyString_AS_STRING(s));
- Py_DECREF(s);
- return NULL;
- }
- break;
- }
- default:
- PyErr_Format(
- PyExc_SystemError, "Adding value to a field of unknown type %d",
- field_descriptor->cpp_type());
- }
-
- Py_RETURN_NONE;
-}
-
-static PyObject* InternalGetRepeatedScalar(
- CMessage* cmessage, const google::protobuf::FieldDescriptor* field_descriptor,
- int index) {
- google::protobuf::Message* message = cmessage->message;
- 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", 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: {
- CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
- if (py_cmsg == NULL) {
- return NULL;
- }
- const google::protobuf::Message& msg = reflection->GetRepeatedMessage(
- *message, field_descriptor, index);
- py_cmsg->parent = cmessage;
- py_cmsg->full_name = field_descriptor->full_name().c_str();
- py_cmsg->message = const_cast<google::protobuf::Message*>(&msg);
- py_cmsg->free_message = false;
- py_cmsg->read_only = false;
- result = reinterpret_cast<PyObject*>(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* InternalGetRepeatedScalarSlice(
- CMessage* cmessage, const google::protobuf::FieldDescriptor* field_descriptor,
- PyObject* slice) {
- Py_ssize_t from;
- Py_ssize_t to;
- Py_ssize_t step;
- Py_ssize_t length;
- bool return_list = false;
- google::protobuf::Message* message = cmessage->message;
-
- if (PyInt_Check(slice)) {
- from = to = PyInt_AsLong(slice);
- } else 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);
- PySlice_GetIndices(
- reinterpret_cast<PySliceObject*>(slice), length, &from, &to, &step);
- return_list = true;
- } else {
- PyErr_SetString(PyExc_TypeError, "list indices must be integers");
- return NULL;
- }
-
- if (!return_list) {
- return InternalGetRepeatedScalar(cmessage, field_descriptor, 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;
- PyObject* s = InternalGetRepeatedScalar(
- cmessage, field_descriptor, index);
- PyList_Append(list, s);
- Py_DECREF(s);
- }
- } else {
- if (step > 0) return list;
- for (Py_ssize_t index = from; index > to; index += step) {
- if (index < 0 || index >= length) break;
- PyObject* s = InternalGetRepeatedScalar(
- cmessage, field_descriptor, index);
- PyList_Append(list, s);
- Py_DECREF(s);
- }
- }
- return list;
-}
-
-// ------ C Constructor/Destructor:
-
-static int CMessageInit(CMessage* self, PyObject *args, PyObject *kwds) {
- self->message = NULL;
- return 0;
-}
-
-static void CMessageDealloc(CMessage* self) {
- if (self->free_message) {
- if (self->read_only) {
- PyErr_WriteUnraisable(reinterpret_cast<PyObject*>(self));
- }
- delete self->message;
- }
- self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
-}
-
-// ------ Methods:
-
-static PyObject* CMessage_Clear(CMessage* self, PyObject* arg) {
- AssureWritable(self);
- google::protobuf::Message* message = self->message;
-
- // This block of code is equivalent to the following:
- // for cfield_descriptor, child_cmessage in arg:
- // ReleaseSubMessage(cfield_descriptor, child_cmessage)
- if (!PyList_Check(arg)) {
- PyErr_SetString(PyExc_TypeError, "Must be a list");
- return NULL;
- }
- PyObject* messages_to_clear = arg;
- Py_ssize_t num_messages_to_clear = PyList_GET_SIZE(messages_to_clear);
- for(int i = 0; i < num_messages_to_clear; ++i) {
- PyObject* message_tuple = PyList_GET_ITEM(messages_to_clear, i);
- if (!PyTuple_Check(message_tuple) || PyTuple_GET_SIZE(message_tuple) != 2) {
- PyErr_SetString(PyExc_TypeError, "Must be a tuple of size 2");
- return NULL;
- }
-
- PyObject* py_cfield_descriptor = PyTuple_GET_ITEM(message_tuple, 0);
- PyObject* py_child_cmessage = PyTuple_GET_ITEM(message_tuple, 1);
- if (!PyObject_TypeCheck(py_cfield_descriptor, &CFieldDescriptor_Type) ||
- !PyObject_TypeCheck(py_child_cmessage, &CMessage_Type)) {
- PyErr_SetString(PyExc_ValueError, "Invalid Tuple");
- return NULL;
- }
-
- CFieldDescriptor* cfield_descriptor = reinterpret_cast<CFieldDescriptor *>(
- py_cfield_descriptor);
- CMessage* child_cmessage = reinterpret_cast<CMessage *>(py_child_cmessage);
- ReleaseSubMessage(message, cfield_descriptor->descriptor, child_cmessage);
- }
-
- message->Clear();
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_IsInitialized(CMessage* self, PyObject* args) {
- return PyBool_FromLong(self->message->IsInitialized() ? 1 : 0);
-}
-
-static PyObject* CMessage_HasField(CMessage* self, PyObject* arg) {
- char* field_name;
- if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
- return NULL;
- }
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
- const google::protobuf::FieldDescriptor* field_descriptor =
- descriptor->FindFieldByName(field_name);
- if (field_descriptor == NULL) {
- PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
- return NULL;
- }
-
- bool has_field =
- message->GetReflection()->HasField(*message, field_descriptor);
- return PyBool_FromLong(has_field ? 1 : 0);
-}
-
-static PyObject* CMessage_HasFieldByDescriptor(CMessage* self, PyObject* arg) {
- CFieldDescriptor* cfield_descriptor = NULL;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
- &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
- return NULL;
- }
- cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::FieldDescriptor* field_descriptor =
- cfield_descriptor->descriptor;
-
- if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
- PyErr_SetString(PyExc_KeyError,
- "Field does not belong to message!");
- return NULL;
- }
-
- if (FIELD_IS_REPEATED(field_descriptor)) {
- 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);
-}
-
-static PyObject* CMessage_ClearFieldByDescriptor(
- CMessage* self, PyObject* arg) {
- CFieldDescriptor* cfield_descriptor = NULL;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
- &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
- return NULL;
- }
- cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::FieldDescriptor* field_descriptor =
- cfield_descriptor->descriptor;
-
- if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
- PyErr_SetString(PyExc_KeyError,
- "Field does not belong to message!");
- return NULL;
- }
-
- message->GetReflection()->ClearField(message, field_descriptor);
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_ClearField(CMessage* self, PyObject* args) {
- char* field_name;
- CMessage* child_cmessage = NULL;
- if (!PyArg_ParseTuple(args, C("s|O!:ClearField"), &field_name,
- &CMessage_Type, &child_cmessage)) {
- return NULL;
- }
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
- const google::protobuf::FieldDescriptor* field_descriptor =
- descriptor->FindFieldByName(field_name);
- if (field_descriptor == NULL) {
- PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
- return NULL;
- }
-
- if (child_cmessage != NULL && !FIELD_IS_REPEATED(field_descriptor)) {
- ReleaseSubMessage(message, field_descriptor, child_cmessage);
- } else {
- message->GetReflection()->ClearField(message, field_descriptor);
- }
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_GetScalar(CMessage* self, PyObject* arg) {
- CFieldDescriptor* cdescriptor = NULL;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
- &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
- return NULL;
- }
- cdescriptor = reinterpret_cast<CFieldDescriptor*>(arg);
-
- google::protobuf::Message* message = self->message;
- return InternalGetScalar(message, cdescriptor->descriptor);
-}
-
-static PyObject* CMessage_GetRepeatedScalar(CMessage* self, PyObject* args) {
- CFieldDescriptor* cfield_descriptor;
- PyObject* slice;
- if (!PyArg_ParseTuple(args, C("O!O:GetRepeatedScalar"),
- &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
- return NULL;
- }
-
- return InternalGetRepeatedScalarSlice(
- self, cfield_descriptor->descriptor, slice);
-}
-
-static PyObject* CMessage_AssignRepeatedScalar(CMessage* self, PyObject* args) {
- CFieldDescriptor* cfield_descriptor;
- PyObject* slice;
- if (!PyArg_ParseTuple(args, C("O!O:AssignRepeatedScalar"),
- &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
- return NULL;
- }
-
- AssureWritable(self);
- google::protobuf::Message* message = self->message;
- message->GetReflection()->ClearField(message, cfield_descriptor->descriptor);
-
- PyObject* iter = PyObject_GetIter(slice);
- PyObject* next;
- while ((next = PyIter_Next(iter)) != NULL) {
- if (InternalAddRepeatedScalar(
- message, cfield_descriptor->descriptor, next) == NULL) {
- Py_DECREF(next);
- Py_DECREF(iter);
- return NULL;
- }
- Py_DECREF(next);
- }
- Py_DECREF(iter);
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_DeleteRepeatedField(CMessage* self, PyObject* args) {
- CFieldDescriptor* cfield_descriptor;
- PyObject* slice;
- if (!PyArg_ParseTuple(args, C("O!O:DeleteRepeatedField"),
- &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
- return NULL;
- }
- AssureWritable(self);
-
- Py_ssize_t length, from, to, step, slice_length;
- google::protobuf::Message* message = self->message;
- const google::protobuf::FieldDescriptor* field_descriptor =
- cfield_descriptor->descriptor;
- 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 NULL;
- }
- } else if (PySlice_Check(slice)) {
- from = to = step = slice_length = 0;
- PySlice_GetIndicesEx(
- reinterpret_cast<PySliceObject*>(slice),
- 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 NULL;
- }
-
- Py_ssize_t i = from;
- std::vector<bool> 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);
- }
- ++to;
- }
- }
-
- while (i > to) {
- reflection->RemoveLast(message, field_descriptor);
- --i;
- }
-
- Py_RETURN_NONE;
-}
-
-
-static PyObject* CMessage_SetScalar(CMessage* self, PyObject* args) {
- CFieldDescriptor* cfield_descriptor;
- PyObject* arg;
- if (!PyArg_ParseTuple(args, C("O!O:SetScalar"),
- &CFieldDescriptor_Type, &cfield_descriptor, &arg)) {
- return NULL;
- }
- AssureWritable(self);
-
- return InternalSetScalar(self->message, cfield_descriptor->descriptor, arg);
-}
-
-static PyObject* CMessage_AddRepeatedScalar(CMessage* self, PyObject* args) {
- CFieldDescriptor* cfield_descriptor;
- PyObject* value;
- if (!PyArg_ParseTuple(args, C("O!O:AddRepeatedScalar"),
- &CFieldDescriptor_Type, &cfield_descriptor, &value)) {
- return NULL;
- }
- AssureWritable(self);
-
- return InternalAddRepeatedScalar(
- self->message, cfield_descriptor->descriptor, value);
-}
-
-static PyObject* CMessage_FieldLength(CMessage* self, PyObject* arg) {
- CFieldDescriptor* cfield_descriptor;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
- &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
- return NULL;
- }
- cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
-
- google::protobuf::Message* message = self->message;
- int length = message->GetReflection()->FieldSize(
- *message, cfield_descriptor->descriptor);
- return PyInt_FromLong(length);
-}
-
-static PyObject* CMessage_DebugString(CMessage* self, PyObject* args) {
- return PyString_FromString(self->message->DebugString().c_str());
-}
-
-static PyObject* CMessage_SerializeToString(CMessage* self, PyObject* args) {
- int size = self->message->ByteSize();
- if (size <= 0) {
- return PyString_FromString("");
- }
- PyObject* result = PyString_FromStringAndSize(NULL, size);
- if (result == NULL) {
- return NULL;
- }
- char* buffer = PyString_AS_STRING(result);
- self->message->SerializeWithCachedSizesToArray(
- reinterpret_cast<uint8*>(buffer));
- return result;
-}
-
-static PyObject* CMessage_SerializePartialToString(
- CMessage* self, PyObject* args) {
- string contents;
- self->message->SerializePartialToString(&contents);
- return PyString_FromStringAndSize(contents.c_str(), contents.size());
-}
-
-static PyObject* CMessageStr(CMessage* self) {
- char str[1024];
- str[sizeof(str) - 1] = 0;
- snprintf(str, sizeof(str) - 1, "CMessage: <%p>", self->message);
- return PyString_FromString(str);
-}
-
-static PyObject* CMessage_MergeFrom(CMessage* self, PyObject* arg) {
- CMessage* other_message;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a message");
- return NULL;
- }
-
- other_message = reinterpret_cast<CMessage*>(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);
-
- self->message->MergeFrom(*other_message->message);
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_CopyFrom(CMessage* self, PyObject* arg) {
- CMessage* other_message;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a message");
- return NULL;
- }
-
- other_message = reinterpret_cast<CMessage*>(arg);
- 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);
-
- self->message->CopyFrom(*other_message->message);
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_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<const uint8*>(data), data_length);
- input.SetExtensionRegistry(GetDescriptorPool(), global_message_factory);
- bool success = self->message->MergePartialFromCodedStream(&input);
- if (success) {
- return PyInt_FromLong(self->message->ByteSize());
- } else {
- return PyInt_FromLong(-1);
- }
-}
-
-static PyObject* CMessage_ByteSize(CMessage* self, PyObject* args) {
- return PyLong_FromLong(self->message->ByteSize());
-}
-
-static PyObject* CMessage_SetInParent(CMessage* self, PyObject* args) {
- AssureWritable(self);
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_SwapRepeatedFieldElements(
- CMessage* self, PyObject* args) {
- CFieldDescriptor* cfield_descriptor;
- int index1, index2;
- if (!PyArg_ParseTuple(args, C("O!ii:SwapRepeatedFieldElements"),
- &CFieldDescriptor_Type, &cfield_descriptor,
- &index1, &index2)) {
- return NULL;
- }
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
-
- reflection->SwapElements(
- message, cfield_descriptor->descriptor, index1, index2);
- Py_RETURN_NONE;
-}
-
-static PyObject* CMessage_AddMessage(CMessage* self, PyObject* arg) {
- CFieldDescriptor* cfield_descriptor;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
- &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
- return NULL;
- }
- cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
- AssureWritable(self);
-
- CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
- if (py_cmsg == NULL) {
- return NULL;
- }
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
- google::protobuf::Message* sub_message =
- reflection->AddMessage(message, cfield_descriptor->descriptor);
-
- py_cmsg->parent = NULL;
- py_cmsg->full_name = sub_message->GetDescriptor()->full_name().c_str();
- py_cmsg->message = sub_message;
- py_cmsg->free_message = false;
- py_cmsg->read_only = false;
- return reinterpret_cast<PyObject*>(py_cmsg);
-}
-
-static PyObject* CMessage_GetRepeatedMessage(CMessage* self, PyObject* args) {
- CFieldDescriptor* cfield_descriptor;
- PyObject* slice;
- if (!PyArg_ParseTuple(args, C("O!O:GetRepeatedMessage"),
- &CFieldDescriptor_Type, &cfield_descriptor, &slice)) {
- return NULL;
- }
-
- return InternalGetRepeatedScalarSlice(
- self, cfield_descriptor->descriptor, slice);
-}
-
-static PyObject* CMessage_NewSubMessage(CMessage* self, PyObject* arg) {
- CFieldDescriptor* cfield_descriptor;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
- &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
- return NULL;
- }
- cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
-
- CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
- if (py_cmsg == NULL) {
- return NULL;
- }
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
- const google::protobuf::Message& sub_message =
- reflection->GetMessage(*message, cfield_descriptor->descriptor,
- global_message_factory);
-
- py_cmsg->full_name = sub_message.GetDescriptor()->full_name().c_str();
- py_cmsg->parent = self;
- py_cmsg->parent_field = cfield_descriptor;
- py_cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
- py_cmsg->free_message = false;
- py_cmsg->read_only = true;
- return reinterpret_cast<PyObject*>(py_cmsg);
-}
-
-static PyObject* CMessage_MutableMessage(CMessage* self, PyObject* arg) {
- CFieldDescriptor* cfield_descriptor;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg),
- &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a field descriptor");
- return NULL;
- }
- cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(arg);
- AssureWritable(self);
-
- CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
- if (py_cmsg == NULL) {
- return NULL;
- }
-
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
- google::protobuf::Message* mutable_message =
- reflection->MutableMessage(message, cfield_descriptor->descriptor,
- global_message_factory);
-
- py_cmsg->full_name = mutable_message->GetDescriptor()->full_name().c_str();
- py_cmsg->message = mutable_message;
- py_cmsg->free_message = false;
- py_cmsg->read_only = false;
- return reinterpret_cast<PyObject*>(py_cmsg);
-}
-
-static PyObject* CMessage_Equals(CMessage* self, PyObject* arg) {
- CMessage* other_message;
- if (!PyObject_TypeCheck(reinterpret_cast<PyObject *>(arg), &CMessage_Type)) {
- PyErr_SetString(PyExc_TypeError, "Must be a message");
- return NULL;
- }
- other_message = reinterpret_cast<CMessage*>(arg);
-
- if (other_message->message == self->message) {
- return PyBool_FromLong(1);
- }
-
- if (other_message->message->GetDescriptor() !=
- self->message->GetDescriptor()) {
- return PyBool_FromLong(0);
- }
-
- return PyBool_FromLong(1);
-}
-
-static PyObject* CMessage_ListFields(CMessage* self, PyObject* args) {
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
- vector<const google::protobuf::FieldDescriptor*> fields;
- reflection->ListFields(*message, &fields);
-
- PyObject* list = PyList_New(fields.size());
- if (list == NULL) {
- return NULL;
- }
-
- for (unsigned int i = 0; i < fields.size(); ++i) {
- bool is_extension = fields[i]->is_extension();
- PyObject* t = PyTuple_New(2);
- if (t == NULL) {
- Py_DECREF(list);
- return NULL;
- }
-
- PyObject* is_extension_object = PyBool_FromLong(is_extension ? 1 : 0);
-
- PyObject* field_name;
- const string* s;
- if (is_extension) {
- s = &fields[i]->full_name();
- } else {
- s = &fields[i]->name();
- }
- field_name = PyString_FromStringAndSize(s->c_str(), s->length());
- if (field_name == NULL) {
- Py_DECREF(list);
- Py_DECREF(t);
- return NULL;
- }
-
- PyTuple_SET_ITEM(t, 0, is_extension_object);
- PyTuple_SET_ITEM(t, 1, field_name);
- PyList_SET_ITEM(list, i, t);
- }
-
- return list;
-}
-
-static PyObject* CMessage_FindInitializationErrors(CMessage* self) {
- google::protobuf::Message* message = self->message;
- vector<string> errors;
- message->FindInitializationErrors(&errors);
-
- PyObject* error_list = PyList_New(errors.size());
- if (error_list == NULL) {
- return NULL;
- }
- for (unsigned int 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;
-}
-
-// ------ Python Constructor:
-
-PyObject* Python_NewCMessage(PyObject* ignored, PyObject* arg) {
- const char* message_type = PyString_AsString(arg);
- if (message_type == NULL) {
- return NULL;
- }
-
- const google::protobuf::Message* message = CreateMessage(message_type);
- if (message == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't create message of type %s!",
- message_type);
- return NULL;
- }
-
- CMessage* py_cmsg = PyObject_New(CMessage, &CMessage_Type);
- if (py_cmsg == NULL) {
- return NULL;
- }
- py_cmsg->message = message->New();
- py_cmsg->free_message = true;
- py_cmsg->full_name = message->GetDescriptor()->full_name().c_str();
- py_cmsg->read_only = false;
- py_cmsg->parent = NULL;
- py_cmsg->parent_field = NULL;
- return reinterpret_cast<PyObject*>(py_cmsg);
-}
-
-// --- Module Functions (exposed to Python):
-
-PyMethodDef methods[] = {
- { C("NewCMessage"), (PyCFunction)Python_NewCMessage,
- METH_O,
- C("Creates a new C++ protocol message, given its full name.") },
- { C("NewCDescriptorPool"), (PyCFunction)Python_NewCDescriptorPool,
- METH_NOARGS,
- C("Creates a new C++ descriptor pool.") },
- { C("BuildFile"), (PyCFunction)Python_BuildFile,
- METH_O,
- C("Registers a new protocol buffer file in the global C++ descriptor "
- "pool.") },
- {NULL}
-};
-
-// --- Exposing the C proto living inside Python proto to C code:
-
-extern const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg);
-extern Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg);
-
-static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg) {
- PyObject* c_msg_obj = PyObject_GetAttrString(msg, "_cmsg");
- if (c_msg_obj == NULL) {
- PyErr_Clear();
- return NULL;
- }
- Py_DECREF(c_msg_obj);
- if (!PyObject_TypeCheck(c_msg_obj, &CMessage_Type)) {
- return NULL;
- }
- CMessage* c_msg = reinterpret_cast<CMessage*>(c_msg_obj);
- return c_msg->message;
-}
-
-static google::protobuf::Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
- PyObject* c_msg_obj = PyObject_GetAttrString(msg, "_cmsg");
- if (c_msg_obj == NULL) {
- PyErr_Clear();
- return NULL;
- }
- Py_DECREF(c_msg_obj);
- if (!PyObject_TypeCheck(c_msg_obj, &CMessage_Type)) {
- return NULL;
- }
- CMessage* c_msg = reinterpret_cast<CMessage*>(c_msg_obj);
- AssureWritable(c_msg);
- return c_msg->message;
-}
-
-// --- Module Init Function:
-
-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.";
-
-extern "C" {
- void init_net_proto2___python() {
- // Initialize constants.
- 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);
-
- global_message_factory = new DynamicMessageFactory(GetDescriptorPool());
- global_message_factory->SetDelegateToGeneratedFactory(true);
-
- // Export our functions to Python.
- PyObject *m;
- m = Py_InitModule3(C("_net_proto2___python"), methods, C(module_docstring));
- if (m == NULL) {
- return;
- }
-
- AddConstants(m);
-
- CMessage_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&CMessage_Type) < 0) {
- return;
- }
-
- if (!InitDescriptor()) {
- return;
- }
-
- // Override {Get,Mutable}CProtoInsidePyProto.
- GetCProtoInsidePyProtoPtr = GetCProtoInsidePyProtoImpl;
- MutableCProtoInsidePyProtoPtr = MutableCProtoInsidePyProtoImpl;
- }
-}
-
-} // namespace python
-} // namespace protobuf
-} // namespace google
diff --git a/python/google/protobuf/pyext/python_descriptor.cc b/python/google/protobuf/pyext/python_descriptor.cc
deleted file mode 100644
index 5e3e9ea4..00000000
--- a/python/google/protobuf/pyext/python_descriptor.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-// 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 <Python.h>
-#include <string>
-
-#include <google/protobuf/pyext/python_descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-
-#define C(str) const_cast<char*>(str)
-
-namespace google {
-namespace protobuf {
-namespace python {
-
-
-static void CFieldDescriptorDealloc(CFieldDescriptor* self);
-
-static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
-
-static PyObject* CFieldDescriptor_GetFullName(
- CFieldDescriptor* self, void *closure) {
- Py_XINCREF(self->full_name);
- return self->full_name;
-}
-
-static PyObject* CFieldDescriptor_GetName(
- CFieldDescriptor *self, void *closure) {
- Py_XINCREF(self->name);
- return self->name;
-}
-
-static PyObject* CFieldDescriptor_GetCppType(
- CFieldDescriptor *self, void *closure) {
- Py_XINCREF(self->cpp_type);
- return self->cpp_type;
-}
-
-static PyObject* CFieldDescriptor_GetLabel(
- CFieldDescriptor *self, void *closure) {
- Py_XINCREF(self->label);
- return self->label;
-}
-
-static PyObject* CFieldDescriptor_GetID(
- CFieldDescriptor *self, void *closure) {
- Py_XINCREF(self->id);
- return self->id;
-}
-
-
-static PyGetSetDef CFieldDescriptorGetters[] = {
- { C("full_name"),
- (getter)CFieldDescriptor_GetFullName, NULL, "Full name", NULL},
- { C("name"),
- (getter)CFieldDescriptor_GetName, NULL, "last name", NULL},
- { C("cpp_type"),
- (getter)CFieldDescriptor_GetCppType, NULL, "C++ Type", NULL},
- { C("label"),
- (getter)CFieldDescriptor_GetLabel, NULL, "Label", NULL},
- { C("id"),
- (getter)CFieldDescriptor_GetID, NULL, "ID", NULL},
- {NULL}
-};
-
-PyTypeObject CFieldDescriptor_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- C("google.protobuf.internal."
- "_net_proto2___python."
- "CFieldDescriptor"), // tp_name
- sizeof(CFieldDescriptor), // tp_basicsize
- 0, // tp_itemsize
- (destructor)CFieldDescriptorDealloc, // 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
- CFieldDescriptorGetters, // 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
-};
-
-static void CFieldDescriptorDealloc(CFieldDescriptor* self) {
- Py_DECREF(self->full_name);
- Py_DECREF(self->name);
- Py_DECREF(self->cpp_type);
- Py_DECREF(self->label);
- Py_DECREF(self->id);
- self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
-}
-
-typedef struct {
- PyObject_HEAD
-
- const google::protobuf::DescriptorPool* pool;
-} CDescriptorPool;
-
-static void CDescriptorPoolDealloc(CDescriptorPool* self);
-
-static PyObject* CDescriptorPool_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->full_name = PyString_FromString(
- field_descriptor->full_name().c_str());
- cfield_descriptor->name = PyString_FromString(
- field_descriptor->name().c_str());
- cfield_descriptor->cpp_type = PyLong_FromLong(field_descriptor->cpp_type());
- cfield_descriptor->label = PyLong_FromLong(field_descriptor->label());
- cfield_descriptor->id = PyLong_FromVoidPtr(cfield_descriptor);
- return reinterpret_cast<PyObject*>(cfield_descriptor);
-}
-
-static PyObject* CDescriptorPool_FindFieldByName(
- 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 = 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 CDescriptorPool_NewCDescriptor(field_descriptor);
-}
-
-static PyObject* CDescriptorPool_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 CDescriptorPool_NewCDescriptor(field_descriptor);
-}
-
-static PyMethodDef CDescriptorPoolMethods[] = {
- { C("FindFieldByName"),
- (PyCFunction)CDescriptorPool_FindFieldByName,
- METH_O,
- C("Searches for a field descriptor by full name.") },
- { C("FindExtensionByName"),
- (PyCFunction)CDescriptorPool_FindExtensionByName,
- METH_O,
- C("Searches for extension descriptor by full name.") },
- {NULL}
-};
-
-PyTypeObject CDescriptorPool_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- C("google.protobuf.internal."
- "_net_proto2___python."
- "CFieldDescriptor"), // tp_name
- sizeof(CDescriptorPool), // tp_basicsize
- 0, // tp_itemsize
- (destructor)CDescriptorPoolDealloc, // 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
- CDescriptorPoolMethods, // 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
-};
-
-static void CDescriptorPoolDealloc(CDescriptorPool* self) {
- self->ob_type->tp_free(reinterpret_cast<PyObject*>(self));
-}
-
-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<PyObject*>(cdescriptor_pool);
-}
-
-PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
- char* message_type;
- Py_ssize_t message_len;
-
- if (PyString_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;
- }
-
- const google::protobuf::FileDescriptor* descriptor = GetDescriptorPool()->BuildFile(
- file_proto);
- if (descriptor == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "Couldn't build proto file into descriptor pool!");
- 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/setup.py b/python/setup.py
index efe5589a..24a446a9 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -72,7 +72,11 @@ def GenerateUnittestProtos():
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/compatibility_mode_test.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")
@@ -102,6 +106,22 @@ def MakeTestSuite():
import google.protobuf.internal.message_cpp_test as message_cpp_test
import google.protobuf.internal.reflection_cpp_generated_test \
as reflection_cpp_generated_test
+ import google.protobuf.internal.api_implementation_default_test \
+ as api_implementation_default_test
+ import google.protobuf.internal.descriptor_cpp2_test as descriptor_cpp2_test
+ import google.protobuf.internal.descriptor_python_test \
+ as descriptor_python_test
+ import google.protobuf.internal.message_factory_cpp2_test \
+ as message_factory_cpp2_test
+ import google.protobuf.internal.message_factory_cpp_test \
+ as message_factory_cpp_test
+ import google.protobuf.internal.message_factory_python_test \
+ as message_factory_python_test
+ import google.protobuf.internal.message_python_test as message_python_test
+ import google.protobuf.internal.reflection_cpp2_generated_test \
+ as reflection_cpp2_generated_test
+ import google.protobuf.internal.symbol_database_test as symbol_database_test
+ import google.protobuf.internal.text_encoding_test as text_encoding_test
loader = unittest.defaultTestLoader
suite = unittest.TestSuite()
@@ -110,7 +130,23 @@ def MakeTestSuite():
reflection_test,
service_reflection_test,
text_format_test,
- wire_format_test ]:
+ wire_format_test,
+ unknown_fields_test,
+ descriptor_pool_test,
+ message_factory_test,
+ message_cpp_test,
+ reflection_cpp_generated_test,
+ api_implementation_default_test,
+ descriptor_cpp2_test,
+ descriptor_python_test,
+ message_factory_cpp2_test,
+ message_factory_cpp_test,
+ message_factory_python_test,
+ message_python_test,
+ reflection_cpp2_generated_test,
+ symbol_database_test,
+ text_encoding_test ]:
+
suite.addTest(loader.loadTestsFromModule(test))
return suite
diff --git a/src/Makefile.am b/src/Makefile.am
index 40696035..ada36ad4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,11 +40,13 @@ MAINTAINERCLEANFILES = \
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_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 \
@@ -73,6 +75,7 @@ nobase_include_HEADERS = \
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 \
@@ -97,7 +100,7 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/common.cc \
google/protobuf/stubs/once.cc \
google/protobuf/stubs/hash.h \
- google/protobuf/stubs/map-util.h \
+ google/protobuf/stubs/map_util.h \
google/protobuf/stubs/stl_util.h \
google/protobuf/stubs/stringprintf.cc \
google/protobuf/stubs/stringprintf.h \
@@ -134,6 +137,7 @@ 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 \
@@ -174,6 +178,8 @@ libprotoc_la_SOURCES = \
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 \
@@ -185,14 +191,22 @@ 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 \
@@ -229,9 +243,10 @@ 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/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_extensions_data.txt \
google/protobuf/package_info.h \
google/protobuf/io/package_info.h \
google/protobuf/compiler/package_info.h \
@@ -352,7 +367,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 \
-I$(top_builddir)/gtest/include \
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 455c239a..bc4800a6 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -44,6 +44,11 @@ namespace compiler {
CodeGenerator::~CodeGenerator() {}
GeneratorContext::~GeneratorContext() {}
+io::ZeroCopyOutputStream*
+GeneratorContext::OpenForAppend(const string& filename) {
+ return NULL;
+}
+
io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert(
const string& filename, const string& insertion_point) {
GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion.";
@@ -58,8 +63,7 @@ void GeneratorContext::ListParsedFiles(
// Parses a set of comma-delimited name/value pairs.
void ParseGeneratorParameter(const string& text,
vector<pair<string, string> >* output) {
- vector<string> parts;
- SplitStringUsing(text, ",", &parts);
+ vector<string> 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 252f68d1..541f784c 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -104,6 +104,9 @@ class LIBPROTOC_EXPORT GeneratorContext {
// 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
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index b9293c97..358d6462 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -49,8 +49,10 @@
#include <ctype.h>
#include <google/protobuf/stubs/hash.h>
+#include <memory>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/plugin.pb.h>
@@ -64,7 +66,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -160,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<string> parts;
- SplitStringUsing(filename, "/", &parts);
+ vector<string> parts = Split(filename, "/", true);
string path_so_far = prefix;
for (int i = 0; i < parts.size() - 1; i++) {
path_so_far += parts[i];
@@ -252,6 +253,7 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
// 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<const FileDescriptor*>* output) {
@@ -271,7 +273,8 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
class CommandLineInterface::MemoryOutputStream
: public io::ZeroCopyOutputStream {
public:
- MemoryOutputStream(GeneratorContextImpl* 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();
@@ -290,6 +293,9 @@ class CommandLineInterface::MemoryOutputStream
// 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<io::StringOutputStream> inner_;
};
@@ -434,7 +440,13 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
const string& filename) {
- return new MemoryOutputStream(this, filename);
+ return new MemoryOutputStream(this, filename, false);
+}
+
+io::ZeroCopyOutputStream*
+CommandLineInterface::GeneratorContextImpl::OpenForAppend(
+ const string& filename) {
+ return new MemoryOutputStream(this, filename, true);
}
io::ZeroCopyOutputStream*
@@ -446,9 +458,10 @@ CommandLineInterface::GeneratorContextImpl::OpenForInsert(
// -------------------------------------------------------------------
CommandLineInterface::MemoryOutputStream::MemoryOutputStream(
- GeneratorContextImpl* 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_)) {
}
@@ -471,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;
}
@@ -565,6 +582,7 @@ 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),
@@ -632,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);
@@ -721,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;
}
@@ -735,6 +774,7 @@ 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;
@@ -889,7 +929,8 @@ bool CommandLineInterface::ParseArgument(const char* arg,
*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.
@@ -919,8 +960,8 @@ 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<string> parts;
- SplitStringUsing(value, kPathSeparator, &parts);
+ vector<string> parts = Split(
+ value, kPathSeparator, true);
for (int i = 0; i < parts.size(); i++) {
string virtual_path;
@@ -1061,6 +1102,19 @@ CommandLineInterface::InterpretArgument(const string& name,
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 =
@@ -1082,8 +1136,8 @@ CommandLineInterface::InterpretArgument(const string& name,
} else {
// 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;
+ cerr << "Cannot use --encode, --decode or print .proto info and "
+ "generate code at the same time." << endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -1151,7 +1205,12 @@ void CommandLineInterface::PrintHelpText() {
" 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"
@@ -1431,6 +1490,113 @@ void CommandLineInterface::GetTransitiveDependencies(
}
}
+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<int, int> FieldRange;
+void GatherOccupiedFieldRanges(const Descriptor* descriptor,
+ set<FieldRange>* ranges,
+ vector<const Descriptor*>* nested_messages) {
+ set<const Descriptor*> 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<FieldRange>& ranges) {
+ string output;
+ StringAppendF(&output, "%-35s free:", name.c_str());
+ int next_free_number = 1;
+ for (set<FieldRange>::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<FieldRange> ranges;
+ vector<const Descriptor*> 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 86ea9bde..3b734150 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -48,8 +48,9 @@
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<typename T> class RepeatedPtrField; // repeated_field.h
@@ -259,6 +260,22 @@ class LIBPROTOC_EXPORT CommandLineInterface {
set<const FileDescriptor*>* already_seen,
RepeatedPtrField<FileDescriptorProto>* 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]).
@@ -295,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).
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 16559923..9e244da3 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 <unistd.h>
#endif
+#include <memory>
#include <vector>
#include <google/protobuf/descriptor.pb.h>
@@ -126,6 +127,9 @@ class CommandLineInterfaceTest : public testing::Test {
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);
@@ -182,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<CodeGenerator*> mock_generators_to_delete_;
@@ -224,7 +231,7 @@ 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");
@@ -255,8 +262,7 @@ void CommandLineInterfaceTest::TearDown() {
}
void CommandLineInterfaceTest::Run(const string& command) {
- vector<string> args;
- SplitStringUsing(command, " ", &args);
+ vector<string> args = Split(command, " ", true);
if (!disallow_plugins_) {
cli_.AllowPlugins("prefix-");
@@ -295,18 +301,20 @@ void CommandLineInterfaceTest::Run(const string& command) {
}
}
- scoped_array<const char*> argv(new const char*[args.size()]);
+ scoped_array<const char*> 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();
}
+ CaptureTestStdout();
CaptureTestStderr();
return_code_ = cli_.Run(args.size(), argv.get());
error_text_ = GetCapturedTestStderr();
+ captured_stdout_ = GetCapturedTestStdout();
}
// -------------------------------------------------------------------
@@ -318,16 +326,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));
}
// -------------------------------------------------------------------
@@ -414,14 +426,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) {
@@ -813,7 +829,7 @@ 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());
@@ -838,7 +854,7 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
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());
// Source code info included.
EXPECT_TRUE(descriptor_set.file(0).has_source_code_info());
@@ -863,7 +879,7 @@ 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]);
@@ -894,7 +910,7 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
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]);
@@ -1393,6 +1409,70 @@ 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();
+ 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");
+}
+
// ===================================================================
// Test for --encode and --decode. Note that it would be easier to do this
@@ -1412,7 +1492,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));
}
@@ -1446,7 +1526,7 @@ class EncodeDecodeTest : public testing::Test {
SplitStringUsing(command, " ", &args);
args.push_back("--proto_path=" + TestSourceDir());
- scoped_array<const char*> argv(new const char*[args.size()]);
+ scoped_array<const char*> argv(new const char* [args.size()]);
for (int i = 0; i < args.size(); i++) {
argv[i] = args[i].c_str();
}
@@ -1467,7 +1547,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.
@@ -1476,7 +1556,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);
}
@@ -1496,22 +1576,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 b7c1766b..48da534c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -48,7 +48,7 @@
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -93,9 +93,9 @@ class MockGeneratorContext : public GeneratorContext {
<< "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 "
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 67c12d7a..0c4796f6 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 Options& options)
: descriptor_(descriptor),
classname_(ClassName(descriptor, false)),
- options_(options) {
+ 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_ + "_";
@@ -97,9 +116,13 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
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 2e85a0bd..98cbdf69 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -89,6 +89,8 @@ class EnumGenerator {
const EnumDescriptor* descriptor_;
string classname_;
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 6e1620d4..2723c04a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -51,7 +51,8 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
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
@@ -83,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"
" assert($type$_IsValid(value));\n"
" set_has_$name$();\n"
" $name$_ = value;\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
@@ -121,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");
@@ -153,6 +161,52 @@ 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,
const Options& options)
@@ -166,7 +220,8 @@ void RepeatedEnumFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField<int> $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");
}
@@ -187,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"
" 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"
" 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<int>&\n"
"$classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
"inline ::google::protobuf::RepeatedField<int>*\n"
"$classname$::mutable_$name$() {\n"
+ " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
"}\n");
}
@@ -238,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");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index 65770083..1da1623a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -63,13 +63,30 @@ class EnumFieldGenerator : public FieldGenerator {
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> 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,
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 0786176b..beea8bac 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 <google/protobuf/compiler/cpp/cpp_field.h>
+#include <memory>
+
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
#include <google/protobuf/compiler/cpp/cpp_string_field.h>
@@ -68,6 +70,12 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
(*variables)["cppget"] = "Get";
}
+void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ (*variables)["oneof_prefix"] = descriptor->containing_oneof()->name() + "_.";
+ (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
+}
+
FieldGenerator::~FieldGenerator() {}
void FieldGenerator::
@@ -84,8 +92,9 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor,
const Options& options)
- : descriptor_(descriptor),
- field_generators_(new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
+ : descriptor_(descriptor),
+ field_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->field_count()]) {
// Construct all the FieldGenerators.
for (int i = 0; i < descriptor->field_count(); i++) {
field_generators_[i].reset(MakeGenerator(descriptor->field(i), options));
@@ -109,6 +118,21 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
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 EnumOneofFieldGenerator(field, options);
+ default:
+ return new PrimitiveOneofFieldGenerator(field, options);
+ }
} else {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_MESSAGE:
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index f7d99b15..e4340672 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -36,9 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
#include <map>
+#include <memory>
#include <string>
-#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>
@@ -61,6 +61,9 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
map<string, string>* variables,
const Options& options);
+void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables);
+
class FieldGenerator {
public:
FieldGenerator() {}
@@ -71,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;
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 3d869a37..f7f2cdda 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 <google/protobuf/compiler/cpp/cpp_file.h>
+#include <memory>
+#include <set>
+
#include <google/protobuf/compiler/cpp/cpp_enum.h>
#include <google/protobuf/compiler/cpp/cpp_service.h>
#include <google/protobuf/compiler/cpp/cpp_extension.h>
@@ -50,18 +53,17 @@ namespace cpp {
// ===================================================================
-FileGenerator::FileGenerator(const FileDescriptor* file,
- const Options& options)
- : file_(file),
- message_generators_(
- new scoped_ptr<MessageGenerator>[file->message_type_count()]),
- enum_generators_(
- new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
- service_generators_(
- new scoped_ptr<ServiceGenerator>[file->service_count()]),
- extension_generators_(
- new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
- options_(options) {
+FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
+ : file_(file),
+ message_generators_(
+ new scoped_ptr<MessageGenerator>[file->message_type_count()]),
+ enum_generators_(
+ new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
+ service_generators_(
+ new scoped_ptr<ServiceGenerator>[file->service_count()]),
+ extension_generators_(
+ new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
+ options_(options) {
for (int i = 0; i < file->message_type_count(); i++) {
message_generators_[i].reset(
@@ -153,19 +155,28 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"#include <google/protobuf/service.h>\n");
}
- if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
+ if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
printer->Print(
"#include <google/protobuf/unknown_field_set.h>\n");
}
+ set<string> public_import_names;
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ public_import_names.insert(file_->public_dependency(i)->name());
+ }
+
for (int i = 0; i < file_->dependency_count(); i++) {
+ const 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");
@@ -248,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) {
@@ -317,6 +329,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"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 <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
+ }
+
if (HasDescriptorMethods(file_)) {
printer->Print(
"#include <google/protobuf/descriptor.h>\n"
@@ -542,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<string> dependency_package_parts;
- SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
- printer->Print("::");
- for (int j = 0; j < dependency_package_parts.size(); j++) {
- printer->Print("$name$::",
- "name", dependency_package_parts[j]);
- }
+ 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_)) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 2deefaa8..07970971 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -35,6 +35,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
+#include <memory>
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
@@ -85,7 +86,6 @@ class FileGenerator {
// E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}.
vector<string> package_parts_;
-
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 1813510b..a43e993b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <vector>
+#include <memory>
#include <utility>
#include <google/protobuf/compiler/cpp/cpp_file.h>
@@ -102,7 +103,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
// Generate header.
{
scoped_ptr<io::ZeroCopyOutputStream> output(
- generator_context->Open(basename + ".h"));
+ generator_context->Open(basename + ".h"));
io::Printer printer(output.get(), '$');
file_generator.GenerateHeader(&printer);
}
@@ -110,7 +111,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
// Generate cc file.
{
scoped_ptr<io::ZeroCopyOutputStream> output(
- generator_context->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_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 28911ab0..2c94b3a9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -82,6 +82,22 @@ hash_set<string> MakeKeywordsMap() {
hash_set<string> 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.
@@ -107,22 +123,6 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) {
return result;
}
-// 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
-
const char kThickSeparator[] =
"// ===================================================================\n";
const char kThinSeparator[] =
@@ -256,27 +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(-0x8000000000000000),
+ kint64min_value_error);
+ return "GOOGLE_LONGLONG(-0x8000000000000000)";
+ }
+ return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")";
+}
+
string DefaultValue(const FieldDescriptor* field) {
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
- // gcc rejects the decimal form of kint32min and kint64min.
- if (field->default_value_int32() == kint32min) {
- // Make sure we are in a 2's complement system.
- GOOGLE_COMPILE_ASSERT(kint32min == -0x80000000, kint32min_value_error);
- return "-0x80000000";
- }
- 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:
- // See the comments for CPPTYPE_INT32.
- if (field->default_value_int64() == kint64min) {
- // Make sure we are in a 2's complement system.
- GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(-0x8000000000000000),
- kint64min_value_error);
- return "GOOGLE_LONGLONG(-0x8000000000000000)";
- }
- 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: {
@@ -319,7 +327,7 @@ 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 "\"" + EscapeTrigraphs(
CEscape(field->default_value_string())) +
@@ -366,11 +374,39 @@ 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;
@@ -432,6 +468,26 @@ bool HasEnumDefinitions(const FileDescriptor* file) {
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 526e19cc..27444d5a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -103,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);
@@ -115,14 +121,23 @@ 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);
// Escape C++ trigraphs by escaping question marks to \?
string EscapeTrigraphs(const string& to_escape);
-// Do message classes in this file keep track of unknown fields?
-inline bool HasUnknownFields(const FileDescriptor* file) {
+// 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;
}
@@ -178,6 +193,11 @@ void PrintHandlingOptionalStaticInitializers(
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
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 1ea4f13d..962ff535 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -35,6 +35,8 @@
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
#include <map>
+#include <memory>
+#include <set>
#include <utility>
#include <vector>
#include <google/protobuf/compiler/cpp/cpp_message.h>
@@ -74,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) {
@@ -255,8 +248,9 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
aligned_to_4.push_back(field_group);
}
// Sort by preferred location to keep fields as close to their original
- // location as possible.
- sort(aligned_to_4.begin(), aligned_to_4.end());
+ // 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.
@@ -271,9 +265,8 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
}
aligned_to_8.push_back(field_group);
}
- // Sort by preferred location to keep fields as close to their original
- // location as possible.
- sort(aligned_to_8.begin(), aligned_to_8.end());
+ // Sort by preferred location.
+ stable_sort(aligned_to_8.begin(), aligned_to_8.end());
// Now pull out all the FieldDescriptors in order.
fields->clear();
@@ -284,22 +277,26 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
}
}
+string MessageTypeProtoName(const FieldDescriptor* field) {
+ return field->message_type()->full_name();
+}
+
}
// ===================================================================
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
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<EnumGenerator>[
- descriptor->enum_type_count()]),
- extension_generators_(new scoped_ptr<ExtensionGenerator>[
- descriptor->extension_count()]) {
+ : 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<EnumGenerator>[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(
@@ -383,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::
@@ -403,6 +408,18 @@ 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];
@@ -426,14 +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()) {
+ if (field->containing_oneof()) {
+ // Clear this field only if it is the active field in this oneof,
+ // otherwise ignore
printer->Print(vars,
- " clear_has_$name$();\n");
+ "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.
@@ -441,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<string, string> 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::
@@ -455,6 +528,7 @@ GenerateClassDefinition(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = classname_;
vars["field_count"] = SimpleItoa(descriptor_->field_count());
+ vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count());
if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
} else {
@@ -479,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"
@@ -489,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.
@@ -502,6 +586,33 @@ 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"
@@ -545,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<const FieldDescriptor*> 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(
@@ -621,13 +762,44 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(
"inline void set_has_$name$();\n",
"name", FieldName(descriptor_->field(i)));
- printer->Print(
- "inline void clear_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<int> 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
@@ -642,42 +814,92 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
- if (HasUnknownFields(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(
"::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
"\n");
+ } else {
+ printer->Print(
+ "::std::string _unknown_fields_;\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<const FieldDescriptor*> fields;
+ hash_map<string, int> fieldname_to_chunk;
for (int i = 0; i < descriptor_->field_count(); i++) {
- fields.push_back(descriptor_->field(i));
+ 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<string> >(1);
for (int i = 0; i < fields.size(); ++i) {
- field_generators_.get(fields[i]).GeneratePrivateMembers(printer);
+ 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<string>());
+ }
+ runs_of_fields_.back().push_back(fieldname);
+ } else if (!runs_of_fields_.back().empty()) {
+ runs_of_fields_.push_back(vector<string>());
+ }
+ }
+
+ // 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:
- // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it.
- printer->Print(
- "\n"
- "mutable int _cached_size_;\n");
+ if (need_to_emit_cached_size) {
+ printer->Print(cached_size_decl.c_str());
+ need_to_emit_cached_size = false;
+ }
- // Generate _has_bits_.
- if (descriptor_->field_count() > 0) {
+ // Generate _oneof_case_.
+ if (descriptor_->oneof_decl_count() > 0) {
printer->Print(vars,
- "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n"
- "\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"
+ "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n"
"\n");
}
@@ -710,6 +932,7 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Outdent();
printer->Print(vars, "};");
+ GOOGLE_DCHECK(!need_to_emit_cached_size);
}
void MessageGenerator::
@@ -721,6 +944,23 @@ GenerateInlineMethods(io::Printer* printer) {
}
GenerateFieldAccessorDefinitions(printer);
+
+ // Generate oneof_case() functions.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ map<string, string> 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::
@@ -731,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);
}
@@ -783,6 +1042,14 @@ 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,
@@ -830,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);
@@ -861,6 +1135,11 @@ 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_);
@@ -918,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");
@@ -977,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();
@@ -999,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");
}
@@ -1020,10 +1331,21 @@ 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);
+ }
+ }
+
+ // 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(
@@ -1042,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));
+ }
}
}
@@ -1063,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"
@@ -1082,7 +1410,14 @@ GenerateStructors(io::Printer* printer) {
const FieldDescriptor* field = descriptor_->field(i);
if (!field->is_repeated() &&
- field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ 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.
@@ -1091,8 +1426,12 @@ GenerateStructors(io::Printer* printer) {
" $name$_ = const_cast< $type$*>(\n"
" $type$::internal_default_instance());\n",
// Vars.
- "name", FieldName(field),
+ "name", name,
"type", FieldMessageTypeName(field));
+ } else if (field->containing_oneof() &&
+ HasDescriptorMethods(descriptor_->file())) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateConstructorCode(printer);
}
}
printer->Print(
@@ -1105,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);
@@ -1116,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);
@@ -1166,13 +1509,25 @@ GenerateStructors(io::Printer* printer) {
"}\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::
@@ -1181,64 +1536,133 @@ GenerateClear(io::Printer* printer) {
"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<int> step2_indices;
+ hash_map<string, int> fieldname_to_chunk;
+ hash_map<int, string> memsets_for_chunk;
+ hash_map<int, int> memset_field_count_for_chunk;
+ hash_set<string> handled; // fields that appear anywhere in memsets_for_chunk
+ hash_map<int, uint32> 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<uint32>(1) << (i % 32);
+ }
+ }
- if (!field->is_repeated()) {
- // 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(
- "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
- "index", SimpleItoa(field->index()));
- 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<char*>( \\\n"
+ " &reinterpret_cast<$classname$*>(16)->f) - \\\n"
+ " reinterpret_cast<char*>(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<string>& 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) {
+ // 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_$name$()) {\n",
- "name", FieldName(field));
+ "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);
@@ -1247,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();
@@ -1260,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",
@@ -1274,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) {
@@ -1352,13 +1849,43 @@ 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()) {
+ 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) {
@@ -1394,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();
@@ -1465,14 +1995,39 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
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<const FieldDescriptor*> 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.
@@ -1482,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<const FieldDescriptor*> ordered_fields(
- SortFieldsByNumber(descriptor_));
-
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = ordered_fields[i];
@@ -1502,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(
@@ -1523,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();
@@ -1544,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
@@ -1568,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(
@@ -1578,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.
@@ -1617,7 +2171,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
}
printer->Print(") {\n");
- if (HasUnknownFields(descriptor_->file())) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
PrintHandlingOptionalStaticInitializers(
descriptor_->file(), printer,
// With static initializers.
@@ -1630,9 +2184,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
PrintHandlingOptionalStaticInitializers(
descriptor_->file(), printer,
// With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_));\n",
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " &unknown_fields_stream));\n",
// Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance()));\n");
+ " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+ " &unknown_fields_stream));\n");
}
printer->Print(
" continue;\n"
@@ -1640,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) {
@@ -1660,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(
@@ -1719,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;
@@ -1735,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");
@@ -1752,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");
@@ -1770,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"
@@ -1781,7 +2357,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
void MessageGenerator::
GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
scoped_array<const FieldDescriptor*> ordered_fields(
- SortFieldsByNumber(descriptor_));
+ SortFieldsByNumber(descriptor_));
vector<const Descriptor::ExtensionRange*> sorted_extensions;
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
@@ -1810,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) {
@@ -1827,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");
}
}
@@ -1838,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"
@@ -1865,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.
@@ -1915,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(
@@ -1930,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,
@@ -1987,16 +2602,26 @@ GenerateIsInitialized(io::Printer* printer) {
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 a7e43d9c..3b4085dc 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -35,8 +35,9 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
+#include <memory>
#include <string>
-#include <google/protobuf/stubs/common.h>
+#include <vector>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>
@@ -132,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);
@@ -156,9 +158,11 @@ class MessageGenerator {
string classname_;
Options options_;
FieldGeneratorMap field_generators_;
+ vector< vector<string> > runs_of_fields_; // that might be trivially cleared
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
scoped_array<scoped_ptr<ExtensionGenerator> > 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 447f975f..08a4f257 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -53,6 +53,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(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
@@ -78,14 +84,15 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $name$() const$deprecation$;\n"
"inline $type$* mutable_$name$()$deprecation$;\n"
- "inline $type$* release_$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");
+ "inline const $type$& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n");
PrintHandlingOptionalStaticInitializers(
variables_, descriptor_->file(), printer,
@@ -99,9 +106,10 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"inline $type$* $classname$::mutable_$name$() {\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"
+ "inline $type$* $classname$::$release_name$() {\n"
" clear_has_$name$();\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
@@ -115,6 +123,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" } else {\n"
" clear_has_$name$();\n"
" }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
@@ -178,6 +187,69 @@ 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,
const Options& options)
@@ -210,21 +282,26 @@ void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const $type$& $classname$::$name$(int index) const {\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 a5ed68a5..4c01795c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -63,13 +63,30 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> 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,
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 5c4aa4fb..697b95f0 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 <memory>
+
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -73,7 +75,7 @@ class TestGenerator : public CodeGenerator {
void TryInsert(const string& filename, const string& insertion_point,
GeneratorContext* context) const {
scoped_ptr<io::ZeroCopyOutputStream> output(
- context->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 1c35fefa..cb72fb1d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -93,6 +93,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["wire_format_field_type"] =
"::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
static_cast<FieldDescriptorProto_Type>(descriptor->type()));
+ (*variables)["full_name"] = descriptor->full_name();
}
} // namespace
@@ -124,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_has_$name$();\n"
" $name$_ = value;\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
@@ -191,6 +194,62 @@ 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,
const Options& options)
@@ -235,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");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 48249c40..1f66c9df 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -63,13 +63,31 @@ class PrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> 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,
diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h
index 820f9f5f..493f314a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_service.h
+++ b/src/google/protobuf/compiler/cpp/cpp_service.h
@@ -37,7 +37,6 @@
#include <map>
#include <string>
-#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 0b58b981..d41b5bcd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -53,10 +53,16 @@ void SetStringVariables(const FieldDescriptor* descriptor,
(*variables)["default_length"] =
SimpleItoa(descriptor->default_value_string().length());
(*variables)["default_variable"] = descriptor->default_value_string().empty()
- ? "&::google::protobuf::internal::GetEmptyString()"
+ ? "&::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
@@ -75,6 +81,10 @@ StringFieldGenerator::~StringFieldGenerator() {}
void StringFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
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");
}
@@ -113,7 +123,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline void set_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
"inline ::std::string* mutable_$name$()$deprecation$;\n"
- "inline ::std::string* release_$name$()$deprecation$;\n"
+ "inline ::std::string* $release_name$()$deprecation$;\n"
"inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
@@ -128,6 +138,7 @@ 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"
@@ -136,6 +147,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $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_has_$name$();\n"
@@ -143,6 +155,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $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"
@@ -151,6 +164,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $name$_ = new ::std::string;\n"
" }\n"
" $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
+ " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
"inline ::std::string* $classname$::mutable_$name$() {\n"
" set_has_$name$();\n"
@@ -164,9 +178,10 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
}
printer->Print(variables_,
" }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::std::string* $classname$::release_$name$() {\n"
+ "inline ::std::string* $classname$::$release_name$() {\n"
" clear_has_$name$();\n"
" if ($name$_ == $default_variable$) {\n"
" return NULL;\n"
@@ -187,6 +202,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" clear_has_$name$();\n"
" $name$_ = const_cast< ::std::string*>($default_variable$);\n"
" }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
}
@@ -263,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");
}
}
@@ -274,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");
}
@@ -288,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"
@@ -308,6 +327,125 @@ 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<const char*>(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,
const Options& options)
@@ -365,43 +503,53 @@ void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline const ::std::string& $classname$::$name$(int index) const {\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<const char*>(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<const char*>(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");
}
@@ -434,10 +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"
+ "::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");
+ " ::google::protobuf::internal::WireFormat::PARSE,\n"
+ " \"$name$\");\n");
}
}
@@ -448,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"
@@ -465,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 3264134a..65f605c0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -52,6 +52,7 @@ class StringFieldGenerator : public FieldGenerator {
// 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;
@@ -67,13 +68,31 @@ class StringFieldGenerator : public FieldGenerator {
void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
void GenerateByteSize(io::Printer* printer) const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> 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,
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 e14a818c..8b9ff5ae 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -98,6 +98,7 @@ 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 {}
@@ -107,6 +108,14 @@ message TestConflictingSymbolNames {
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;
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 1eae29b5..4ef1da1e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -46,6 +46,7 @@
#include <google/protobuf/compiler/cpp/cpp_unittest.h>
+#include <memory>
#include <vector>
#include <google/protobuf/unittest.pb.h>
@@ -53,6 +54,7 @@
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
#include <google/protobuf/unittest_no_generic_services.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/io/coded_stream.h>
@@ -148,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(-0x8000000000000000)", Int64ToString(kint64min));
+ EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max));
+}
+
TEST(GeneratedMessageTest, FloatingPointDefaults) {
const unittest::TestExtremeDefaultValues& extreme_default =
unittest::TestExtremeDefaultValues::default_instance();
@@ -233,11 +248,10 @@ TEST(GeneratedMessageTest, ReleaseString) {
message.set_default_string("blah");
EXPECT_TRUE(message.has_default_string());
- string* str = message.release_default_string();
+ scoped_ptr<string> str(message.release_default_string());
EXPECT_FALSE(message.has_default_string());
ASSERT_TRUE(str != NULL);
EXPECT_EQ("blah", *str);
- delete str;
EXPECT_EQ(NULL, message.release_default_string());
EXPECT_FALSE(message.has_default_string());
@@ -253,12 +267,11 @@ TEST(GeneratedMessageTest, ReleaseMessage) {
EXPECT_FALSE(message.has_optional_nested_message());
message.mutable_optional_nested_message()->set_bb(1);
- unittest::TestAllTypes::NestedMessage* nest =
- message.release_optional_nested_message();
+ scoped_ptr<unittest::TestAllTypes::NestedMessage> nest(
+ message.release_optional_nested_message());
EXPECT_FALSE(message.has_optional_nested_message());
ASSERT_TRUE(nest != NULL);
EXPECT_EQ(1, nest->bb());
- delete nest;
EXPECT_EQ(NULL, message.release_optional_nested_message());
EXPECT_FALSE(message.has_optional_nested_message());
@@ -381,6 +394,7 @@ TEST(GeneratedMessageTest, StringCharStarLength) {
EXPECT_EQ("wx", message.repeated_string(0));
}
+
TEST(GeneratedMessageTest, CopyFrom) {
unittest::TestAllTypes message1, message2;
@@ -393,6 +407,7 @@ TEST(GeneratedMessageTest, CopyFrom) {
TestUtil::ExpectAllFieldsSet(message2);
}
+
TEST(GeneratedMessageTest, SwapWithEmpty) {
unittest::TestAllTypes message1, message2;
TestUtil::SetAllFields(&message1);
@@ -763,6 +778,9 @@ 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;
@@ -840,6 +858,40 @@ 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
@@ -887,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.)
@@ -915,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);
@@ -989,6 +1044,20 @@ TEST(GeneratedEnumTest, GetEnumDescriptor) {
GetEnumDescriptor<unittest::TestSparseEnum>());
}
+enum NonProtoEnum {
+ kFoo = 1,
+};
+
+TEST(GeneratedEnumTest, IsProtoEnumTypeTrait) {
+ EXPECT_TRUE(is_proto_enum<unittest::TestAllTypes::NestedEnum>::value);
+ EXPECT_TRUE(is_proto_enum<unittest::ForeignEnum>::value);
+ EXPECT_TRUE(is_proto_enum<unittest::TestEnumWithDupValue>::value);
+ EXPECT_TRUE(is_proto_enum<unittest::TestSparseEnum>::value);
+
+ EXPECT_FALSE(is_proto_enum<int>::value);
+ EXPECT_FALSE(is_proto_enum<NonProtoEnum>::value);
+}
+
#endif // PROTOBUF_TEST_NO_DESCRIPTORS
// ===================================================================
@@ -1288,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<string> 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<unittest::TestOneof2_NestedMessage> 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<const Message*>(&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<uint8*>(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<uint8*>(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<uint8*>(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<uint8*>(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<uint8*>(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<uint8*>(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/importer.cc b/src/google/protobuf/compiler/importer.cc
index 422f759f..701ac483 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -43,6 +43,7 @@
#include <errno.h>
#include <algorithm>
+#include <memory>
#include <google/protobuf/compiler/importer.h>
@@ -124,7 +125,8 @@ bool SourceTreeDescriptorDatabase::FindFileByName(
scoped_ptr<io::ZeroCopyInputStream> 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() {}
@@ -239,9 +254,9 @@ static string CanonicalizePath(string path) {
}
#endif
- vector<string> parts;
vector<string> canonical_parts;
- SplitStringUsing(path, "/", &parts); // Note: Removes empty parts.
+ vector<string> parts = Split(
+ path, "/", true); // Note: Removes empty parts.
for (int i = 0; i < parts.size(); i++) {
if (parts[i] == ".") {
// Ignore.
@@ -249,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;
@@ -395,8 +410,8 @@ DiskSourceTree::DiskFileToVirtualFile(
bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
string* disk_file) {
- scoped_ptr<io::ZeroCopyInputStream> stream(OpenVirtualFile(virtual_file,
- disk_file));
+ scoped_ptr<io::ZeroCopyInputStream> stream(
+ OpenVirtualFile(virtual_file, disk_file));
return stream != NULL;
}
@@ -404,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) {
@@ -412,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;
}
@@ -429,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 7a62fa0e..0171d2fa 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,7 +283,9 @@ 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 {
@@ -285,6 +297,7 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree {
: virtual_path(virtual_path_param), disk_path(disk_path_param) {}
};
vector<Mapping> 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 56fad56e..b54d9b73 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 <google/protobuf/stubs/hash.h>
+#include <memory>
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/stubs/strutil.h>
@@ -92,6 +93,10 @@ class MockSourceTree : public SourceTree {
}
}
+ string GetLastErrorMessage() {
+ return "File not found.";
+ }
+
private:
hash_map<string, const char*> 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<io::ZeroCopyInputStream> 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 00000000..67ac0ef3
--- /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 <google/protobuf/compiler/java/java_context.h>
+
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/map_util.h>
+
+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<const FieldDescriptor*> 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<const FieldDescriptor*>& fields) {
+ // Find out all fields that conflict with some other field in the same
+ // message.
+ vector<bool> is_conflict(fields.size());
+ vector<string> 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 00000000..c622b319
--- /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 <map>
+#include <memory>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+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<const FieldDescriptor*>& fields);
+
+ scoped_ptr<ClassNameResolver> name_resolver_;
+ map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_;
+ map<const OneofDescriptor*, OneofGeneratorInfo> 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
index 60b4f2ac..23127b7f 100644
--- a/src/google/protobuf/compiler/java/java_doc_comment.cc
+++ b/src/google/protobuf/compiler/java/java_doc_comment.cc
@@ -70,12 +70,10 @@ string EscapeJavadoc(const string& input) {
}
break;
case '@':
- // "{@" starts Javadoc markup.
- if (prev == '{') {
- result.append("&#64;");
- } else {
- result.push_back(c);
- }
+ // '@' 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("&#64;");
break;
case '<':
// Avoid interpretation as HTML.
@@ -117,8 +115,7 @@ static void WriteDocCommentBodyForLocation(
// HTML-escape them so that they don't accidentally close the doc comment.
comments = EscapeJavadoc(comments);
- vector<string> lines;
- SplitStringAllowEmpty(comments, "\n", &lines);
+ vector<string> lines = Split(comments, "\n");
while (!lines.empty() && lines.back().empty()) {
lines.pop_back();
}
diff --git a/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
index 28b6d8b4..41ea9f42 100644
--- a/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
@@ -46,6 +46,7 @@ TEST(JavaDocCommentTest, Escaping) {
EXPECT_EQ("{&#64;foo}", EscapeJavadoc("{@foo}"));
EXPECT_EQ("&lt;i&gt;&amp;&lt;/i&gt;", EscapeJavadoc("<i>&</i>"));
EXPECT_EQ("foo&#92;u1234bar", EscapeJavadoc("foo\\u1234bar"));
+ EXPECT_EQ("&#64;deprecated", EscapeJavadoc("@deprecated"));
}
// TODO(kenton): It's hard to write a robust test of the doc comments -- we
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index cfed815f..6bebe213 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -35,9 +35,11 @@
#include <map>
#include <string>
+#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
@@ -47,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 =
@@ -88,6 +104,9 @@ void EnumGenerator::Generate(io::Printer* printer) {
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");
}
@@ -178,15 +197,58 @@ 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$.descriptor\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(
diff --git a/src/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h
index 9a9e5742..af0cd15d 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,11 @@ class EnumGenerator {
};
vector<Alias> 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 ec0b067e..cab9bd0e 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -35,10 +35,12 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/java/java_enum_field.h>
-#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum_field.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
@@ -50,20 +52,19 @@ 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<string, string>* variables) {
- (*variables)["name"] =
- UnderscoresToCamelCase(descriptor);
- (*variables)["capitalized_name"] =
- UnderscoresToCapitalizedCamelCase(descriptor);
- (*variables)["constant_name"] = FieldConstantName(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)));
@@ -74,14 +75,28 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["on_changed"] =
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
- // For singular messages and builders, one bit is used for the hasField bit.
- (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
- (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
+ 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)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
- (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
- (*variables)["clear_has_field_bit_builder"] =
- GenerateClearBit(builderBitIndex);
+ (*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);
@@ -105,44 +120,53 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
// ===================================================================
-EnumFieldGenerator::
-EnumFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex,
- int builderBitIndex)
+ImmutableEnumFieldGenerator::
+ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex) {
- SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
+ builderBitIndex_(builderBitIndex),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-EnumFieldGenerator::~EnumFieldGenerator() {}
+ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {}
-int EnumFieldGenerator::GetNumBitsForMessage() const {
+int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
return 1;
}
-int EnumFieldGenerator::GetNumBitsForBuilder() const {
+int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
-void EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n");
+ 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 EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $type$ $name$_;\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public boolean has$capitalized_name$() {\n"
- " return $get_has_field_bit_message$;\n"
- "}\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"
@@ -150,15 +174,17 @@ GenerateMembers(io::Printer* printer) const {
"}\n");
}
-void EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $type$ $name$_ = $default$;\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public boolean has$capitalized_name$() {\n"
- " return $get_has_field_bit_builder$;\n"
- "}\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"
@@ -170,7 +196,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" if (value == null) {\n"
" throw new NullPointerException();\n"
" }\n"
- " $set_has_field_bit_builder$;\n"
+ " $set_has_field_bit_builder$\n"
" $name$_ = value;\n"
" $on_changed$\n"
" return this;\n"
@@ -178,129 +204,274 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
- " $clear_has_field_bit_builder$;\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 EnumFieldGenerator::
+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");
+ "$name$_ = $default$;\n"
+ "$clear_has_field_bit_builder$\n");
}
-void EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
+ 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 EnumFieldGenerator::
+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_,
- "if ($get_has_field_bit_from_local$) {\n"
- " $set_has_field_bit_to_local$;\n"
- "}\n"
"result.$name$_ = $name$_;\n");
}
-void EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
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_has_field_bit_message$;\n"
+ "} else {\n"
+ " $set_has_field_bit_message$\n"
" $name$_ = value;\n"
"}\n");
}
-void EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
// noop for enums
}
-void EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($get_has_field_bit_message$) {\n"
+ "if ($is_field_present_message$) {\n"
" output.writeEnum($number$, $name$_.getNumber());\n"
"}\n");
}
-void EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($get_has_field_bit_message$) {\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 EnumFieldGenerator::
+void ImmutableEnumFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"hash = (37 * hash) + $constant_name$;\n"
- "hash = (53 * hash) + hashEnum(get$capitalized_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");
}
-string EnumFieldGenerator::GetBoxedType() const {
- return ClassName(descriptor_->enum_type());
+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 {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " result.$oneof_name$_ = $oneof_name$_;\n"
+ "}\n");
+}
+
+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 (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_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeEnum($number$, (($type$) $oneof_name$_).getNumber());\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSize($number$, (($type$) $oneof_name$_).getNumber());\n"
+ "}\n");
}
// ===================================================================
-RepeatedEnumFieldGenerator::
-RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex,
- int builderBitIndex)
+RepeatedImmutableEnumFieldGenerator::
+RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex) {
- SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_);
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {}
-int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const {
+int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const {
return 0;
}
-int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const {
+int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
-void RepeatedEnumFieldGenerator::
+void RepeatedImmutableEnumFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -313,10 +484,11 @@ GenerateInterfaceMembers(io::Printer* printer) const {
"$deprecation$$type$ get$capitalized_name$(int index);\n");
}
-void RepeatedEnumFieldGenerator::
+void RepeatedImmutableEnumFieldGenerator::
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"
@@ -340,7 +512,7 @@ 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
@@ -409,7 +581,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<? extends $type$> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
- " super.addAll(values, $name$_);\n"
+ " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+ " values, $name$_);\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -423,24 +596,24 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n");
}
-void RepeatedEnumFieldGenerator::
+void RepeatedImmutableEnumFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
// noop for enums
}
-void RepeatedEnumFieldGenerator::
+void RepeatedImmutableEnumFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
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 RepeatedEnumFieldGenerator::
+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
@@ -460,7 +633,7 @@ GenerateMergingCode(io::Printer* printer) const {
"}\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.
@@ -472,22 +645,23 @@ GenerateBuildingCode(io::Printer* printer) const {
"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_,
+ " } else {\n"
" if (!$get_mutable_bit_parser$) {\n"
" $name$_ = new java.util.ArrayList<$type$>();\n"
" $set_mutable_bit_parser$;\n"
@@ -496,7 +670,7 @@ GenerateParsingCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedEnumFieldGenerator::
+void RepeatedImmutableEnumFieldGenerator::
GenerateParsingCodeFromPacked(io::Printer* printer) const {
// Wrap GenerateParsingCode's contents with a while loop.
@@ -514,7 +688,7 @@ 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"
@@ -522,7 +696,7 @@ GenerateParsingDoneCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedEnumFieldGenerator::
+void RepeatedImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_,
@@ -541,7 +715,7 @@ GenerateSerializationCode(io::Printer* printer) const {
}
}
-void RepeatedEnumFieldGenerator::
+void RepeatedImmutableEnumFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"{\n"
@@ -577,24 +751,25 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print("}\n");
}
-void RepeatedEnumFieldGenerator::
+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 RepeatedEnumFieldGenerator::
+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) + hashEnumList(get$capitalized_name$List());\n"
+ " hash = (53 * hash) + com.google.protobuf.Internal.hashEnumList(\n"
+ " get$capitalized_name$List());\n"
"}\n");
}
-string RepeatedEnumFieldGenerator::GetBoxedType() const {
- return ClassName(descriptor_->enum_type());
+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 90fae639..a3afb160 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -41,16 +41,26 @@
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,
- int messageBitIndex, int builderBitIndex);
- ~EnumFieldGenerator();
+ explicit ImmutableEnumFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableEnumFieldGenerator();
- // implements FieldGenerator ---------------------------------------
+ // implements ImmutableFieldGenerator ---------------------------------------
int GetNumBitsForMessage() const;
int GetNumBitsForBuilder() const;
void GenerateInterfaceMembers(io::Printer* printer) const;
@@ -70,22 +80,45 @@ class EnumFieldGenerator : public FieldGenerator {
string GetBoxedType() const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
const int messageBitIndex_;
const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator);
+};
+
+class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
+ public:
+ ImmutableEnumOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableEnumOneofFieldGenerator();
+
+ 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 RepeatedEnumFieldGenerator : public FieldGenerator {
+class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator {
public:
- explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex, int builderBitIndex);
- ~RepeatedEnumFieldGenerator();
+ explicit RepeatedImmutableEnumFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableEnumFieldGenerator();
- // implements FieldGenerator ---------------------------------------
+ // implements ImmutableFieldGenerator ---------------------------------------
int GetNumBitsForMessage() const;
int GetNumBitsForBuilder() const;
void GenerateInterfaceMembers(io::Printer* printer) const;
@@ -111,8 +144,10 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
map<string, string> 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 921fe658..c62dbfaf 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -33,74 +33,50 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/java_extension.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
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() {}
+ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {}
// Initializes the vars referenced in the generated code templates.
-void InitTemplateVars(const FieldDescriptor* descriptor,
- const string& scope,
- map<string, string>* vars_pointer) {
+void ExtensionGenerator::InitTemplateVars(const FieldDescriptor* descriptor,
+ const string& scope,
+ bool immutable,
+ ClassNameResolver* name_resolver,
+ map<string, string>* vars_pointer) {
map<string, string> &vars = *vars_pointer;
vars["scope"] = scope;
vars["name"] = UnderscoresToCamelCase(descriptor);
- vars["containing_type"] = ClassName(descriptor->containing_type());
+ 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);
- vars["type_constant"] = TypeName(GetType(descriptor));
+ 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";
@@ -109,13 +85,21 @@ void InitTemplateVars(const FieldDescriptor* descriptor,
string singular_type;
switch (java_type) {
case JAVATYPE_MESSAGE:
- singular_type = ClassName(descriptor->message_type());
+ singular_type = name_resolver->GetClassName(descriptor->message_type(),
+ immutable);
vars["prototype"] = singular_type + ".getDefaultInstance()";
break;
case JAVATYPE_ENUM:
- singular_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:
singular_type = BoxedPrimitiveTypeName(java_type);
break;
@@ -125,9 +109,11 @@ void InitTemplateVars(const FieldDescriptor* descriptor,
vars["singular_type"] = singular_type;
}
-void ExtensionGenerator::Generate(io::Printer* printer) {
+void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
map<string, string> vars;
- InitTemplateVars(descriptor_, scope_, &vars);
+ const bool kUseImmutableNames = true;
+ InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
+ &vars);
printer->Print(vars,
"public static final int $constant_name$ = $number$;\n");
@@ -174,7 +160,8 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
" $enum_map$,\n"
" $number$,\n"
" com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
- " $packed$);\n");
+ " $packed$,\n"
+ " $singular_type$.class);\n");
} else {
printer->Print(
vars,
@@ -188,12 +175,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) {
" $prototype$,\n"
" $enum_map$,\n"
" $number$,\n"
- " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n");
+ " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n"
+ " $singular_type$.class);\n");
}
}
}
-void ExtensionGenerator::GenerateNonNestedInitializationCode(
+void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
io::Printer* printer) {
if (descriptor_->extension_scope() == NULL &&
HasDescriptorMethods(descriptor_->file())) {
@@ -205,7 +193,8 @@ void ExtensionGenerator::GenerateNonNestedInitializationCode(
}
}
-void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) {
+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 009ed9ff..69686ef2 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 <map>
#include <string>
#include <google/protobuf/stubs/common.h>
@@ -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 GenerateNonNestedInitializationCode(io::Printer* printer);
- void GenerateRegistrationCode(io::Printer* printer);
+ protected:
+ static void InitTemplateVars(const FieldDescriptor* descriptor,
+ const string& scope,
+ bool immutable,
+ ClassNameResolver* name_resolver,
+ map<string, string>* 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 c7d433c8..f670477c 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -33,102 +33,178 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/java_field.h>
-#include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/compiler/java/java_primitive_field.h>
+
+#include <memory>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field.h>
#include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_primitive_field.h>
#include <google/protobuf/compiler/java/java_string_field.h>
-#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
namespace google {
namespace protobuf {
namespace compiler {
namespace java {
-FieldGenerator::~FieldGenerator() {}
+namespace {
+
+ImmutableFieldGenerator* MakeImmutableGenerator(
+ const FieldDescriptor* field, int messageBitIndex, int builderBitIndex,
+ Context* context) {
+ if (field->is_repeated()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsLazy(field)) {
+ return new RepeatedImmutableLazyMessageFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new RepeatedImmutableMessageFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ case JAVATYPE_ENUM:
+ return new RepeatedImmutableEnumFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new RepeatedImmutableStringFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new RepeatedImmutablePrimitiveFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ } else {
+ 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);
+ }
+ }
+ }
+}
+
-void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const {
+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.
+ // - 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<FieldGenerator>[descriptor->field_count()]),
- extension_generators_(
- new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
+} // namespace
+
+ImmutableFieldGenerator::~ImmutableFieldGenerator() {}
+
+void ImmutableFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ ReportUnexpectedPackedFieldsCall(printer);
+}
+
+// ===================================================================
+
+template <>
+FieldGeneratorMap<ImmutableFieldGenerator>::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++) {
- FieldGenerator* generator = MakeGenerator(descriptor->field(i),
- messageBitIndex, builderBitIndex);
+ ImmutableFieldGenerator* generator = MakeImmutableGenerator(
+ descriptor->field(i), messageBitIndex, builderBitIndex, context);
field_generators_[i].reset(generator);
messageBitIndex += generator->GetNumBitsForMessage();
builderBitIndex += generator->GetNumBitsForBuilder();
}
- for (int i = 0; i < descriptor->extension_count(); i++) {
- FieldGenerator* generator = MakeGenerator(descriptor->extension(i),
- messageBitIndex, builderBitIndex);
- extension_generators_[i].reset(generator);
- messageBitIndex += generator->GetNumBitsForMessage();
- builderBitIndex += generator->GetNumBitsForBuilder();
- }
}
-FieldGenerator* FieldGeneratorMap::MakeGenerator(
- const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) {
- if (field->is_repeated()) {
- switch (GetJavaType(field)) {
- case JAVATYPE_MESSAGE:
- return new RepeatedMessageFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- case JAVATYPE_ENUM:
- return new RepeatedEnumFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- case JAVATYPE_STRING:
- return new RepeatedStringFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- default:
- return new RepeatedPrimitiveFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- }
- } else {
- switch (GetJavaType(field)) {
- case JAVATYPE_MESSAGE:
- return new MessageFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- case JAVATYPE_ENUM:
- return new EnumFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- case JAVATYPE_STRING:
- return new StringFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- default:
- return new PrimitiveFieldGenerator(
- field, messageBitIndex, builderBitIndex);
- }
- }
-}
+template<>
+FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {}
-FieldGeneratorMap::~FieldGeneratorMap() {}
-const FieldGenerator& FieldGeneratorMap::get(
- const FieldDescriptor* field) const {
- GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
- return *field_generators_[field->index()];
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ const FieldGeneratorInfo* info,
+ map<string, string>* 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());
}
-const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
- return *extension_generators_[index];
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ const OneofGeneratorInfo* info,
+ map<string, string>* 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<string, string>& variables,
+ io::Printer* printer) {
+ const map<string, string>::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 4dd0efd6..a4aa3bce 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 <map>
+#include <memory>
#include <string>
+
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
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,10 +59,10 @@ 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;
@@ -78,29 +87,73 @@ class FieldGenerator {
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<typename FieldGeneratorType>
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<scoped_ptr<FieldGenerator> > field_generators_;
- scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
-
- static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
- int messageBitIndex, int builderBitIndex);
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ scoped_array<scoped_ptr<FieldGeneratorType> > field_generators_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
+template<typename FieldGeneratorType>
+inline const FieldGeneratorType&
+FieldGeneratorMap<FieldGeneratorType>::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<ImmutableFieldGenerator>::
+FieldGeneratorMap(const Descriptor* descriptor,
+ Context* context);
+
+template<>
+FieldGeneratorMap<ImmutableFieldGenerator>::~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<string, string>* variables);
+
+// Set some common oneof variables used in OneofFieldGenerators.
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ const OneofGeneratorInfo* info,
+ map<string, string>* variables);
+
+// Print useful comments before a field's accessors.
+void PrintExtraFieldInfo(const map<string, string>& 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 f43e5500..deec0e71 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -33,11 +33,17 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/java_file.h>
+
+#include <memory>
+
+#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum.h>
-#include <google/protobuf/compiler/java/java_service.h>
#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_message.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_service.h>
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -132,10 +138,27 @@ void CollectExtensions(const FileDescriptorProto& file_proto,
} // 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<MessageGenerator>[file->message_type_count()]),
+ extension_generators_(
+ new scoped_ptr<ExtensionGenerator>[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() {}
@@ -145,25 +168,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, \"");
@@ -174,7 +179,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;
}
@@ -208,12 +235,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();
@@ -222,18 +248,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 messageGenerator(file_->message_type(i));
- messageGenerator.GenerateInterface(printer);
- messageGenerator.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<ServiceGenerator> generator(
+ generator_factory_->NewServiceGenerator(file_->service(i)));
+ generator->Generate(printer);
}
}
}
@@ -241,28 +269,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);
+ message_generators_[i]->GenerateStaticVariableInitializers(printer);
}
printer->Outdent();
@@ -278,23 +307,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"
@@ -302,55 +316,18 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
"}\n"
"private static com.google.protobuf.Descriptors.FileDescriptor\n"
" descriptor;\n"
- "static {\n"
- " java.lang.String[] descriptorData = {\n");
+ "static {\n");
printer->Indent();
- 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();
+ "descriptor = $descriptor_classname$.descriptor;\n",
+ "descriptor_classname", name_resolver_->GetDescriptorClassName(file_));
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))
- .GenerateNonNestedInitializationCode(printer);
+ extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
}
// Proto compiler builds a DescriptorPool, which holds all the descriptors to
@@ -368,52 +345,107 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
// 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<const FieldDescriptor*> extensions;
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
if (extensions.size() > 0) {
// Must construct an ExtensionRegistry containing all existing extensions
- // and return it.
+ // 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");
+ " com.google.protobuf.ExtensionRegistry.newInstance();\n");
for (int i = 0; i < extensions.size(); i++) {
- ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer);
+ scoped_ptr<ExtensionGenerator> 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<const FieldDescriptor*> 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");
@@ -426,6 +458,7 @@ static void GenerateSibling(const string& package_dir,
GeneratorContext* context,
vector<string>* 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);
@@ -445,42 +478,53 @@ static void GenerateSibling(const string& package_dir,
"package", java_package);
}
- GeneratorClass generator(descriptor);
- (generator.*pfn)(&printer);
+ (generator->*pfn)(&printer);
}
void FileGenerator::GenerateSiblings(const string& package_dir,
GeneratorContext* context,
vector<string>* 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<EnumGenerator>(package_dir, java_package_,
file_->enum_type(i),
context, file_list, "",
+ &generator,
&EnumGenerator::Generate);
}
for (int i = 0; i < file_->message_type_count(); i++) {
- GenerateSibling<MessageGenerator>(package_dir, java_package_,
- file_->message_type(i),
- context, file_list, "OrBuilder",
- &MessageGenerator::GenerateInterface);
+ if (immutable_api_) {
+ GenerateSibling<MessageGenerator>(package_dir, java_package_,
+ file_->message_type(i),
+ context, file_list,
+ "OrBuilder",
+ message_generators_[i].get(),
+ &MessageGenerator::GenerateInterface);
+ }
GenerateSibling<MessageGenerator>(package_dir, java_package_,
file_->message_type(i),
context, file_list, "",
+ message_generators_[i].get(),
&MessageGenerator::Generate);
}
if (HasGenericServices(file_)) {
for (int i = 0; i < file_->service_count(); i++) {
+ scoped_ptr<ServiceGenerator> generator(
+ generator_factory_->NewServiceGenerator(file_->service(i)));
GenerateSibling<ServiceGenerator>(package_dir, java_package_,
file_->service(i),
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 59911462..7f289491 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 <memory>
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
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 GeneratorContext; // 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.
@@ -78,17 +86,23 @@ class FileGenerator {
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_;
+ scoped_array<scoped_ptr<MessageGenerator> > message_generators_;
+ scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
+ scoped_ptr<GeneratorFactory> generator_factory_;
+ scoped_ptr<Context> context_;
+ ClassNameResolver* name_resolver_;
+ bool immutable_api_;
- void GenerateEmbeddedDescriptor(io::Printer* printer);
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 e6c79abc..b713797b 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 <google/protobuf/compiler/java/java_generator.h>
+
+#include <memory>
+
#include <google/protobuf/compiler/java/java_file.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_shared_code_generator.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.pb.h>
@@ -64,55 +69,89 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
vector<pair<string, string> > 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;
+ }
+
// -----------------------------------------------------------------
- if (file->options().optimize_for() == FileOptions::LITE_RUNTIME &&
- file->options().java_generate_equals_and_hash()) {
- *error = "The \"java_generate_equals_and_hash\" option is incompatible "
- "with \"optimize_for = LITE_RUNTIME\". You must optimize for "
- "SPEED or CODE_SIZE if you want to use this option.";
- return false;
+ vector<string> all_files;
+
+ if (generate_shared_code) {
+ // Generate code shared between immutable and mutable API.
+ SharedCodeGenerator shared_code_generator(file);
+ shared_code_generator.Generate(context, &all_files);
}
- FileGenerator file_generator(file);
- if (!file_generator.Validate(error)) {
- return false;
+ vector<FileGenerator*> file_generators;
+ if (generate_immutable_code) {
+ file_generators.push_back(new FileGenerator(file, /* immutable = */ true));
+ }
+ if (generate_mutable_code) {
+ file_generators.push_back(new FileGenerator(file, /* mutable = */ false));
+ }
+ 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 = JavaPackageToDir(file_generator.java_package());
+ for (int i = 0; i < file_generators.size(); ++i) {
+ FileGenerator* file_generator = file_generators[i];
- vector<string> 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<io::ZeroCopyOutputStream> output(
- context->Open(java_filename));
- io::Printer printer(output.get(), '$');
- file_generator.Generate(&printer);
+ // Generate main java file.
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ context->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, context, &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<io::ZeroCopyOutputStream> srclist_raw_output(
- context->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_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc
new file mode 100644
index 00000000..ce71d436
--- /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 <google/protobuf/compiler/java/java_generator_factory.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum_field.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_message.h>
+#include <google/protobuf/compiler/java/java_service.h>
+
+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 00000000..abf894f6
--- /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 <google/protobuf/stubs/common.h>
+
+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 cf241b8a..fdd4e5e5 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 <algorithm>
+#include <google/protobuf/stubs/hash.h>
#include <limits>
#include <vector>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -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,22 +160,12 @@ 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()) {
@@ -146,7 +178,6 @@ string FileJavaPackage(const FileDescriptor* file) {
}
}
-
return result;
}
@@ -157,7 +188,10 @@ string JavaPackageToDir(string package_name) {
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);
@@ -178,22 +212,42 @@ string ToJavaName(const string& full_name, const FileDescriptor* file) {
}
string ClassName(const Descriptor* descriptor) {
- return ToJavaName(descriptor->full_name(), descriptor->file());
+ ClassNameResolver name_resolver;
+ return name_resolver.GetClassName(descriptor, true);
}
string ClassName(const EnumDescriptor* descriptor) {
- return ToJavaName(descriptor->full_name(), descriptor->file());
+ ClassNameResolver name_resolver;
+ return name_resolver.GetClassName(descriptor, true);
}
string ClassName(const ServiceDescriptor* descriptor) {
- return ToJavaName(descriptor->full_name(), descriptor->file());
+ 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) {
@@ -272,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) {
@@ -281,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()) {
@@ -344,11 +428,12 @@ string DefaultValue(const FieldDescriptor* field) {
}
case FieldDescriptor::CPPTYPE_ENUM:
- return ClassName(field->enum_type()) + "." +
+ 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.
@@ -494,6 +579,158 @@ 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<const Descriptor*>* 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<const Descriptor*> 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 3937f069..6d1eae0a 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,15 +61,22 @@ 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);
@@ -74,17 +84,46 @@ 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);
-
-// These return the fully-qualified class name corresponding to the given
-// descriptor.
+// TODO(xiaofeng): this method is deprecated and should be removed in the
+// future.
+string ToJavaName(const string& full_name,
+ const FileDescriptor* 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);
-inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) {
- return ToJavaName(descriptor->full_name(), descriptor->file());
+// 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();
+}
+
+
+// Whether we should generate multiple java files for messages.
+inline bool MultipleJavaFiles(
+ const FileDescriptor* descriptor, bool immutable) {
+ return descriptor->options().java_multiple_files();
}
// Get the unqualified name that should be used for a field's field
@@ -115,11 +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);
+
+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 keep track of unknown fields?
-inline bool HasUnknownFields(const Descriptor* descriptor) {
+// 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;
}
@@ -163,6 +214,15 @@ 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.
@@ -212,6 +272,48 @@ string GenerateGetBitMutableLocal(int bitIndex);
// 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 00000000..32d97b6f
--- /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 <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/io/printer.h>
+
+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<com.google.protobuf.LazyFieldLite> $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<? extends $type$OrBuilder>\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<com.google.protobuf.LazyFieldLite> $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<com.google.protobuf.LazyFieldLite>(\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<Field> 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<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ PrintNestedBuilderFunction(printer,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> 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<? extends $type$OrBuilder> \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<com.google.protobuf.LazyFieldLite>();\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 00000000..2a1f8574
--- /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 <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message_field.h>
+
+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 9322e242..1cd08f7d 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -37,12 +37,16 @@
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
#include <map>
+#include <memory>
#include <vector>
+#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_enum.h>
#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
@@ -59,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')));
+bool GenerateHasBits(const Descriptor* descriptor) {
+ return SupportFieldPresence(descriptor->file()) ||
+ HasRepeatedFields(descriptor);
}
-
-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<const Descriptor*>* 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<const Descriptor*> already_seen;
- return HasRequiredFields(type, &already_seen);
-}
-
} // 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
@@ -171,12 +99,12 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) {
map<string, string> 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"] = "";
@@ -186,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<string, string> 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());
@@ -228,56 +153,95 @@ 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");
+ 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<string, string> 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");
+}
+
+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::GenerateInterface(io::Printer* printer) {
+void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
"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 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 interface $classname$OrBuilder\n"
- " extends com.google.protobuf.MessageOrBuilder {\n",
+ "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 interface $classname$OrBuilder\n"
- " extends com.google.protobuf.MessageLiteOrBuilder {\n",
+ "public interface $classname$OrBuilder extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.MessageLiteOrBuilder {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
"classname", descriptor_->name());
}
}
@@ -285,7 +249,6 @@ void MessageGenerator::GenerateInterface(io::Printer* printer) {
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("\n");
- PrintFieldComment(printer, descriptor_->field(i));
field_generators_.get(descriptor_->field(i))
.GenerateInterfaceMembers(printer);
}
@@ -296,10 +259,10 @@ void MessageGenerator::GenerateInterface(io::Printer* printer) {
// ===================================================================
-void MessageGenerator::Generate(io::Printer* printer) {
+void ImmutableMessageGenerator::Generate(io::Printer* printer) {
bool is_own_file =
descriptor_->containing_type() == NULL &&
- descriptor_->file()->options().java_multiple_files();
+ MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
WriteMessageDocComment(printer, descriptor_);
@@ -308,41 +271,51 @@ void MessageGenerator::Generate(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
- "public $static$ final class $classname$ extends\n"
+ "public$static$final class $classname$ extends\n"
" com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
- " $classname$> implements $classname$OrBuilder {\n",
- "static", is_own_file ? "" : "static",
- "classname", descriptor_->name());
+ " $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, ?>",
- ClassName(descriptor_));
+ name_resolver_->GetImmutableClassName(descriptor_));
} else {
printer->Print(
- "public $static$ final class $classname$ extends\n"
+ "public$static$final class $classname$ extends\n"
" com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
- " $classname$> implements $classname$OrBuilder {\n",
- "static", is_own_file ? "" : "static",
- "classname", descriptor_->name());
+ " $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, ?>",
- ClassName(descriptor_));
+ name_resolver_->GetImmutableClassName(descriptor_));
}
} else {
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
- "public $static$ final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage\n"
- " implements $classname$OrBuilder {\n",
- "static", is_own_file ? "" : "static",
- "classname", descriptor_->name());
+ "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\n"
- " implements $classname$OrBuilder {\n",
- "static", is_own_file ? "" : "static",
- "classname", descriptor_->name());
+ "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";
}
}
@@ -359,8 +332,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
"}\n",
"classname", descriptor_->name(),
"buildertype", builder_type,
- "set_unknown_fields", HasUnknownFields(descriptor_)
- ? " this.unknownFields = builder.getUnknownFields();" : "");
+ "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.
@@ -376,11 +349,12 @@ void MessageGenerator::Generate(io::Printer* printer) {
"}\n"
"\n",
"classname", descriptor_->name(),
- "set_default_unknown_fields", HasUnknownFields(descriptor_)
+ "set_default_unknown_fields", UseUnknownFieldSet(descriptor_)
? " this.unknownFields ="
- " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " : "");
+ " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); "
+ : " this.unknownFields = com.google.protobuf.ByteString.EMPTY;");
- if (HasUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_)) {
printer->Print(
"private final com.google.protobuf.UnknownFieldSet unknownFields;\n"
""
@@ -389,6 +363,9 @@ void MessageGenerator::Generate(io::Printer* printer) {
" getUnknownFields() {\n"
" return this.unknownFields;\n"
"}\n");
+ } else {
+ printer->Print(
+ "private final com.google.protobuf.ByteString unknownFields;\n");
}
if (HasGeneratedMethods(descriptor_)) {
@@ -400,30 +377,102 @@ void MessageGenerator::Generate(io::Printer* 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 messageGenerator(descriptor_->nested_type(i));
+ ImmutableMessageGenerator messageGenerator(
+ descriptor_->nested_type(i), context_);
messageGenerator.GenerateInterface(printer);
messageGenerator.Generate(printer);
}
- // Integers for bit fields.
- int totalBits = 0;
- for (int i = 0; i < descriptor_->field_count(); i++) {
- totalBits += field_generators_.get(descriptor_->field(i))
- .GetNumBitsForMessage();
+ 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));
+ }
}
- 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<string, string> 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()));
@@ -436,9 +485,12 @@ 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");
@@ -451,6 +503,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
GenerateEqualsAndHashCode(printer);
}
+
GenerateParseFromMethods(printer);
GenerateBuilder(printer);
@@ -471,7 +524,8 @@ void MessageGenerator::Generate(io::Printer* printer) {
// 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++) {
- ExtensionGenerator(descriptor_->extension(i)).Generate(printer);
+ ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+ .Generate(printer);
}
printer->Outdent();
@@ -481,10 +535,10 @@ void MessageGenerator::Generate(io::Printer* printer) {
// ===================================================================
-void MessageGenerator::
+void ImmutableMessageGenerator::
GenerateMessageSerializationMethods(io::Printer* printer) {
scoped_array<const FieldDescriptor*> sorted_fields(
- SortFieldsByNumber(descriptor_));
+ SortFieldsByNumber(descriptor_));
vector<const Descriptor::ExtensionRange*> sorted_extensions;
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
@@ -513,14 +567,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
" .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
" newMessageSetExtensionWriter();\n",
"lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
} else {
printer->Print(
"com.google.protobuf.GeneratedMessage$lite$\n"
" .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
" newExtensionWriter();\n",
"lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
}
}
@@ -539,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");
@@ -547,6 +601,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
printer->Print(
"getUnknownFields().writeTo(output);\n");
}
+ } else {
+ printer->Print(
+ "output.writeRawBytes(unknownFields);\n");
}
printer->Outdent();
@@ -575,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");
@@ -583,6 +640,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
printer->Print(
"size += getUnknownFields().getSerializedSize();\n");
}
+ } else {
+ printer->Print(
+ "size += unknownFields.size();\n");
}
printer->Outdent();
@@ -602,7 +662,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
"\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
@@ -661,15 +721,15 @@ GenerateParseFromMethods(io::Printer* printer) {
" 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",
@@ -678,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"
@@ -687,7 +747,7 @@ 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(
@@ -706,29 +766,40 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
printer->Print(
"public static final class Builder extends\n"
" com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
- " $classname$, Builder> implements $classname$OrBuilder {\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> implements $classname$OrBuilder {\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<Builder>\n"
- " implements $classname$OrBuilder {\n",
- "classname", ClassName(descriptor_));
+ " com.google.protobuf.GeneratedMessage.Builder<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"
- " implements $classname$OrBuilder {\n",
- "classname", ClassName(descriptor_));
+ " implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
}
}
printer->Indent();
@@ -741,21 +812,54 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
GenerateBuilderParsingMethods(printer);
}
- // Integers for bit fields.
- int totalBits = 0;
- for (int i = 0; i < descriptor_->field_count(); i++) {
- totalBits += field_generators_.get(descriptor_->field(i))
- .GetNumBitsForBuilder();
+ // oneof
+ map<string, string> 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");
}
- 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));
+
+ 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);
}
@@ -769,7 +873,8 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) {
printer->Print("}\n");
}
-void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
+void ImmutableMessageGenerator::
+GenerateDescriptorMethods(io::Printer* printer) {
if (HasDescriptorMethods(descriptor_)) {
if (!descriptor_->options().no_standard_descriptor_accessor()) {
printer->Print(
@@ -778,7 +883,7 @@ void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
" return $fileclass$.internal_$identifier$_descriptor;\n"
"}\n"
"\n",
- "fileclass", ClassName(descriptor_->file()),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
}
printer->Print(
@@ -789,22 +894,23 @@ void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) {
" $classname$.class, $classname$.Builder.class);\n"
"}\n"
"\n",
- "classname", ClassName(descriptor_),
- "fileclass", ClassName(descriptor_->file()),
+ "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(
"// Construct using $classname$.newBuilder()\n"
"private Builder() {\n"
" maybeForceBuilderInitialization();\n"
"}\n"
"\n",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
@@ -813,7 +919,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" super(parent);\n"
" maybeForceBuilderInitialization();\n"
"}\n",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
}
@@ -825,8 +931,10 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
printer->Indent();
printer->Indent();
for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i))
- .GenerateFieldBuilderInitializationCode(printer);
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateFieldBuilderInitializationCode(printer);
+ }
}
printer->Outdent();
printer->Outdent();
@@ -847,13 +955,23 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
"\n"
"public Builder clear() {\n"
" super.clear();\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))
- .GenerateBuilderClearCode(printer);
+ 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();
@@ -866,7 +984,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" 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"
@@ -874,7 +992,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" return $fileclass$.internal_$identifier$_descriptor;\n"
"}\n"
"\n",
- "fileclass", ClassName(descriptor_->file()),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
}
printer->Print(
@@ -882,7 +1000,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" return $classname$.getDefaultInstance();\n"
"}\n"
"\n",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
// -----------------------------------------------------------------
@@ -897,30 +1015,34 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
"\n"
"public $classname$ buildPartial() {\n"
" $classname$ result = new $classname$(this);\n",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
printer->Indent();
- // 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.
int totalBuilderBits = 0;
int totalMessageBits = 0;
for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
+ 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;
- 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));
+
+ 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.
@@ -928,10 +1050,18 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
}
- // 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));
+ 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();
@@ -945,7 +1075,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" return result;\n"
"}\n"
"\n",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
// -----------------------------------------------------------------
@@ -963,7 +1093,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
" }\n"
"}\n"
"\n",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
}
printer->Print(
@@ -971,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();
@@ -986,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(
@@ -1000,7 +1171,8 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) {
// ===================================================================
-void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
+void ImmutableMessageGenerator::
+GenerateBuilderParsingMethods(io::Printer* printer) {
printer->Print(
"public Builder mergeFrom(\n"
" com.google.protobuf.CodedInputStream input,\n"
@@ -1019,12 +1191,12 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
" }\n"
" return this;\n"
"}\n",
- "classname", ClassName(descriptor_));
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
}
// ===================================================================
-void MessageGenerator::GenerateIsInitialized(
+void ImmutableMessageGenerator::GenerateIsInitialized(
io::Printer* printer, UseMemoization useMemoization) {
bool memoization = useMemoization == MEMOIZE;
if (memoization) {
@@ -1039,9 +1211,11 @@ void MessageGenerator::GenerateIsInitialized(
printer->Indent();
if (memoization) {
+ // Don't directly compare to -1 to avoid an Android x86 JIT bug.
printer->Print(
"byte isInitialized = memoizedIsInitialized;\n"
- "if (isInitialized != -1) return isInitialized == 1;\n"
+ "if (isInitialized == 1) return true;\n"
+ "if (isInitialized == 0) return false;\n"
"\n");
}
@@ -1050,6 +1224,7 @@ void MessageGenerator::GenerateIsInitialized(
// "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(
@@ -1057,7 +1232,7 @@ void MessageGenerator::GenerateIsInitialized(
" $memoize$\n"
" return false;\n"
"}\n",
- "name", UnderscoresToCapitalizedCamelCase(field),
+ "name", info->capitalized_name,
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
}
}
@@ -1065,6 +1240,7 @@ void MessageGenerator::GenerateIsInitialized(
// 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()) {
@@ -1074,8 +1250,9 @@ void MessageGenerator::GenerateIsInitialized(
" $memoize$\n"
" return false;\n"
"}\n",
- "type", ClassName(field->message_type()),
- "name", UnderscoresToCapitalizedCamelCase(field),
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name,
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
break;
case FieldDescriptor::LABEL_OPTIONAL:
@@ -1086,8 +1263,9 @@ void MessageGenerator::GenerateIsInitialized(
" return false;\n"
" }\n"
"}\n",
- "type", ClassName(field->message_type()),
- "name", UnderscoresToCapitalizedCamelCase(field),
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name,
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
break;
case FieldDescriptor::LABEL_REPEATED:
@@ -1098,8 +1276,9 @@ void MessageGenerator::GenerateIsInitialized(
" return false;\n"
" }\n"
"}\n",
- "type", ClassName(field->message_type()),
- "name", UnderscoresToCapitalizedCamelCase(field),
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name,
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
break;
}
@@ -1130,7 +1309,21 @@ void MessageGenerator::GenerateIsInitialized(
// ===================================================================
-void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
+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(
"@java.lang.Override\n"
"public boolean equals(final java.lang.Object obj) {\n");
@@ -1144,20 +1337,22 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
"}\n"
"$classname$ other = ($classname$) obj;\n"
"\n",
- "classname", ClassName(descriptor_));
+ "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);
- if (!field->is_repeated()) {
+ 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", UnderscoresToCapitalizedCamelCase(field));
+ "name", info->capitalized_name);
printer->Indent();
}
field_generators_.get(field).GenerateEqualsCode(printer);
- if (!field->is_repeated()) {
+ if (check_has_bits) {
printer->Outdent();
printer->Print(
"}\n");
@@ -1181,8 +1376,6 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
"\n");
printer->Print(
- "private int memoizedHashCode = 0;\n");
- printer->Print(
"@java.lang.Override\n"
"public int hashCode() {\n");
printer->Indent();
@@ -1194,18 +1387,29 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Outdent();
printer->Print(
"}\n"
- "int hash = 41;\n"
- "hash = (19 * hash) + getDescriptorForType().hashCode();\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);
- if (!field->is_repeated()) {
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+ if (check_has_bits) {
printer->Print(
"if (has$name$()) {\n",
- "name", UnderscoresToCapitalizedCamelCase(field));
+ "name", info->capitalized_name);
printer->Indent();
}
field_generators_.get(field).GenerateHashCode(printer);
- if (!field->is_repeated()) {
+ if (check_has_bits) {
printer->Outdent();
printer->Print("}\n");
}
@@ -1216,8 +1420,15 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
"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(
- "hash = (29 * hash) + getUnknownFields().hashCode();\n"
"memoizedHashCode = hash;\n"
"return hash;\n");
printer->Outdent();
@@ -1228,20 +1439,22 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) {
// ===================================================================
-void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) {
+void ImmutableMessageGenerator::
+GenerateExtensionRegistrationCode(io::Printer* printer) {
for (int i = 0; i < descriptor_->extension_count(); i++) {
- ExtensionGenerator(descriptor_->extension(i))
+ ImmutableExtensionGenerator(descriptor_->extension(i), context_)
.GenerateRegistrationCode(printer);
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- MessageGenerator(descriptor_->nested_type(i))
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
.GenerateExtensionRegistrationCode(printer);
}
}
// ===================================================================
-void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
+void ImmutableMessageGenerator::
+GenerateParsingConstructor(io::Printer* printer) {
scoped_array<const FieldDescriptor*> sorted_fields(
SortFieldsByNumber(descriptor_));
@@ -1260,7 +1473,8 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
// Use builder bits to track mutable repeated fields.
int totalBuilderBits = 0;
for (int i = 0; i < descriptor_->field_count(); i++) {
- const FieldGenerator& field = field_generators_.get(descriptor_->field(i));
+ const ImmutableFieldGenerator& field =
+ field_generators_.get(descriptor_->field(i));
totalBuilderBits += field.GetNumBitsForBuilder();
}
int totalBuilderInts = (totalBuilderBits + 31) / 32;
@@ -1269,10 +1483,17 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
"bit_field_name", GetBitFieldName(i));
}
- if (HasUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_)) {
printer->Print(
"com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
" com.google.protobuf.UnknownFieldSet.newBuilder();\n");
+ } else {
+ printer->Print(
+ "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(
@@ -1300,8 +1521,8 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
" }\n"
" break;\n"
"}\n",
- "unknown_fields", HasUnknownFields(descriptor_)
- ? " unknownFields," : "");
+ "unknown_fields", UseUnknownFieldSet(descriptor_)
+ ? " unknownFields," : " unknownFieldsCodedOutput,");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
@@ -1362,9 +1583,18 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
}
// Make unknown fields immutable.
- if (HasUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_)) {
printer->Print(
"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.
@@ -1379,7 +1609,7 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) {
}
// ===================================================================
-void MessageGenerator::GenerateParser(io::Printer* 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",
@@ -1429,6 +1659,7 @@ void MessageGenerator::GenerateParser(io::Printer* printer) {
"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 a30f0202..406910dc 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 <string>
-#include <google/protobuf/stubs/common.h>
+#include <map>
#include <google/protobuf/compiler/java/java_field.h>
namespace google {
namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
namespace io {
class Printer; // printer.h
}
@@ -53,26 +59,45 @@ 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
- void GenerateInterface(io::Printer* printer);
+ 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 {
@@ -80,6 +105,9 @@ class MessageGenerator {
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,
@@ -94,14 +122,14 @@ class MessageGenerator {
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<ImmutableFieldGenerator> 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 b0b284f7..80b9a382 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -35,9 +35,11 @@
#include <map>
#include <string>
+#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_message_field.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
@@ -49,19 +51,18 @@ 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<string, string>* variables) {
- (*variables)["name"] =
- UnderscoresToCamelCase(descriptor);
- (*variables)["capitalized_name"] =
- UnderscoresToCapitalizedCamelCase(descriptor);
- (*variables)["constant_name"] = FieldConstantName(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";
@@ -72,14 +73,28 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["on_changed"] =
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
- // For singular messages and builders, one bit is used for the hasField bit.
- (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
- (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
+ 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)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
- (*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);
@@ -103,35 +118,41 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
// ===================================================================
-MessageFieldGenerator::
-MessageFieldGenerator(const FieldDescriptor* descriptor,
+ImmutableMessageFieldGenerator::
+ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
int messageBitIndex,
- int builderBitIndex)
+ int builderBitIndex,
+ Context* context)
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex) {
- SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
- &variables_);
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-MessageFieldGenerator::~MessageFieldGenerator() {}
+ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {}
-int MessageFieldGenerator::GetNumBitsForMessage() const {
+int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
return 1;
}
-int MessageFieldGenerator::GetNumBitsForBuilder() const {
+int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
-void MessageFieldGenerator::
+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.
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n");
+ 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");
@@ -143,31 +164,56 @@ GenerateInterfaceMembers(io::Printer* printer) const {
}
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $type$ $name$_;\n");
- 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");
+ PrintExtraFieldInfo(variables_, printer);
- if (HasNestedBuilders(descriptor_->containing_type())) {
+ if (SupportFieldPresence(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ "$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::PrintNestedBuilderCondition(
+void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
io::Printer* printer,
const char* regular_case,
const char* nested_builder_case) const {
@@ -186,7 +232,7 @@ void MessageFieldGenerator::PrintNestedBuilderCondition(
}
}
-void MessageFieldGenerator::PrintNestedBuilderFunction(
+void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
io::Printer* printer,
const char* method_prototype,
const char* regular_case,
@@ -203,15 +249,22 @@ void MessageFieldGenerator::PrintNestedBuilderFunction(
printer->Print("}\n");
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
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.
- "private $type$ $name$_ = $type$.getDefaultInstance();\n");
+ 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_,
@@ -227,17 +280,26 @@ GenerateBuilderMembers(io::Printer* printer) const {
// boolean hasField()
WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public boolean has$capitalized_name$() {\n"
- " return $get_has_field_bit_builder$;\n"
- "}\n");
+ 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$()",
- "return $name$_;\n",
+ support_field_presence
+ ? "return $name$_;\n"
+ : "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
"return $name$Builder_.getMessage();\n",
@@ -256,7 +318,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$name$Builder_.setMessage(value);\n",
- "$set_has_field_bit_builder$;\n"
+ "$set_has_field_bit_builder$\n"
"return this;\n");
// Field.Builder setField(Field.Builder builderForValue)
@@ -270,7 +332,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$name$Builder_.setMessage(builderForValue.build());\n",
- "$set_has_field_bit_builder$;\n"
+ "$set_has_field_bit_builder$\n"
"return this;\n");
// Field.Builder mergeField(Field value)
@@ -278,18 +340,26 @@ GenerateBuilderMembers(io::Printer* printer) const {
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder merge$capitalized_name$($type$ value)",
- "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",
+ 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"
+ "$set_has_field_bit_builder$\n"
"return this;\n");
// Field.Builder clearField()
@@ -297,19 +367,25 @@ GenerateBuilderMembers(io::Printer* printer) const {
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder clear$capitalized_name$()",
- "$name$_ = $type$.getDefaultInstance();\n"
- "$on_changed$\n",
+ support_field_presence
+ ? "$name$_ = $type$.getDefaultInstance();\n"
+ "$on_changed$\n"
+ : "$name$_ = null;\n"
+ "$on_changed$\n",
- "$name$Builder_.clear();\n",
+ support_field_presence
+ ? "$name$Builder_.clear();\n"
+ : "$name$_ = null;\n"
+ "$name$Builder_ = null;\n",
- "$clear_has_field_bit_builder$;\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"
+ " $set_has_field_bit_builder$\n"
" $on_changed$\n"
" return get$capitalized_name$FieldBuilder().getBuilder();\n"
"}\n");
@@ -318,8 +394,16 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
" if ($name$Builder_ != null) {\n"
" return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n"
- " return $name$_;\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_);
@@ -330,7 +414,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" if ($name$Builder_ == null) {\n"
" $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
" $type$, $type$.Builder, $type$OrBuilder>(\n"
- " $name$_,\n"
+ " get$capitalized_name$(),\n"
" getParentForChildren(),\n"
" isClean());\n"
" $name$_ = null;\n"
@@ -340,28 +424,40 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
- printer->Print(variables_,
- "get$capitalized_name$FieldBuilder();\n");
+ if (SupportFieldPresence(descriptor_->file())) {
+ printer->Print(variables_,
+ "get$capitalized_name$FieldBuilder();\n");
+ }
}
-void MessageFieldGenerator::
+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 {
- PrintNestedBuilderCondition(printer,
- "$name$_ = $type$.getDefaultInstance();\n",
+ if (SupportFieldPresence(descriptor_->file())) {
+ PrintNestedBuilderCondition(printer,
+ "$name$_ = $type$.getDefaultInstance();\n",
- "$name$Builder_.clear();\n");
- printer->Print(variables_, "$clear_has_field_bit_builder$;\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 MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -369,13 +465,14 @@ GenerateMergingCode(io::Printer* printer) const {
"}\n");
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
-
- printer->Print(variables_,
- "if ($get_has_field_bit_from_local$) {\n"
- " $set_has_field_bit_to_local$;\n"
- "}\n");
+ 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",
@@ -383,11 +480,11 @@ GenerateBuildingCode(io::Printer* printer) const {
"result.$name$_ = $name$Builder_.build();\n");
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"$type$.Builder subBuilder = null;\n"
- "if ($get_has_field_bit_message$) {\n"
+ "if ($is_field_present_message$) {\n"
" subBuilder = $name$_.toBuilder();\n"
"}\n");
@@ -404,74 +501,344 @@ GenerateParsingCode(io::Printer* printer) const {
"if (subBuilder != null) {\n"
" subBuilder.mergeFrom($name$_);\n"
" $name$_ = subBuilder.buildPartial();\n"
- "}\n");
- printer->Print(variables_,
- "$set_has_field_bit_message$;\n");
+ "}\n"
+ "$set_has_field_bit_message$\n");
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
// noop for messages.
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($get_has_field_bit_message$) {\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 ($get_has_field_bit_message$) {\n"
+ "if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
" .compute$group_or_message$Size($number$, $name$_);\n"
"}\n");
}
-void MessageFieldGenerator::
+void ImmutableMessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"result = result && get$capitalized_name$()\n"
" .equals(other.get$capitalized_name$());\n");
}
-void MessageFieldGenerator::
+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 MessageFieldGenerator::GetBoxedType() const {
- return ClassName(descriptor_->message_type());
+string ImmutableMessageFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+// ===================================================================
+
+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_);
+}
+
+ImmutableMessageOneofFieldGenerator::
+~ImmutableMessageOneofFieldGenerator() {}
+
+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_,
+ "$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 ImmutableMessageOneofFieldGenerator::
+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.
+ 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"
+ "return $type$.getDefaultInstance();\n",
+
+ "if ($has_oneof_case_message$) {\n"
+ " return $name$Builder_.getMessage();\n"
+ "}\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"
+ "$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"
+ "$on_changed$\n",
+
+ "if ($has_oneof_case_message$) {\n"
+ " $name$Builder_.mergeFrom(value);\n"
+ "}\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"
+ "$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");
}
// ===================================================================
-RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex,
- int builderBitIndex)
+RepeatedImmutableMessageFieldGenerator::
+RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex) {
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
- &variables_);
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+RepeatedImmutableMessageFieldGenerator::
+~RepeatedImmutableMessageFieldGenerator() {}
-int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const {
+int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const {
return 0;
}
-int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const {
+int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
-void RepeatedMessageFieldGenerator::
+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
@@ -499,10 +866,11 @@ GenerateInterfaceMembers(io::Printer* printer) const {
}
}
-void RepeatedMessageFieldGenerator::
+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"
@@ -533,7 +901,7 @@ GenerateMembers(io::Printer* printer) const {
}
-void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition(
+void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
io::Printer* printer,
const char* regular_case,
const char* nested_builder_case) const {
@@ -552,7 +920,7 @@ void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition(
}
}
-void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction(
+void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
io::Printer* printer,
const char* method_prototype,
const char* regular_case,
@@ -569,7 +937,7 @@ void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction(
printer->Print("}\n");
}
-void RepeatedMessageFieldGenerator::
+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
@@ -737,7 +1105,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
" java.lang.Iterable<? extends $type$> values)",
"ensure$capitalized_name$IsMutable();\n"
- "super.addAll(values, $name$_);\n"
+ "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+ " values, $name$_);\n"
"$on_changed$\n",
"$name$Builder_.addAllMessages(values);\n",
@@ -836,18 +1205,18 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
printer->Print(variables_,
"get$capitalized_name$FieldBuilder();\n");
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n");
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
PrintNestedBuilderCondition(printer,
"$name$_ = java.util.Collections.emptyList();\n"
@@ -856,7 +1225,7 @@ GenerateBuilderClearCode(io::Printer* printer) const {
"$name$Builder_.clear();\n");
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// 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
@@ -890,7 +1259,7 @@ GenerateMergingCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateBuildingCode(io::Printer* printer) const {
// 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,
@@ -905,7 +1274,7 @@ GenerateBuildingCode(io::Printer* printer) const {
"result.$name$_ = $name$Builder_.build();\n");
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!$get_mutable_bit_parser$) {\n"
@@ -923,7 +1292,7 @@ GenerateParsingCode(io::Printer* printer) const {
}
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_mutable_bit_parser$) {\n"
@@ -931,7 +1300,7 @@ GenerateParsingDoneCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
@@ -939,7 +1308,7 @@ GenerateSerializationCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
@@ -948,14 +1317,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedMessageFieldGenerator::
+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 RepeatedMessageFieldGenerator::
+void RepeatedImmutableMessageFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"if (get$capitalized_name$Count() > 0) {\n"
@@ -964,8 +1333,8 @@ GenerateHashCode(io::Printer* printer) const {
"}\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 5c8078a1..f7b491e5 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -41,16 +41,26 @@
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,
- int messageBitIndex, int builderBitIndex);
- ~MessageFieldGenerator();
+ explicit ImmutableMessageFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMessageFieldGenerator();
- // implements FieldGenerator ---------------------------------------
+ // implements ImmutableFieldGenerator ---------------------------------------
int GetNumBitsForMessage() const;
int GetNumBitsForBuilder() const;
void GenerateInterfaceMembers(io::Printer* printer) const;
@@ -70,13 +80,13 @@ class MessageFieldGenerator : public FieldGenerator {
string GetBoxedType() const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
const int messageBitIndex_;
const int builderBitIndex_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+ Context* context_;
+ ClassNameResolver* name_resolver_;
void PrintNestedBuilderCondition(io::Printer* printer,
const char* regular_case, const char* nested_builder_case) const;
@@ -84,15 +94,39 @@ class MessageFieldGenerator : public FieldGenerator {
const char* method_prototype, const char* regular_case,
const char* nested_builder_case,
const char* trailing_code) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator);
};
-class RepeatedMessageFieldGenerator : public FieldGenerator {
+class ImmutableMessageOneofFieldGenerator
+ : public ImmutableMessageFieldGenerator {
public:
- explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex, int builderBitIndex);
- ~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;
@@ -112,13 +146,13 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
string GetBoxedType() const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
const int messageBitIndex_;
const int builderBitIndex_;
-
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+ Context* context_;
+ ClassNameResolver* name_resolver_;
void PrintNestedBuilderCondition(io::Printer* printer,
const char* regular_case, const char* nested_builder_case) const;
@@ -126,6 +160,9 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
const char* method_prototype, const char* regular_case,
const char* nested_builder_case,
const char* trailing_code) const;
+
+ 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 00000000..7f52d234
--- /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 <google/protobuf/compiler/java/java_name_resolver.h>
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/stubs/substitute.h>
+
+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) + "InternalDescriptors";
+}
+
+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 00000000..1d3e185c
--- /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 <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+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<class DescriptorType>
+ string GetImmutableClassName(const DescriptorType* descriptor) {
+ return GetClassName(descriptor, true);
+ }
+ template<class DescriptorType>
+ 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<const FileDescriptor*, string> 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 ccc94c9d..52577626 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 <memory>
+
#include <google/protobuf/compiler/java/java_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -71,7 +73,7 @@ class TestGenerator : public CodeGenerator {
void TryInsert(const string& filename, const string& insertion_point,
GeneratorContext* context) const {
scoped_ptr<io::ZeroCopyOutputStream> output(
- context->OpenForInsert(filename, insertion_point));
+ context->OpenForInsert(filename, insertion_point));
io::Printer printer(output.get(), '$');
printer.Print("// inserted $name$\n", "name", insertion_point);
}
@@ -81,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 0140e23f..031a1293 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -35,10 +35,12 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/java/java_primitive_field.h>
-#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_primitive_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
@@ -73,107 +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<string, string>* variables) {
- (*variables)["name"] =
- UnderscoresToCamelCase(descriptor);
- (*variables)["capitalized_name"] =
- UnderscoresToCapitalizedCamelCase(descriptor);
- (*variables)["constant_name"] = FieldConstantName(descriptor);
- (*variables)["number"] = SimpleItoa(descriptor->number());
+ SetCommonFieldVariables(descriptor, info, variables);
+
(*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
(*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(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"] = DefaultValue(descriptor);
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
(*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
- "" : ("= " + DefaultValue(descriptor));
- (*variables)["capitalized_type"] = GetCapitalizedType(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)));
@@ -196,14 +116,33 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["on_changed"] =
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
- // For singular messages and builders, one bit is used for the hasField bit.
- (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
- (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
+ 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);
- (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
- (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex);
- (*variables)["clear_has_field_bit_builder"] =
- GenerateClearBit(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);
@@ -227,46 +166,53 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
// ===================================================================
-PrimitiveFieldGenerator::
-PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex,
- int builderBitIndex)
+ImmutablePrimitiveFieldGenerator::
+ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex) {
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
- &variables_);
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {}
-int PrimitiveFieldGenerator::GetNumBitsForMessage() const {
+int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
return 1;
}
-int PrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n");
+ 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 PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $field_type$ $name$_;\n");
-
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public boolean has$capitalized_name$() {\n"
- " return $get_has_field_bit_message$;\n"
- "}\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_,
@@ -275,16 +221,18 @@ GenerateMembers(io::Printer* printer) const {
"}\n");
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $field_type$ $name$_ $default_init$;\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public boolean has$capitalized_name$() {\n"
- " return $get_has_field_bit_builder$;\n"
- "}\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_,
@@ -296,7 +244,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
"$null_check$"
- " $set_has_field_bit_builder$;\n"
+ " $set_has_field_bit_builder$\n"
" $name$_ = value;\n"
" $on_changed$\n"
" return this;\n"
@@ -305,7 +253,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
- " $clear_has_field_bit_builder$;\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
@@ -322,70 +270,80 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n");
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
// noop for primitives
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $default$;\n");
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = $default$;\n"
- "$clear_has_field_bit_builder$;\n");
+ "$clear_has_field_bit_builder$\n");
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (other.has$capitalized_name$()) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
- "}\n");
+ 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 {
+ 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_,
- "if ($get_has_field_bit_from_local$) {\n"
- " $set_has_field_bit_to_local$;\n"
- "}\n"
"result.$name$_ = $name$_;\n");
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
- "$set_has_field_bit_message$;\n"
+ "$set_has_field_bit_message$\n"
"$name$_ = input.read$capitalized_type$();\n");
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
// noop for primitives.
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($get_has_field_bit_message$) {\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 ($get_has_field_bit_message$) {\n"
+ "if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
" .compute$capitalized_type$Size($number$, $name$_);\n"
"}\n");
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
switch (GetJavaType(descriptor_)) {
case JAVATYPE_INT:
@@ -398,14 +356,18 @@ GenerateEqualsCode(io::Printer* printer) const {
case JAVATYPE_FLOAT:
printer->Print(variables_,
- "result = result && (Float.floatToIntBits(get$capitalized_name$())"
- " == Float.floatToIntBits(other.get$capitalized_name$()));\n");
+ "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 && (Double.doubleToLongBits(get$capitalized_name$())"
- " == Double.doubleToLongBits(other.get$capitalized_name$()));\n");
+ "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:
@@ -423,7 +385,7 @@ GenerateEqualsCode(io::Printer* printer) const {
}
}
-void PrimitiveFieldGenerator::
+void ImmutablePrimitiveFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"hash = (37 * hash) + $constant_name$;\n");
@@ -435,24 +397,26 @@ GenerateHashCode(io::Printer* printer) const {
case JAVATYPE_LONG:
printer->Print(variables_,
- "hash = (53 * hash) + hashLong(get$capitalized_name$());\n");
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " get$capitalized_name$());\n");
break;
case JAVATYPE_BOOLEAN:
printer->Print(variables_,
- "hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n");
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
+ " get$capitalized_name$());\n");
break;
case JAVATYPE_FLOAT:
printer->Print(variables_,
- "hash = (53 * hash) + Float.floatToIntBits(\n"
+ "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
" get$capitalized_name$());\n");
break;
case JAVATYPE_DOUBLE:
printer->Print(variables_,
- "hash = (53 * hash) + hashLong(\n"
- " Double.doubleToLongBits(get$capitalized_name$()));\n");
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
break;
case JAVATYPE_STRING:
@@ -469,33 +433,157 @@ GenerateHashCode(io::Printer* printer) const {
}
}
-string PrimitiveFieldGenerator::GetBoxedType() const {
+string ImmutablePrimitiveFieldGenerator::GetBoxedType() const {
return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
}
// ===================================================================
-RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex,
- int builderBitIndex)
+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_);
+}
+
+ImmutablePrimitiveOneofFieldGenerator::
+~ImmutablePrimitiveOneofFieldGenerator() {}
+
+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_,
+ "$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) {
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
- &variables_);
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+RepeatedImmutablePrimitiveFieldGenerator::
+~RepeatedImmutablePrimitiveFieldGenerator() {}
-int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const {
+int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const {
return 0;
}
-int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const {
+int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -509,10 +597,11 @@ GenerateInterfaceMembers(io::Printer* printer) const {
}
-void RepeatedPrimitiveFieldGenerator::
+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"
@@ -537,7 +626,7 @@ 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
@@ -603,7 +692,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<? extends $boxed_type$> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
- " super.addAll(values, $name$_);\n"
+ " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+ " values, $name$_);\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -617,24 +707,24 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n");
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
// noop for primitives
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
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 RepeatedPrimitiveFieldGenerator::
+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
@@ -654,7 +744,7 @@ GenerateMergingCode(io::Printer* printer) const {
"}\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.
@@ -666,7 +756,7 @@ GenerateBuildingCode(io::Printer* printer) const {
"result.$name$_ = $name$_;\n");
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!$get_mutable_bit_parser$) {\n"
@@ -676,7 +766,7 @@ GenerateParsingCode(io::Printer* printer) const {
"$name$_.add(input.read$capitalized_type$());\n");
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateParsingCodeFromPacked(io::Printer* printer) const {
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
@@ -691,7 +781,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
"input.popLimit(limit);\n");
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_mutable_bit_parser$) {\n"
@@ -699,7 +789,7 @@ GenerateParsingDoneCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_,
@@ -718,7 +808,7 @@ GenerateSerializationCode(io::Printer* printer) const {
}
}
-void RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"{\n"
@@ -761,14 +851,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print("}\n");
}
-void RepeatedPrimitiveFieldGenerator::
+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 RepeatedPrimitiveFieldGenerator::
+void RepeatedImmutablePrimitiveFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"if (get$capitalized_name$Count() > 0) {\n"
@@ -777,7 +867,7 @@ GenerateHashCode(io::Printer* printer) const {
"}\n");
}
-string RepeatedPrimitiveFieldGenerator::GetBoxedType() const {
+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 1b5b6d95..489e1b20 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -41,16 +41,26 @@
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,
- int messageBitIndex, int builderBitIndex);
- ~PrimitiveFieldGenerator();
+ explicit ImmutablePrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutablePrimitiveFieldGenerator();
- // implements FieldGenerator ---------------------------------------
+ // implements ImmutableFieldGenerator ---------------------------------------
int GetNumBitsForMessage() const;
int GetNumBitsForBuilder() const;
void GenerateInterfaceMembers(io::Printer* printer) const;
@@ -70,22 +80,47 @@ class PrimitiveFieldGenerator : public FieldGenerator {
string GetBoxedType() const;
- private:
+ protected:
const FieldDescriptor* descriptor_;
map<string, string> variables_;
const int messageBitIndex_;
const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator);
+};
+
+class ImmutablePrimitiveOneofFieldGenerator
+ : public ImmutablePrimitiveFieldGenerator {
+ public:
+ ImmutablePrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutablePrimitiveOneofFieldGenerator();
+
+ 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 RepeatedPrimitiveFieldGenerator : public FieldGenerator {
+class RepeatedImmutablePrimitiveFieldGenerator
+ : public ImmutableFieldGenerator {
public:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex, int builderBitIndex);
- ~RepeatedPrimitiveFieldGenerator();
+ explicit RepeatedImmutablePrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ virtual ~RepeatedImmutablePrimitiveFieldGenerator();
- // implements FieldGenerator ---------------------------------------
+ // implements ImmutableFieldGenerator ---------------------------------------
int GetNumBitsForMessage() const;
int GetNumBitsForBuilder() const;
void GenerateInterfaceMembers(io::Printer* printer) const;
@@ -111,8 +146,10 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
map<string, string> 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 bcd80359..aa5c5231 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -33,8 +33,11 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/java/java_service.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
@@ -49,8 +52,17 @@ 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"
@@ -77,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);
@@ -98,7 +110,8 @@ void ServiceGenerator::Generate(io::Printer* printer) {
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"
@@ -106,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);
@@ -114,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"
@@ -141,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"
@@ -162,7 +175,7 @@ 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);
@@ -171,7 +184,7 @@ void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
}
}
-void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
+void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"\n"
"public final void callMethod(\n"
@@ -194,8 +207,10 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
map<string, string> 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"
@@ -217,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"
@@ -239,8 +255,10 @@ void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) {
map<string, string> 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");
@@ -259,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
@@ -283,7 +301,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
const MethodDescriptor* method = descriptor_->method(i);
map<string, string> 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"
@@ -303,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"
@@ -312,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(
@@ -335,7 +353,8 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) {
map<string, string> 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"
@@ -357,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"
@@ -399,7 +418,8 @@ void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
map<string, string> 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"
@@ -417,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<string, string> 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"
@@ -432,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<string, string> 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 e07eebf7..0d52325e 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 00000000..c9f80abf
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -0,0 +1,223 @@
+// 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 <google/protobuf/compiler/java/java_shared_code_generator.h>
+
+#include <memory>
+
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.h>
+
+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<string>* 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<io::ZeroCopyOutputStream> output(context->Open(filename));
+ scoped_ptr<io::Printer> 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",
+ "classname", classname);
+ printer->Indent();
+ GenerateDescriptors(printer.get());
+ printer->Outdent();
+ printer->Print(
+ "}\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(
+ "public static com.google.protobuf.Descriptors.FileDescriptor\n"
+ " descriptor;\n"
+ "static {\n"
+ " java.lang.String[] descriptorData = {\n");
+ printer->Indent();
+ 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<pair<string, string> > 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");
+
+ printer->Print(
+ " $classname$.class,\n"
+ " new java.lang.String[] {\n",
+ "classname", name_resolver_->GetDescriptorClassName(file_));
+ for (int i = 0; i < dependencies.size(); i++) {
+ const string& dependency = dependencies[i].second;
+ printer->Print(
+ // Here we load the dependency FileDescriptors lazily via Java
+ // reflection. This is to avoid breaking proto1 targets who have
+ // genproto dependencies for which we can't generate the descriptor
+ // class. They will compile fine but when users try to call reflection
+ // functions upon them it will fail. Users will have to get rid of
+ // genproto dependencies before they can use proto2 reflection on
+ // proto1 messages.
+ " \"$dependency$\",\n",
+ "dependency", dependency);
+ }
+
+ printer->Print(
+ " }, new java.lang.String[] {\n");
+
+ for (int i = 0; i < dependencies.size(); i++) {
+ const string& filename = dependencies[i].first;
+ printer->Print(
+ " \"$filename$\",\n",
+ "filename", filename);
+ }
+
+ printer->Print(
+ " }, assigner);\n");
+
+ printer->Outdent();
+ printer->Print(
+ "}\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 00000000..c5457bf1
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.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: 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 <memory>
+#include <string>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+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<string>* file_list);
+
+ private:
+ void GenerateDescriptors(io::Printer* printer);
+
+ // 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<ClassNameResolver> 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
index 4815663b..374e1d4e 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -36,10 +36,12 @@
#include <map>
#include <string>
-#include <google/protobuf/compiler/java/java_string_field.h>
-#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_string_field.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
@@ -57,17 +59,16 @@ namespace {
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
int messageBitIndex,
int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
map<string, string>* variables) {
- (*variables)["name"] =
- UnderscoresToCamelCase(descriptor);
- (*variables)["capitalized_name"] =
- UnderscoresToCapitalizedCamelCase(descriptor);
- (*variables)["constant_name"] = FieldConstantName(descriptor);
- (*variables)["number"] = SimpleItoa(descriptor->number());
+ SetCommonFieldVariables(descriptor, info, variables);
+
(*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
- (*variables)["default"] = DefaultValue(descriptor);
- (*variables)["default_init"] = ("= " + DefaultValue(descriptor));
+ (*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(
@@ -84,16 +85,30 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["on_changed"] =
HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
- // For singular messages and builders, one bit is used for the hasField bit.
- (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
- (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex);
+ 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)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex);
- (*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"] = "";
- // For repated builders, one bit is used for whether the array is immutable.
+ (*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);
@@ -111,27 +126,34 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
GenerateSetBitToLocal(messageBitIndex);
}
+bool CheckUtf8(const FieldDescriptor* descriptor) {
+ return descriptor->file()->options().java_string_check_utf8();
+}
+
} // namespace
// ===================================================================
-StringFieldGenerator::
-StringFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex,
- int builderBitIndex)
+ImmutableStringFieldGenerator::
+ImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex) {
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
- &variables_);
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-StringFieldGenerator::~StringFieldGenerator() {}
+ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {}
-int StringFieldGenerator::GetNumBitsForMessage() const {
+int ImmutableStringFieldGenerator::GetNumBitsForMessage() const {
return 1;
}
-int StringFieldGenerator::GetNumBitsForBuilder() const {
+int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
@@ -167,11 +189,13 @@ int StringFieldGenerator::GetNumBitsForBuilder() const {
// 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 StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$boolean has$capitalized_name$();\n");
+ 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");
@@ -181,15 +205,19 @@ GenerateInterfaceMembers(io::Printer* printer) const {
" get$capitalized_name$Bytes();\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private java.lang.Object $name$_;\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public boolean has$capitalized_name$() {\n"
- " return $get_has_field_bit_message$;\n"
- "}\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_,
@@ -200,10 +228,17 @@ GenerateMembers(io::Printer* printer) const {
" } else {\n"
" com.google.protobuf.ByteString bs = \n"
" (com.google.protobuf.ByteString) ref;\n"
- " java.lang.String s = bs.toStringUtf8();\n"
- " if (bs.isValidUtf8()) {\n"
- " $name$_ = s;\n"
- " }\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");
@@ -224,24 +259,36 @@ GenerateMembers(io::Printer* printer) const {
"}\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"private java.lang.Object $name$_ $default_init$;\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public boolean has$capitalized_name$() {\n"
- " return $get_has_field_bit_builder$;\n"
- "}\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"
- " java.lang.String s = ((com.google.protobuf.ByteString) ref)\n"
- " .toStringUtf8();\n"
- " $name$_ = s;\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"
@@ -269,7 +316,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public Builder set$capitalized_name$(\n"
" java.lang.String value) {\n"
"$null_check$"
- " $set_has_field_bit_builder$;\n"
+ " $set_has_field_bit_builder$\n"
" $name$_ = value;\n"
" $on_changed$\n"
" return this;\n"
@@ -277,7 +324,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
- " $clear_has_field_bit_builder$;\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_,
@@ -291,89 +338,113 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public Builder set$capitalized_name$Bytes(\n"
" com.google.protobuf.ByteString value) {\n"
- "$null_check$"
- " $set_has_field_bit_builder$;\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 StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
// noop for primitives
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $default$;\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = $default$;\n"
- "$clear_has_field_bit_builder$;\n");
+ "$clear_has_field_bit_builder$\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
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_,
- "if (other.has$capitalized_name$()) {\n"
- " $set_has_field_bit_builder$;\n"
- " $name$_ = other.$name$_;\n"
- " $on_changed$\n"
- "}\n");
+ 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 StringFieldGenerator::
+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_,
- "if ($get_has_field_bit_from_local$) {\n"
- " $set_has_field_bit_to_local$;\n"
- "}\n"
"result.$name$_ = $name$_;\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "$set_has_field_bit_message$;\n"
- "$name$_ = input.readBytes();\n");
+ 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 StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
// noop for strings.
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($get_has_field_bit_message$) {\n"
+ "if ($is_field_present_message$) {\n"
" output.writeBytes($number$, get$capitalized_name$Bytes());\n"
"}\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
- "if ($get_has_field_bit_message$) {\n"
+ "if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
" .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
"}\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"result = result && get$capitalized_name$()\n"
" .equals(other.get$capitalized_name$());\n");
}
-void StringFieldGenerator::
+void ImmutableStringFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"hash = (37 * hash) + $constant_name$;\n");
@@ -381,39 +452,270 @@ GenerateHashCode(io::Printer* printer) const {
"hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
}
-string StringFieldGenerator::GetBoxedType() const {
+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");
+}
// ===================================================================
-RepeatedStringFieldGenerator::
-RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex,
- int builderBitIndex)
+RepeatedImmutableStringFieldGenerator::
+RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
: descriptor_(descriptor), messageBitIndex_(messageBitIndex),
- builderBitIndex_(builderBitIndex) {
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
- &variables_);
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
}
-RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
+RepeatedImmutableStringFieldGenerator::
+~RepeatedImmutableStringFieldGenerator() {}
-int RepeatedStringFieldGenerator::GetNumBitsForMessage() const {
+int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const {
return 0;
}
-int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const {
+int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const {
return 1;
}
-void RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$java.util.List<java.lang.String>\n"
- "get$capitalized_name$List();\n");
+ "$deprecation$com.google.protobuf.ProtocolStringList\n"
+ " get$capitalized_name$List();\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$int get$capitalized_name$Count();\n");
@@ -427,13 +729,14 @@ GenerateInterfaceMembers(io::Printer* printer) const {
}
-void RepeatedStringFieldGenerator::
+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 java.util.List<java.lang.String>\n"
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
" get$capitalized_name$List() {\n"
" return $name$_;\n" // note: unmodifiable list
"}\n");
@@ -461,7 +764,7 @@ GenerateMembers(io::Printer* printer) const {
}
}
-void RepeatedStringFieldGenerator::
+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
@@ -489,9 +792,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
// immutable.
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$public java.util.List<java.lang.String>\n"
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
" get$capitalized_name$List() {\n"
- " return java.util.Collections.unmodifiableList($name$_);\n"
+ " return $name$_.getUnmodifiableView();\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -534,7 +837,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<java.lang.String> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
- " super.addAll(values, $name$_);\n"
+ " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
+ " values, $name$_);\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -551,7 +855,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public Builder add$capitalized_name$Bytes(\n"
" com.google.protobuf.ByteString value) {\n"
- "$null_check$"
+ "$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"
@@ -559,24 +868,24 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n");
}
-void RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
// noop for primitives
}
-void RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_ = $empty_list$;\n");
}
-void RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
printer->Print(variables_,
"$name$_ = $empty_list$;\n"
"$clear_mutable_bit_builder$;\n");
}
-void RepeatedStringFieldGenerator::
+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
@@ -596,31 +905,43 @@ GenerateMergingCode(io::Printer* printer) const {
"}\n");
}
-void RepeatedStringFieldGenerator::
+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$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n"
- " $name$_);\n"
+ " $name$_ = $name$_.getUnmodifiableView();\n"
" $clear_mutable_bit_builder$;\n"
"}\n"
"result.$name$_ = $name$_;\n");
}
-void RepeatedStringFieldGenerator::
+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"
- "$name$_.add(input.readBytes());\n");
+ "}\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "$name$_.add(s);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.add(bs);\n");
+ }
}
-void RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateParsingCodeFromPacked(io::Printer* printer) const {
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
@@ -629,21 +950,30 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
" $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
" $set_mutable_bit_parser$;\n"
"}\n"
- "while (input.getBytesUntilLimit() > 0) {\n"
- " $name$.add(input.read$capitalized_type$());\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 RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateParsingDoneCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($get_mutable_bit_parser$) {\n"
- " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n"
+ " $name$_ = $name$_.getUnmodifiableView();\n"
"}\n");
}
-void RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
if (descriptor_->options().packed()) {
printer->Print(variables_,
@@ -662,7 +992,7 @@ GenerateSerializationCode(io::Printer* printer) const {
}
}
-void RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"{\n"
@@ -700,14 +1030,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print("}\n");
}
-void RepeatedStringFieldGenerator::
+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 RepeatedStringFieldGenerator::
+void RepeatedImmutableStringFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"if (get$capitalized_name$Count() > 0) {\n"
@@ -716,7 +1046,7 @@ GenerateHashCode(io::Printer* printer) const {
"}\n");
}
-string RepeatedStringFieldGenerator::GetBoxedType() const {
+string RepeatedImmutableStringFieldGenerator::GetBoxedType() const {
return "String";
}
diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h
index 4f7532f4..348cbcbd 100644
--- a/src/google/protobuf/compiler/java/java_string_field.h
+++ b/src/google/protobuf/compiler/java/java_string_field.h
@@ -42,16 +42,26 @@
namespace google {
namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
namespace compiler {
namespace java {
-class StringFieldGenerator : public FieldGenerator {
+class ImmutableStringFieldGenerator : public ImmutableFieldGenerator {
public:
- explicit StringFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex, int builderBitIndex);
- ~StringFieldGenerator();
+ explicit ImmutableStringFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableStringFieldGenerator();
- // implements FieldGenerator ---------------------------------------
+ // implements ImmutableFieldGenerator ---------------------------------------
int GetNumBitsForMessage() const;
int GetNumBitsForBuilder() const;
void GenerateInterfaceMembers(io::Printer* printer) const;
@@ -68,24 +78,49 @@ class StringFieldGenerator : public FieldGenerator {
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<string, string> variables_;
const int messageBitIndex_;
const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator);
};
-class RepeatedStringFieldGenerator : public FieldGenerator {
+class ImmutableStringOneofFieldGenerator
+ : public ImmutableStringFieldGenerator {
public:
- explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
- int messageBitIndex, int builderBitIndex);
- ~RepeatedStringFieldGenerator();
+ ImmutableStringOneofFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableStringOneofFieldGenerator();
- // implements FieldGenerator ---------------------------------------
+ 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;
@@ -103,6 +138,7 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
+
string GetBoxedType() const;
private:
@@ -110,8 +146,10 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
map<string, string> variables_;
const int messageBitIndex_;
const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator);
};
} // namespace java
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 0e35ed19..1f91817f 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -32,6 +32,8 @@
#include <google/protobuf/compiler/mock_code_generator.h>
+#include <memory>
+
#include <google/protobuf/testing/file.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
@@ -53,7 +55,7 @@ string CommaSeparatedList(const vector<const FileDescriptor*> all_files) {
for (int i = 0; i < all_files.size(); i++) {
names.push_back(all_files[i]->name());
}
- return JoinStrings(names, ",");
+ return Join(names, ",");
}
static const char* kFirstInsertionPointName = "first_mock_insertion_point";
@@ -77,11 +79,11 @@ void MockCodeGenerator::ExpectGenerated(
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<string> lines;
- SplitStringUsing(content, "\n", &lines);
+ vector<string> lines = Split(content, "\n", true);
while (!lines.empty() && lines.back().empty()) {
lines.pop_back();
@@ -95,7 +97,7 @@ void MockCodeGenerator::ExpectGenerated(
SplitStringUsing(insertions, ",", &insertion_list);
}
- ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
+ EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2);
EXPECT_EQ(GetOutputFileContent(name, parameter, file,
first_parsed_file_name, first_message_name),
lines[0]);
@@ -155,10 +157,8 @@ bool MockCodeGenerator::Generate(
for (int i = 0; i < insert_into.size(); i++) {
{
- scoped_ptr<io::ZeroCopyOutputStream> output(
- context->OpenForInsert(
- GetOutputFileName(insert_into[i], file),
- kFirstInsertionPointName));
+ scoped_ptr<io::ZeroCopyOutputStream> output(context->OpenForInsert(
+ GetOutputFileName(insert_into[i], file), kFirstInsertionPointName));
io::Printer printer(output.get(), '$');
printer.PrintRaw(GetOutputFileContent(name_, "first_insert",
file, context));
@@ -170,9 +170,8 @@ bool MockCodeGenerator::Generate(
{
scoped_ptr<io::ZeroCopyOutputStream> output(
- context->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, context));
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 23aa01ce..7e0df7e1 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -46,7 +46,7 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
namespace google {
namespace protobuf {
@@ -343,6 +343,11 @@ void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) {
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);
@@ -489,15 +494,15 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
} else if (LookingAt("message")) {
LocationRecorder location(root_location,
FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size());
- return ParseMessageDefinition(file->add_message_type(), location);
+ return ParseMessageDefinition(file->add_message_type(), location, file);
} else if (LookingAt("enum")) {
LocationRecorder location(root_location,
FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size());
- return ParseEnumDefinition(file->add_enum_type(), location);
+ return ParseEnumDefinition(file->add_enum_type(), location, file);
} else if (LookingAt("service")) {
LocationRecorder location(root_location,
FileDescriptorProto::kServiceFieldNumber, file->service_size());
- return ParseServiceDefinition(file->add_service(), location);
+ return ParseServiceDefinition(file->add_service(), location, file);
} else if (LookingAt("extend")) {
LocationRecorder location(root_location,
FileDescriptorProto::kExtensionFieldNumber);
@@ -505,18 +510,19 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
file->mutable_message_type(),
root_location,
FileDescriptorProto::kMessageTypeFieldNumber,
- location);
+ location, file);
} else if (LookingAt("import")) {
return ParseImport(file->mutable_dependency(),
file->mutable_public_dependency(),
file->mutable_weak_dependency(),
- root_location);
+ root_location, file);
} else if (LookingAt("package")) {
- return ParsePackage(file, root_location);
+ return ParsePackage(file, root_location, file);
} else if (LookingAt("option")) {
LocationRecorder location(root_location,
FileDescriptorProto::kOptionsFieldNumber);
- return ParseOption(file->mutable_options(), location, OPTION_STATEMENT);
+ return ParseOption(file->mutable_options(), location, file,
+ OPTION_STATEMENT);
} else {
AddError("Expected top-level statement (e.g. \"message\").");
return false;
@@ -526,8 +532,10 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
// -------------------------------------------------------------------
// Messages
-bool Parser::ParseMessageDefinition(DescriptorProto* message,
- const LocationRecorder& message_location) {
+bool Parser::ParseMessageDefinition(
+ DescriptorProto* message,
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file) {
DO(Consume("message"));
{
LocationRecorder location(message_location,
@@ -536,7 +544,7 @@ bool Parser::ParseMessageDefinition(DescriptorProto* message,
message, DescriptorPool::ErrorCollector::NAME);
DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
}
- DO(ParseMessageBlock(message, message_location));
+ DO(ParseMessageBlock(message, message_location, containing_file));
return true;
}
@@ -575,7 +583,8 @@ void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
} // namespace
bool Parser::ParseMessageBlock(DescriptorProto* message,
- const LocationRecorder& message_location) {
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file) {
DO(ConsumeEndOfDeclaration("{", &message_location));
while (!TryConsumeEndOfDeclaration("}", NULL)) {
@@ -584,7 +593,7 @@ bool Parser::ParseMessageBlock(DescriptorProto* message,
return false;
}
- if (!ParseMessageStatement(message, message_location)) {
+ if (!ParseMessageStatement(message, message_location, containing_file)) {
// This statement failed to parse. Skip it, but keep looping to parse
// other statements.
SkipStatement();
@@ -598,7 +607,8 @@ bool Parser::ParseMessageBlock(DescriptorProto* message,
}
bool Parser::ParseMessageStatement(DescriptorProto* message,
- const LocationRecorder& message_location) {
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file) {
if (TryConsumeEndOfDeclaration(";", NULL)) {
// empty statement; ignore
return true;
@@ -606,16 +616,18 @@ bool Parser::ParseMessageStatement(DescriptorProto* message,
LocationRecorder location(message_location,
DescriptorProto::kNestedTypeFieldNumber,
message->nested_type_size());
- return ParseMessageDefinition(message->add_nested_type(), location);
+ return ParseMessageDefinition(message->add_nested_type(), location,
+ containing_file);
} else if (LookingAt("enum")) {
LocationRecorder location(message_location,
DescriptorProto::kEnumTypeFieldNumber,
message->enum_type_size());
- return ParseEnumDefinition(message->add_enum_type(), location);
+ return ParseEnumDefinition(message->add_enum_type(), location,
+ containing_file);
} else if (LookingAt("extensions")) {
LocationRecorder location(message_location,
DescriptorProto::kExtensionRangeFieldNumber);
- return ParseExtensions(message, location);
+ return ParseExtensions(message, location, containing_file);
} else if (LookingAt("extend")) {
LocationRecorder location(message_location,
DescriptorProto::kExtensionFieldNumber);
@@ -623,11 +635,21 @@ bool Parser::ParseMessageStatement(DescriptorProto* message,
message->mutable_nested_type(),
message_location,
DescriptorProto::kNestedTypeFieldNumber,
- location);
+ location, containing_file);
} else if (LookingAt("option")) {
LocationRecorder location(message_location,
DescriptorProto::kOptionsFieldNumber);
- return ParseOption(message->mutable_options(), location, OPTION_STATEMENT);
+ 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,
@@ -636,7 +658,8 @@ bool Parser::ParseMessageStatement(DescriptorProto* message,
message->mutable_nested_type(),
message_location,
DescriptorProto::kNestedTypeFieldNumber,
- location);
+ location,
+ containing_file);
}
}
@@ -644,17 +667,30 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
RepeatedPtrField<DescriptorProto>* messages,
const LocationRecorder& parent_location,
int location_field_number_for_nested_type,
- const LocationRecorder& field_location) {
- // Parse label and type.
- io::Tokenizer::Token label_token = input_->current();
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
{
LocationRecorder location(field_location,
FieldDescriptorProto::kLabelFieldNumber);
FieldDescriptorProto::Label label;
- DO(ParseLabel(&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<DescriptorProto>* 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);
@@ -693,14 +729,14 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
}
// Parse options.
- DO(ParseFieldOptions(field, field_location));
+ DO(ParseFieldOptions(field, field_location, containing_file));
// Deal with groups.
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(label_token);
+ group_location.StartAt(field_location);
group_location.AddPath(location_field_number_for_nested_type);
group_location.AddPath(messages->size());
@@ -736,7 +772,7 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
field->set_type_name(group->name());
if (LookingAt("{")) {
- DO(ParseMessageBlock(group, group_location));
+ DO(ParseMessageBlock(group, group_location, containing_file));
} else {
AddError("Missing group body.");
return false;
@@ -749,7 +785,8 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
}
bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
- const LocationRecorder& field_location) {
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file) {
if (!LookingAt("[")) return true;
LocationRecorder location(field_location,
@@ -762,9 +799,10 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
if (LookingAt("default")) {
// We intentionally pass field_location rather than location here, since
// the default value is not actually an option.
- DO(ParseDefaultAssignment(field, field_location));
+ DO(ParseDefaultAssignment(field, field_location, containing_file));
} else {
- DO(ParseOption(field->mutable_options(), location, OPTION_ASSIGNMENT));
+ DO(ParseOption(field->mutable_options(), location,
+ containing_file, OPTION_ASSIGNMENT));
}
} while (TryConsume(","));
@@ -772,8 +810,10 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
return true;
}
-bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field,
- const LocationRecorder& field_location) {
+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();
@@ -790,8 +830,16 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field,
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;
}
@@ -817,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;
@@ -839,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;
@@ -871,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:
@@ -880,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:
@@ -893,7 +948,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field,
}
bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
- const LocationRecorder& part_location) {
+ 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.
@@ -957,6 +1013,7 @@ bool Parser::ParseUninterpretedBlock(string* value) {
// UninterpretedOption, to be interpreted later.
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()->
@@ -988,14 +1045,16 @@ bool Parser::ParseOption(Message* options,
{
LocationRecorder part_location(name_location,
uninterpreted_option->name_size());
- DO(ParseOptionNamePart(uninterpreted_option, part_location));
+ DO(ParseOptionNamePart(uninterpreted_option, part_location,
+ containing_file));
}
while (LookingAt(".")) {
DO(Consume("."));
LocationRecorder part_location(name_location,
uninterpreted_option->name_size());
- DO(ParseOptionNamePart(uninterpreted_option, part_location));
+ DO(ParseOptionNamePart(uninterpreted_option, part_location,
+ containing_file));
}
}
@@ -1088,11 +1147,13 @@ bool Parser::ParseOption(Message* options,
DO(ConsumeEndOfDeclaration(";", &location));
}
+
return true;
}
bool Parser::ParseExtensions(DescriptorProto* message,
- const LocationRecorder& extensions_location) {
+ const LocationRecorder& extensions_location,
+ const FileDescriptorProto* containing_file) {
// Parse the declaration.
DO(Consume("extensions"));
@@ -1150,7 +1211,8 @@ bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
RepeatedPtrField<DescriptorProto>* messages,
const LocationRecorder& parent_location,
int location_field_number_for_nested_type,
- const LocationRecorder& extend_location) {
+ const LocationRecorder& extend_location,
+ const FileDescriptorProto* containing_file) {
DO(Consume("extend"));
// Parse the extendee type.
@@ -1192,7 +1254,65 @@ bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
if (!ParseMessageField(field, messages, parent_location,
location_field_number_for_nested_type,
- location)) {
+ location,
+ containing_file)) {
+ // This statement failed to parse. Skip it, but keep looping to parse
+ // other statements.
+ SkipStatement();
+ }
+ } 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();
@@ -1206,7 +1326,8 @@ bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
// Enums
bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type,
- const LocationRecorder& enum_location) {
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file) {
DO(Consume("enum"));
{
@@ -1217,12 +1338,13 @@ bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type,
DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
}
- DO(ParseEnumBlock(enum_type, enum_location));
+ DO(ParseEnumBlock(enum_type, enum_location, containing_file));
return true;
}
bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
- const LocationRecorder& enum_location) {
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file) {
DO(ConsumeEndOfDeclaration("{", &enum_location));
while (!TryConsumeEndOfDeclaration("}", NULL)) {
@@ -1231,7 +1353,7 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
return false;
}
- if (!ParseEnumStatement(enum_type, enum_location)) {
+ if (!ParseEnumStatement(enum_type, enum_location, containing_file)) {
// This statement failed to parse. Skip it, but keep looping to parse
// other statements.
SkipStatement();
@@ -1242,7 +1364,8 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
}
bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
- const LocationRecorder& enum_location) {
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file) {
if (TryConsumeEndOfDeclaration(";", NULL)) {
// empty statement; ignore
return true;
@@ -1250,16 +1373,17 @@ bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
LocationRecorder location(enum_location,
EnumDescriptorProto::kOptionsFieldNumber);
return ParseOption(enum_type->mutable_options(), location,
- OPTION_STATEMENT);
+ containing_file, OPTION_STATEMENT);
} else {
LocationRecorder location(enum_location,
EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
- return ParseEnumConstant(enum_type->add_value(), location);
+ return ParseEnumConstant(enum_type->add_value(), location, containing_file);
}
}
bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
- const LocationRecorder& enum_value_location) {
+ const LocationRecorder& enum_value_location,
+ const FileDescriptorProto* containing_file) {
// Parse name.
{
LocationRecorder location(enum_value_location,
@@ -1284,7 +1408,8 @@ bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
enum_value->set_number(number);
}
- DO(ParseEnumConstantOptions(enum_value, enum_value_location));
+ DO(ParseEnumConstantOptions(enum_value, enum_value_location,
+ containing_file));
DO(ConsumeEndOfDeclaration(";", &enum_value_location));
@@ -1293,7 +1418,8 @@ bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
bool Parser::ParseEnumConstantOptions(
EnumValueDescriptorProto* value,
- const LocationRecorder& enum_value_location) {
+ const LocationRecorder& enum_value_location,
+ const FileDescriptorProto* containing_file) {
if (!LookingAt("[")) return true;
LocationRecorder location(
@@ -1302,7 +1428,8 @@ bool Parser::ParseEnumConstantOptions(
DO(Consume("["));
do {
- DO(ParseOption(value->mutable_options(), location, OPTION_ASSIGNMENT));
+ DO(ParseOption(value->mutable_options(), location,
+ containing_file, OPTION_ASSIGNMENT));
} while (TryConsume(","));
DO(Consume("]"));
@@ -1312,8 +1439,10 @@ bool Parser::ParseEnumConstantOptions(
// -------------------------------------------------------------------
// Services
-bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service,
- const LocationRecorder& service_location) {
+bool Parser::ParseServiceDefinition(
+ ServiceDescriptorProto* service,
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file) {
DO(Consume("service"));
{
@@ -1324,12 +1453,13 @@ bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service,
DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
}
- DO(ParseServiceBlock(service, service_location));
+ DO(ParseServiceBlock(service, service_location, containing_file));
return true;
}
bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
- const LocationRecorder& service_location) {
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file) {
DO(ConsumeEndOfDeclaration("{", &service_location));
while (!TryConsumeEndOfDeclaration("}", NULL)) {
@@ -1338,7 +1468,7 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
return false;
}
- if (!ParseServiceStatement(service, service_location)) {
+ if (!ParseServiceStatement(service, service_location, containing_file)) {
// This statement failed to parse. Skip it, but keep looping to parse
// other statements.
SkipStatement();
@@ -1349,23 +1479,26 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
}
bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
- const LocationRecorder& service_location) {
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file) {
if (TryConsumeEndOfDeclaration(";", NULL)) {
// empty statement; ignore
return true;
} else if (LookingAt("option")) {
LocationRecorder location(
service_location, ServiceDescriptorProto::kOptionsFieldNumber);
- return ParseOption(service->mutable_options(), location, OPTION_STATEMENT);
+ return ParseOption(service->mutable_options(), location,
+ containing_file, OPTION_STATEMENT);
} else {
LocationRecorder location(service_location,
ServiceDescriptorProto::kMethodFieldNumber, service->method_size());
- return ParseServiceMethod(service->add_method(), location);
+ return ParseServiceMethod(service->add_method(), location, containing_file);
}
}
bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
- const LocationRecorder& method_location) {
+ const LocationRecorder& method_location,
+ const FileDescriptorProto* containing_file) {
DO(Consume("rpc"));
{
@@ -1402,6 +1535,7 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
if (LookingAt("{")) {
// Options!
DO(ParseOptions(method_location,
+ containing_file,
MethodDescriptorProto::kOptionsFieldNumber,
method->mutable_options()));
} else {
@@ -1413,6 +1547,7 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
bool Parser::ParseOptions(const LocationRecorder& parent_location,
+ const FileDescriptorProto* containing_file,
const int optionsFieldNumber,
Message* mutable_options) {
// Options!
@@ -1428,7 +1563,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location,
} else {
LocationRecorder location(parent_location,
optionsFieldNumber);
- if (!ParseOption(mutable_options, location, OPTION_STATEMENT)) {
+ if (!ParseOption(mutable_options, location, containing_file,
+ OPTION_STATEMENT)) {
// This statement failed to parse. Skip it, but keep looping to
// parse other statements.
SkipStatement();
@@ -1441,7 +1577,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location,
// -------------------------------------------------------------------
-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;
@@ -1510,7 +1647,8 @@ bool Parser::ParseUserDefinedType(string* type_name) {
// ===================================================================
bool Parser::ParsePackage(FileDescriptorProto* file,
- const LocationRecorder& root_location) {
+ 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
@@ -1544,7 +1682,8 @@ bool Parser::ParsePackage(FileDescriptorProto* file,
bool Parser::ParseImport(RepeatedPtrField<string>* dependency,
RepeatedField<int32>* public_dependency,
RepeatedField<int32>* weak_dependency,
- const LocationRecorder& root_location) {
+ const LocationRecorder& root_location,
+ const FileDescriptorProto* containing_file) {
DO(Consume("import"));
if (LookingAt("public")) {
LocationRecorder location(
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index cfd3649b..6bca7fa7 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -40,7 +40,6 @@
#include <map>
#include <string>
#include <utility>
-#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/repeated_field.h>
@@ -233,6 +232,9 @@ class LIBPROTOBUF_EXPORT Parser {
// 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.
@@ -284,38 +286,50 @@ class LIBPROTOBUF_EXPORT Parser {
// Parse various language high-level language construrcts.
bool ParseMessageDefinition(DescriptorProto* message,
- const LocationRecorder& message_location);
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file);
bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
- const LocationRecorder& enum_location);
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file);
bool ParseServiceDefinition(ServiceDescriptorProto* service,
- const LocationRecorder& service_location);
+ const LocationRecorder& service_location,
+ const FileDescriptorProto* containing_file);
bool ParsePackage(FileDescriptorProto* file,
- const LocationRecorder& root_location);
+ const LocationRecorder& root_location,
+ const FileDescriptorProto* containing_file);
bool ParseImport(RepeatedPtrField<string>* dependency,
RepeatedField<int32>* public_dependency,
RepeatedField<int32>* weak_dependency,
- const LocationRecorder& root_location);
+ const LocationRecorder& root_location,
+ const FileDescriptorProto* containing_file);
bool ParseOption(Message* options,
- const LocationRecorder& options_location);
+ 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,
- const LocationRecorder& message_location);
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file);
bool ParseEnumBlock(EnumDescriptorProto* enum_type,
- const LocationRecorder& enum_location);
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file);
bool ParseServiceBlock(ServiceDescriptorProto* service,
- const LocationRecorder& service_location);
+ 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,
- const LocationRecorder& message_location);
+ const LocationRecorder& message_location,
+ const FileDescriptorProto* containing_file);
bool ParseEnumStatement(EnumDescriptorProto* message,
- const LocationRecorder& enum_location);
+ const LocationRecorder& enum_location,
+ const FileDescriptorProto* containing_file);
bool ParseServiceStatement(ServiceDescriptorProto* message,
- const LocationRecorder& service_location);
+ 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".
@@ -329,11 +343,22 @@ class LIBPROTOBUF_EXPORT Parser {
RepeatedPtrField<DescriptorProto>* messages,
const LocationRecorder& parent_location,
int location_field_number_for_nested_type,
- const LocationRecorder& field_location);
+ 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<DescriptorProto>* 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,
- const LocationRecorder& extensions_location);
+ const LocationRecorder& extensions_location,
+ const FileDescriptorProto* containing_file);
// Parse an "extend" declaration. (See also comments for
// ParseMessageField().)
@@ -341,30 +366,46 @@ class LIBPROTOBUF_EXPORT Parser {
RepeatedPtrField<DescriptorProto>* messages,
const LocationRecorder& parent_location,
int location_field_number_for_nested_type,
- const LocationRecorder& extend_location);
+ 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,
- const LocationRecorder& enum_value_location);
+ 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,
- const LocationRecorder& enum_value_location);
+ const LocationRecorder& enum_value_location,
+ const FileDescriptorProto* containing_file);
// Parse a single method within a service definition.
bool ParseServiceMethod(MethodDescriptorProto* method,
- const LocationRecorder& method_location);
+ 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.
@@ -377,12 +418,14 @@ 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,
- const LocationRecorder& field_location);
+ 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,
- const LocationRecorder& field_location);
+ const LocationRecorder& field_location,
+ const FileDescriptorProto* containing_file);
enum OptionStyle {
OPTION_ASSIGNMENT, // just "name = value"
@@ -394,6 +437,7 @@ class LIBPROTOBUF_EXPORT Parser {
// is set to the parsed value.
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
@@ -401,7 +445,8 @@ class LIBPROTOBUF_EXPORT Parser {
// of identifiers separated by dots and enclosed in parentheses. E.g.,
// "foo.(bar.baz).qux".
bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
- const LocationRecorder& part_location);
+ 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.
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index c61ac60e..847370a8 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <memory>
#include <vector>
#include <algorithm>
#include <map>
@@ -47,7 +48,7 @@
#include <google/protobuf/unittest_custom_options.pb.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -436,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"
@@ -575,6 +639,7 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
" type_name:\"TestMessage\" extendee: \"Extendee1\" }");
}
+
// ===================================================================
typedef ParserTest ParseEnumTest;
@@ -681,6 +746,8 @@ TEST_F(ParseServiceTest, MethodsAndStreams) {
"}");
}
+
+
// ===================================================================
// imports and packages
@@ -870,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) {
@@ -886,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) {
@@ -934,7 +1001,7 @@ TEST_F(ParseErrorTest, DefaultValueMissing) {
"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) {
@@ -953,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"
@@ -1244,17 +1332,93 @@ TEST_F(ParserValidationErrorTest, MethodOutputTypeError) {
}
+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();
}
};
@@ -1298,7 +1462,8 @@ 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
@@ -1317,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);
@@ -1871,6 +2038,31 @@ TEST_F(SourceInfoTest, ExtensionRanges) {
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"
@@ -2029,6 +2221,7 @@ TEST_F(SourceInfoTest, MethodsAndStreams) {
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$ = "
@@ -2365,6 +2558,51 @@ TEST_F(SourceInfoTest, DocComments3) {
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.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 6525d15c..b5cd01b5 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -171,6 +171,7 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber;
CodeGeneratorRequest::CodeGeneratorRequest()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
}
void CodeGeneratorRequest::InitAsDefaultInstance() {
@@ -180,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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete parameter_;
}
if (this != default_instance_) {
@@ -222,11 +226,9 @@ CodeGeneratorRequest* CodeGeneratorRequest::New() const {
}
void CodeGeneratorRequest::Clear() {
- if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
- if (has_parameter()) {
- if (parameter_ != &::google::protobuf::internal::GetEmptyString()) {
- parameter_->clear();
- }
+ if (has_parameter()) {
+ if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+ parameter_->clear();
}
}
file_to_generate_.Clear();
@@ -237,23 +239,27 @@ 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(
+ ::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);
+ ::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;
@@ -262,16 +268,16 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
// 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;
@@ -279,24 +285,24 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
// 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()));
@@ -304,27 +310,35 @@ 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_parameter()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -338,24 +352,28 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::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_parameter()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -372,6 +390,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest)
return target;
}
@@ -451,9 +470,7 @@ 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;
}
@@ -488,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() {
@@ -497,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*>(&::google::protobuf::internal::GetEmptyString());
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete insertion_point_;
}
- if (content_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete content_;
}
if (this != default_instance_) {
@@ -547,19 +568,19 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const {
}
void CodeGeneratorResponse_File::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 7) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
if (has_insertion_point()) {
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
insertion_point_->clear();
}
}
if (has_content()) {
- if (content_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
content_->clear();
}
}
@@ -570,21 +591,25 @@ 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;
@@ -592,16 +617,16 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
// 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;
@@ -609,26 +634,27 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
// 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()));
@@ -636,36 +662,45 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_insertion_point()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_content()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -673,15 +708,18 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -689,9 +727,10 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
// optional string insertion_point = 2;
if (has_insertion_point()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -699,9 +738,10 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
// optional string content = 15;
if (has_content()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -711,6 +751,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File)
return target;
}
@@ -826,6 +867,7 @@ const int CodeGeneratorResponse::kFileFieldNumber;
CodeGeneratorResponse::CodeGeneratorResponse()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
void CodeGeneratorResponse::InitAsDefaultInstance() {
@@ -835,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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete error_;
}
if (this != default_instance_) {
@@ -877,11 +922,9 @@ CodeGeneratorResponse* CodeGeneratorResponse::New() const {
}
void CodeGeneratorResponse::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- if (has_error()) {
- if (error_ != &::google::protobuf::internal::GetEmptyString()) {
- error_->clear();
- }
+ if (has_error()) {
+ if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+ error_->clear();
}
}
file_.Clear();
@@ -891,21 +934,25 @@ 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;
@@ -913,24 +960,24 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
// 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()));
@@ -938,18 +985,25 @@ 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_error()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -963,15 +1017,18 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
::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_error()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -988,6 +1045,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse)
return target;
}
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index d26a135e..b590d8df 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -89,7 +89,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -143,13 +142,11 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
::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_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
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();
@@ -206,7 +203,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -260,13 +256,11 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* name_;
::std::string* insertion_point_;
::std::string* content_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
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();
@@ -323,7 +317,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -363,12 +356,10 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* error_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
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();
@@ -391,39 +382,49 @@ 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<const char*>(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<const char*>(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_;
}
@@ -438,54 +439,59 @@ inline void CodeGeneratorRequest::clear_has_parameter() {
_has_bits_[0] &= ~0x00000002u;
}
inline void CodeGeneratorRequest::clear_parameter() {
- if (parameter_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
parameter_->clear();
}
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_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
parameter_ = new ::std::string;
}
parameter_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
set_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = parameter_;
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete parameter_;
}
if (parameter) {
@@ -493,8 +499,9 @@ inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* paramet
parameter_ = parameter;
} else {
clear_has_parameter();
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -505,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_;
}
@@ -537,54 +549,59 @@ inline void CodeGeneratorResponse_File::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void CodeGeneratorResponse_File::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -592,8 +609,9 @@ inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name)
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -607,54 +625,59 @@ inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
_has_bits_[0] &= ~0x00000002u;
}
inline void CodeGeneratorResponse_File::clear_insertion_point() {
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
insertion_point_->clear();
}
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_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
insertion_point_ = new ::std::string;
}
insertion_point_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
set_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = insertion_point_;
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete insertion_point_;
}
if (insertion_point) {
@@ -662,8 +685,9 @@ inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::str
insertion_point_ = insertion_point;
} else {
clear_has_insertion_point();
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -677,54 +701,59 @@ inline void CodeGeneratorResponse_File::clear_has_content() {
_has_bits_[0] &= ~0x00000004u;
}
inline void CodeGeneratorResponse_File::clear_content() {
- if (content_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
content_->clear();
}
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_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
content_ = new ::std::string;
}
content_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
set_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = content_;
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete content_;
}
if (content) {
@@ -732,8 +761,9 @@ inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* con
content_ = content;
} else {
clear_has_content();
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
// -------------------------------------------------------------------
@@ -751,54 +781,59 @@ inline void CodeGeneratorResponse::clear_has_error() {
_has_bits_[0] &= ~0x00000001u;
}
inline void CodeGeneratorResponse::clear_error() {
- if (error_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
error_->clear();
}
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_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
error_ = new ::std::string;
}
error_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
}
inline ::std::string* CodeGeneratorResponse::mutable_error() {
set_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = error_;
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete error_;
}
if (error) {
@@ -806,8 +841,9 @@ inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
error_ = error;
} else {
clear_has_error();
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -818,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/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 211ac70c..067d856b 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 <limits>
#include <map>
#include <utility>
+#include <memory>
#include <string>
#include <vector>
@@ -128,6 +131,7 @@ void PrintTopBoilerplate(
printer->Print(
"# Generated by the protocol buffer compiler. DO NOT EDIT!\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)) {
@@ -138,7 +142,8 @@ void PrintTopBoilerplate(
"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 as _service\n"
@@ -151,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");
}
@@ -217,14 +223,14 @@ 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()) + "\"";
- }
- case FieldDescriptor::CPPTYPE_MESSAGE:
- return "None";
+//##!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";
}
// (We could add a default case above but then we wouldn't get the nice
// compiler warning when a new type is added.)
@@ -330,14 +336,25 @@ void Generator::PrintFileDescriptor() const {
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");
}
@@ -382,7 +399,9 @@ void Generator::PrintAllNestedEnumsInFile() const {
// enum_descriptor.
void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
map<string, string> 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;
@@ -412,6 +431,8 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
PrintSerializedPbInterval(enum_descriptor, edp);
printer_->Outdent();
printer_->Print(")\n");
+ printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name",
+ module_level_descriptor_name);
printer_->Print("\n");
}
@@ -522,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();
}
@@ -635,7 +665,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<string> 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");
}
}
@@ -647,33 +682,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<string>* 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<string, string> 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<string>* 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");
}
}
@@ -714,6 +756,29 @@ void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
printer_->Print(m, file_descriptor_template);
}
+void Generator::AddEnumToFileDescriptor(
+ const EnumDescriptor& descriptor) const {
+ map<string, string> 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<string, string> 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
// for the Python version of |field|.
//
@@ -778,7 +843,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);
}
@@ -795,6 +860,12 @@ void Generator::FixForeignFieldsInDescriptors() const {
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");
}
@@ -875,8 +946,10 @@ string Generator::OptionsValue(
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
}
}
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index a3f22cee..40dfddf3 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -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<string>* to_register) const;
+ void PrintNestedMessages(const Descriptor& containing_descriptor,
+ const string& prefix,
+ vector<string>* to_register) const;
void FixForeignFieldsInDescriptors() const;
void FixForeignFieldsInDescriptor(
@@ -105,6 +108,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
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;
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index da619ad3..77da8a87 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 <memory>
+
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -68,7 +70,7 @@ class TestGenerator : public CodeGenerator {
void TryInsert(const string& filename, const string& insertion_point,
GeneratorContext* context) const {
scoped_ptr<io::ZeroCopyOutputStream> output(
- context->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 67da120d..ca4b874d 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -449,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/descriptor.cc b/src/google/protobuf/descriptor.cc
index 3f0d15f7..abd13a0b 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/stubs/hash.h>
#include <map>
#include <set>
+#include <string>
#include <vector>
#include <algorithm>
#include <limits>
@@ -43,9 +44,11 @@
#include <google/protobuf/descriptor_database.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/io/strtod.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -53,7 +56,7 @@
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
#undef PACKAGE // autoheader #defines this. :(
@@ -131,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;
@@ -234,13 +239,14 @@ struct PointerStringPairHash {
struct Symbol {
enum Type {
- NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD,
+ 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;
@@ -266,6 +272,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 )
@@ -278,6 +285,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();
@@ -314,7 +322,7 @@ typedef hash_map<EnumIntPair, const EnumValueDescriptor*,
// for that.
typedef map<DescriptorIntPair, const FieldDescriptor*>
ExtensionsGroupedByDescriptorMap;
-
+typedef hash_map<string, const SourceCodeInfo_Location*> LocationsByPathMap;
} // anonymous namespace
// ===================================================================
@@ -368,10 +376,18 @@ class DescriptorPool::Tables {
vector<string> 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<string> 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<string> known_bad_symbols_;
+
// The set of descriptors for which we've already loaded the full
// set of extensions numbers from fallback_database_.
hash_set<const Descriptor*> extensions_loaded_from_db_;
@@ -388,7 +404,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;
@@ -529,17 +545,34 @@ 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<const FileDescriptorTables*, const SourceCodeInfo*>* 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<int>& 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()
// 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) {}
@@ -663,8 +696,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) {
@@ -835,6 +870,22 @@ void* DescriptorPool::Tables::AllocateBytes(int size) {
return result;
}
+void FileDescriptorTables::BuildLocationsByPath(
+ pair<const FileDescriptorTables*, const SourceCodeInfo*>* 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<int>& path, const SourceCodeInfo* info) const {
+ pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
+ make_pair(this, info));
+ locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p);
+ return FindPtrOrNull(locations_by_path_, Join(path, ","));
+}
+
// ===================================================================
// DescriptorPool
@@ -847,7 +898,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)
@@ -857,7 +909,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)
@@ -867,7 +920,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_;
@@ -880,6 +934,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;
@@ -961,6 +1023,8 @@ 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) {
@@ -977,6 +1041,8 @@ 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) {
@@ -1019,6 +1085,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);
@@ -1047,6 +1119,8 @@ 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;
@@ -1067,6 +1141,8 @@ const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
void DescriptorPool::FindAllExtensions(
const Descriptor* extendee, vector<const FieldDescriptor*>* 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).
@@ -1091,6 +1167,7 @@ void DescriptorPool::FindAllExtensions(
}
}
+
// -------------------------------------------------------------------
const FieldDescriptor*
@@ -1137,6 +1214,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 =
@@ -1301,16 +1389,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;
}
// -------------------------------------------------------------------
@@ -1326,7 +1415,6 @@ bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const {
tables_->known_bad_files_.insert(name);
return false;
}
-
return true;
}
@@ -1355,36 +1443,38 @@ bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const {
bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const {
if (fallback_database_ == NULL) return false;
- // 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.
- if (IsSubSymbolOfBuiltType(name)) return false;
+ if (tables_->known_bad_symbols_.count(name) > 0) 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 (BuildFileFromDatabase(file_proto) == NULL) {
+ 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;
}
@@ -1511,6 +1601,9 @@ void Descriptor::CopyTo(DescriptorProto* proto) const {
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());
}
@@ -1571,11 +1664,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());
@@ -1679,7 +1780,7 @@ bool RetrieveOptions(int depth,
bool FormatBracketedOptions(int depth, const Message &options, string *output) {
vector<string> all_options;
if (RetrieveOptions(depth, options, &all_options)) {
- output->append(JoinStrings(all_options, ", "));
+ output->append(Join(all_options, ", "));
}
return !all_options.empty();
}
@@ -1766,7 +1867,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");
@@ -1813,7 +1914,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++) {
@@ -1832,7 +1938,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);
@@ -1848,14 +1955,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()) {
@@ -1869,9 +1978,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(),
@@ -1902,6 +2017,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);
@@ -1984,29 +2116,21 @@ void MethodDescriptor::DebugString(int depth, string *contents) const {
// Location methods ===============================================
-static bool PathsEqual(const vector<int>& x, const RepeatedField<int32>& y) {
- if (x.size() != y.size()) return false;
- for (int i = 0; i < x.size(); ++i) {
- if (x[i] != y.Get(i)) return false;
- }
- return true;
-}
-
bool FileDescriptor::GetSourceLocation(const vector<int>& path,
SourceLocation* out_location) const {
GOOGLE_CHECK_NOTNULL(out_location);
- const SourceCodeInfo* info = source_code_info_;
- for (int i = 0; info && i < info->location_size(); ++i) {
- if (PathsEqual(path, info->location(i).path())) {
- const RepeatedField<int32>& span = info->location(i).span();
+ if (source_code_info_) {
+ if (const SourceCodeInfo_Location* loc =
+ tables_->GetSourceLocation(path, source_code_info_)) {
+ const RepeatedField<int32>& 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 = info->location(i).leading_comments();
- out_location->trailing_comments = info->location(i).trailing_comments();
+ out_location->leading_comments = loc->leading_comments();
+ out_location->trailing_comments = loc->trailing_comments();
return true;
}
}
@@ -2030,6 +2154,12 @@ bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
return file()->GetSourceLocation(path, out_location);
}
+bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+ vector<int> path;
+ GetLocationPath(&path);
+ return containing_type()->file()->GetSourceLocation(path, out_location);
+}
+
bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
vector<int> path;
GetLocationPath(&path);
@@ -2067,8 +2197,25 @@ void Descriptor::GetLocationPath(vector<int>* output) const {
}
void FieldDescriptor::GetLocationPath(vector<int>* 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<int>* output) const {
containing_type()->GetLocationPath(output);
- output->push_back(DescriptorProto::kFieldFieldNumber);
+ output->push_back(DescriptorProto::kOneofDeclFieldNumber);
output->push_back(index());
}
@@ -2154,6 +2301,10 @@ class DescriptorBuilder {
FileDescriptorTables* file_tables_;
set<const FileDescriptor*> dependencies_;
+ // unused_dependency_ is used to record the unused imported files.
+ // Note: public import is not considered.
+ set<const FileDescriptor*> 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
// possible_undeclared_dependency_ to point at that file. This is only used
@@ -2164,10 +2315,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.
@@ -2177,6 +2340,10 @@ 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.
@@ -2311,6 +2478,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);
@@ -2324,6 +2494,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
@@ -2459,6 +2631,9 @@ class DescriptorBuilder {
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_;
}
@@ -2501,6 +2676,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);
}
@@ -2512,6 +2689,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);
}
@@ -2519,8 +2698,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(
@@ -2531,7 +2718,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() {}
@@ -2553,21 +2741,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);
}
}
@@ -2628,7 +2848,10 @@ 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_ || dependencies_.count(file) > 0) return result;
+ if (file == file_ || dependencies_.count(file) > 0) {
+ unused_dependency_.erase(file);
+ return result;
+ }
if (result.type == Symbol::PACKAGE) {
// Arg, this is overcomplicated. The symbol is a package name. It could
@@ -2654,6 +2877,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.
@@ -2702,7 +2926,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.
}
@@ -2755,7 +2983,7 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name,
placeholder_name = tables_->AllocateString(
placeholder_full_name->substr(dotpos + 1));
} else {
- placeholder_package = &::google::protobuf::internal::GetEmptyString();
+ placeholder_package = &internal::GetEmptyString();
placeholder_name = placeholder_full_name;
}
@@ -2771,6 +2999,7 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name,
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) {
@@ -2841,10 +3070,11 @@ const FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
memset(placeholder, 0, sizeof(*placeholder));
placeholder->name_ = tables_->AllocateString(name);
- placeholder->package_ = &::google::protobuf::internal::GetEmptyString();
+ 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;
@@ -3015,6 +3245,45 @@ template<class DescriptorT> 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();
@@ -3027,9 +3296,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;
}
@@ -3048,15 +3315,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;
}
}
@@ -3083,6 +3342,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
FileDescriptor* result = tables_->Allocate<FileDescriptor>();
file_ = result;
+ result->is_placeholder_ = false;
if (proto.has_source_code_info()) {
SourceCodeInfo *info = tables_->AllocateMessage<SourceCodeInfo>();
info->CopyFrom(proto.source_code_info());
@@ -3129,11 +3389,14 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
result->dependency_count_ = proto.dependency_size();
result->dependencies_ =
tables_->AllocateArray<const FileDescriptor*>(proto.dependency_size());
+ unused_dependency_.clear();
+ set<int> 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));
@@ -3142,20 +3405,20 @@ 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);
}
}
@@ -3171,6 +3434,8 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
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,
@@ -3237,6 +3502,11 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
ValidateFileOptions(result, proto);
}
+
+ if (!unused_dependency_.empty()) {
+ LogUnusedDependency(result);
+ }
+
if (had_errors_) {
tables_->RollbackToLastCheckpoint();
return NULL;
@@ -3264,6 +3534,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);
@@ -3354,6 +3626,19 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
result->label_ = static_cast<FieldDescriptor::Label>(
implicit_cast<int>(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;
@@ -3397,7 +3682,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
result->default_value_float_ = numeric_limits<float>::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:
@@ -3409,7 +3694,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
result->default_value_double_ = numeric_limits<double>::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:
@@ -3451,7 +3736,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 {
@@ -3483,7 +3769,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
result->default_value_enum_ = NULL;
break;
case FieldDescriptor::CPPTYPE_STRING:
- result->default_value_string_ = &::google::protobuf::internal::GetEmptyString();
+ result->default_value_string_ = &internal::GetEmptyString();
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
break;
@@ -3524,6 +3810,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,
@@ -3532,6 +3828,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.
@@ -3569,6 +3882,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) {
@@ -3778,6 +4113,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<const FieldDescriptor*>(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(
@@ -3802,7 +4177,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 "
@@ -3812,6 +4190,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
@@ -3824,6 +4213,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,
@@ -3875,21 +4269,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
@@ -3933,12 +4340,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.
@@ -4022,7 +4443,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;
}
@@ -4050,6 +4470,7 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
}
}
+
void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
const DescriptorProto& proto) {
VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
@@ -4388,6 +4809,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.");
}
@@ -4408,14 +4838,15 @@ 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);
@@ -4432,7 +4863,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,
@@ -4947,5 +5378,39 @@ void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value,
}
}
+void DescriptorBuilder::LogUnusedDependency(const FileDescriptor* result) {
+
+ if (!unused_dependency_.empty()) {
+ std::set<string> 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 FileDescriptor*>::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 33e3af72..93fd4339 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -54,14 +54,11 @@
#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__
#define GOOGLE_PROTOBUF_DESCRIPTOR_H__
+#include <set>
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
-// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
-#ifdef TYPE_BOOL
-#undef TYPE_BOOL
-#endif // TYPE_BOOL
namespace google {
namespace protobuf {
@@ -69,6 +66,7 @@ namespace protobuf {
// Defined in this file.
class Descriptor;
class FieldDescriptor;
+class OneofDescriptor;
class EnumDescriptor;
class EnumValueDescriptor;
class ServiceDescriptor;
@@ -80,6 +78,7 @@ class DescriptorPool;
// Defined in descriptor.proto
class DescriptorProto;
class FieldDescriptorProto;
+class OneofDescriptorProto;
class EnumDescriptorProto;
class EnumValueDescriptorProto;
class ServiceDescriptorProto;
@@ -163,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.
@@ -190,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.
@@ -236,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;
@@ -286,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_;
@@ -303,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);
@@ -473,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
@@ -481,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.
@@ -510,6 +536,12 @@ 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);
@@ -524,7 +556,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
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
@@ -544,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_;
@@ -581,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(vector<int>* 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<OneofDescriptor>() and AllocateArray<OneofDescriptor>()
+ // 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.
@@ -630,6 +723,11 @@ 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
@@ -984,6 +1082,11 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
// 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 ---------------------------------------------------
@@ -1013,6 +1116,7 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
int service_count_;
ServiceDescriptor* services_;
int extension_count_;
+ bool is_placeholder_;
FieldDescriptor* extensions_;
const FileOptions* options_;
@@ -1026,6 +1130,7 @@ 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;
@@ -1083,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);
@@ -1113,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;
@@ -1157,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.
@@ -1166,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);
};
@@ -1186,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
@@ -1195,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
@@ -1254,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;
@@ -1298,6 +1431,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
bool enforce_dependencies_;
bool allow_unknown_;
+ bool enforce_weak_;
+ std::set<string> unused_import_track_files_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool);
};
@@ -1325,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*)
@@ -1338,7 +1475,8 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range,
const Descriptor::ExtensionRange*)
PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension,
const FieldDescriptor*)
-PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions)
+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)
@@ -1350,6 +1488,9 @@ 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*)
@@ -1368,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*)
@@ -1375,7 +1521,8 @@ PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, containing_type, const Descriptor*)
PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int)
PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value,
const EnumValueDescriptor*)
-PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions)
+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)
@@ -1389,14 +1536,14 @@ PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, file, const FileDescriptor*)
PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, method_count, int)
PROTOBUF_DEFINE_ARRAY_ACCESSOR(ServiceDescriptor, method,
const MethodDescriptor*)
-PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions)
+PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions);
PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, name)
PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, full_name)
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_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions);
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name)
PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package)
PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*)
@@ -1407,7 +1554,8 @@ 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_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*)
@@ -1422,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;
}
@@ -1458,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_;
@@ -1494,6 +1650,14 @@ 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 &&
@@ -1515,6 +1679,12 @@ inline const FileDescriptor* FileDescriptor::weak_dependency(
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 cfd4817d..c3aa2fb6 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -38,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;
@@ -136,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_ =
@@ -173,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_),
@@ -181,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_ =
@@ -196,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_),
@@ -213,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_),
@@ -230,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_),
@@ -247,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_),
@@ -265,17 +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_[10] = {
+ 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_ =
@@ -290,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_ =
@@ -307,7 +330,7 @@ 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);
+ 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_),
@@ -329,9 +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_[2] = {
+ 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_ =
@@ -345,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_ =
@@ -360,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_ =
@@ -375,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_ =
@@ -390,7 +417,7 @@ 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);
+ 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_),
@@ -427,7 +454,7 @@ 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(16);
+ SourceCodeInfo_descriptor_ = file->message_type(17);
static const int SourceCodeInfo_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_),
};
@@ -483,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());
@@ -527,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_;
@@ -580,7 +611,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"\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\"\251\003\n\017Descripto"
+ "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"
@@ -588,16 +619,18 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"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\0220"
- "\n\007options\030\007 \001(\0132\037.google.protobuf.Messag"
- "eOptions\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001("
- "\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescriptorProto\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.FieldDescriptorPr"
- "oto.Label\0228\n\004type\030\005 \001(\0162*.google.protobu"
- "f.FieldDescriptorProto.Type\022\021\n\ttype_name"
- "\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_valu"
- "e\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.google.protob"
+ "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"
@@ -607,69 +640,75 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"\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\"\214\001"
- "\n\023EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005v"
- "alue\030\002 \003(\0132).google.protobuf.EnumValueDe"
- "scriptorProto\022-\n\007options\030\003 \001(\0132\034.google."
- "protobuf.EnumOptions\"l\n\030EnumValueDescrip"
- "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222"
- "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa"
- "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n"
- "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro"
- "tobuf.MethodDescriptorProto\0220\n\007options\030\003"
- " \001(\0132\037.google.protobuf.ServiceOptions\"\177\n"
- "\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\n"
- "input_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n"
- "\007options\030\004 \001(\0132\036.google.protobuf.MethodO"
- "ptions\"\351\003\n\013FileOptions\022\024\n\014java_package\030\001"
- " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja"
- "va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g"
- "enerate_equals_and_hash\030\024 \001(\010:\005false\022F\n\014"
- "optimize_for\030\t \001(\0162).google.protobuf.Fil"
- "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa"
- "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f"
- "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal"
- "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022C"
- "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p"
- "rotobuf.UninterpretedOption\":\n\014OptimizeM"
- "ode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RU"
- "NTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n"
- "\027message_set_wire_format\030\001 \001(\010:\005false\022.\n"
- "\037no_standard_descriptor_accessor\030\002 \001(\010:\005"
- "false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g"
- "oogle.protobuf.UninterpretedOption*\t\010\350\007\020"
- "\200\200\200\200\002\"\276\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#."
- "google.protobuf.FieldOptions.CType:\006STRI"
- "NG\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\024experiment"
- "al_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.pr"
- "otobuf.UninterpretedOption\"/\n\005CType\022\n\n\006S"
- "TRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007"
- "\020\200\200\200\200\002\"x\n\013EnumOptions\022\031\n\013allow_alias\030\002 \001"
- "(\010:\004true\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
+ "\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\"b\n\020EnumValueOptions\022C\n\024uninterp"
- "reted_option\030\347\007 \003(\0132$.google.protobuf.Un"
- "interpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceO"
- "ptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
- "google.protobuf.UninterpretedOption*\t\010\350\007"
- "\020\200\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted"
- "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
- "pretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterprete"
- "dOption\022;\n\004name\030\002 \003(\0132-.google.protobuf."
- "UninterpretedOption.NamePart\022\030\n\020identifi"
- "er_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001"
- "(\004\022\032\n\022negative_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\017ag"
- "gregate_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\016Sou"
- "rceCodeInfo\022:\n\010location\030\001 \003(\0132(.google.p"
- "rotobuf.SourceCodeInfo.Location\032c\n\010Locat"
- "ion\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\020leading_comments\030\003 \001(\t\022\031\n\021trailing_co"
- "mments\030\004 \001(\tB)\n\023com.google.protobufB\020Des"
- "criptorProtosH\001", 4135);
+ "\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();
@@ -677,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();
@@ -697,6 +737,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
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();
@@ -731,6 +772,7 @@ const int FileDescriptorSet::kFileFieldNumber;
FileDescriptorSet::FileDescriptorSet()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet)
}
void FileDescriptorSet::InitAsDefaultInstance() {
@@ -740,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() {
@@ -748,6 +791,7 @@ void FileDescriptorSet::SharedCtor() {
}
FileDescriptorSet::~FileDescriptorSet() {
+ // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet)
SharedDtor();
}
@@ -785,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()));
@@ -816,12 +864,18 @@ 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(
@@ -832,10 +886,12 @@ void FileDescriptorSet::SerializeWithCachedSizes(
::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::
@@ -847,6 +903,7 @@ void FileDescriptorSet::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet)
return target;
}
@@ -904,9 +961,7 @@ 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;
}
@@ -947,6 +1002,7 @@ const int FileDescriptorProto::kSourceCodeInfoFieldNumber;
FileDescriptorProto::FileDescriptorProto()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto)
}
void FileDescriptorProto::InitAsDefaultInstance() {
@@ -958,26 +1014,29 @@ 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*>(&::google::protobuf::internal::GetEmptyString());
- package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
- if (package_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete package_;
}
if (this != default_instance_) {
@@ -1008,19 +1067,19 @@ FileDescriptorProto* FileDescriptorProto::New() const {
}
void FileDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 3) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
if (has_package()) {
- if (package_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
package_->clear();
}
}
}
- if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) {
+ if (_has_bits_[8 / 32] & 1536) {
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
}
@@ -1041,21 +1100,25 @@ 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;
@@ -1063,16 +1126,16 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -1080,17 +1143,17 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// 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(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->dependency(this->dependency_size() - 1).data(),
this->dependency(this->dependency_size() - 1).length(),
- ::google::protobuf::internal::WireFormat::PARSE);
+ ::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;
@@ -1099,13 +1162,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -1114,13 +1176,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -1129,13 +1190,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -1144,13 +1204,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -1159,13 +1218,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -1173,13 +1231,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
case 9: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ if (tag == 74) {
parse_source_code_info:
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
input, mutable_source_code_info()));
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(80)) goto parse_public_dependency;
break;
@@ -1187,20 +1244,17 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated int32 public_dependency = 10;
case 10: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ 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 (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_LENGTH_DELIMITED) {
+ } 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_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(80)) goto parse_public_dependency;
if (input->ExpectTag(88)) goto parse_weak_dependency;
@@ -1209,31 +1263,29 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
// repeated int32 weak_dependency = 11;
case 11: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ 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 (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_LENGTH_DELIMITED) {
+ } 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_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(88)) goto parse_weak_dependency;
- 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()));
@@ -1241,35 +1293,44 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_package()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -1326,15 +1387,18 @@ void FileDescriptorProto::SerializeWithCachedSizes(
::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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -1342,9 +1406,10 @@ void FileDescriptorProto::SerializeWithCachedSizes(
// optional string package = 2;
if (has_package()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -1352,9 +1417,10 @@ void FileDescriptorProto::SerializeWithCachedSizes(
// 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);
}
@@ -1417,6 +1483,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto)
return target;
}
@@ -1579,18 +1646,10 @@ 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;
}
@@ -1635,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() {
@@ -1644,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() {
@@ -1654,6 +1715,7 @@ void DescriptorProto_ExtensionRange::SharedCtor() {
}
DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() {
+ // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange)
SharedDtor();
}
@@ -1684,30 +1746,44 @@ 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<char*>( \
+ &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f) - \
+ reinterpret_cast<char*>(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_has_start();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(16)) goto parse_end;
break;
@@ -1715,25 +1791,25 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
// 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_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()));
@@ -1741,12 +1817,18 @@ 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_start()) {
::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
@@ -1761,10 +1843,12 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
::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_start()) {
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
@@ -1779,6 +1863,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange)
return target;
}
@@ -1882,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() {
@@ -1898,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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (this != default_instance_) {
@@ -1942,9 +2032,9 @@ DescriptorProto* DescriptorProto::New() const {
}
void DescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 129) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
@@ -1957,27 +2047,32 @@ 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;
@@ -1985,13 +2080,12 @@ bool DescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2000,13 +2094,12 @@ bool DescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2015,13 +2108,12 @@ bool DescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2030,13 +2122,12 @@ bool DescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2045,13 +2136,12 @@ bool DescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2060,23 +2150,37 @@ bool DescriptorProto::MergePartialFromCodedStream(
// 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()));
@@ -2084,18 +2188,25 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -2135,19 +2246,28 @@ void DescriptorProto::SerializeWithCachedSizes(
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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -2195,10 +2315,18 @@ void DescriptorProto::SerializeWithCachedSizes(
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;
}
@@ -2261,6 +2389,14 @@ int DescriptorProto::ByteSize() const {
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(
@@ -2291,6 +2427,7 @@ 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_name()) {
set_name(from.name());
@@ -2316,18 +2453,10 @@ 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;
}
@@ -2342,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_);
@@ -2444,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() {
@@ -2460,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*>(&::google::protobuf::internal::GetEmptyString());
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
number_ = 0;
label_ = 1;
type_ = 1;
- type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
- extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
- default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
- if (type_name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete type_name_;
}
- if (extendee_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete extendee_;
}
- if (default_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete default_value_;
}
if (this != default_instance_) {
@@ -2519,9 +2655,9 @@ FieldDescriptorProto* FieldDescriptorProto::New() const {
}
void FieldDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 255) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
@@ -2529,23 +2665,24 @@ void FieldDescriptorProto::Clear() {
label_ = 1;
type_ = 1;
if (has_type_name()) {
- if (type_name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
type_name_->clear();
}
}
if (has_extendee()) {
- if (extendee_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
extendee_->clear();
}
}
if (has_default_value()) {
- if (default_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
default_value_->clear();
}
}
- if (has_options()) {
- 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();
@@ -2553,21 +2690,25 @@ 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;
@@ -2575,16 +2716,16 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2592,15 +2733,14 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// 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_has_number();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(32)) goto parse_label;
break;
@@ -2608,8 +2748,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// 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<
@@ -2621,7 +2760,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
mutable_unknown_fields()->AddVarint(4, value);
}
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(40)) goto parse_type;
break;
@@ -2629,8 +2768,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// 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<
@@ -2642,7 +2780,7 @@ 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;
@@ -2650,16 +2788,16 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2667,16 +2805,16 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -2684,23 +2822,38 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
// 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()));
@@ -2708,27 +2861,35 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_extendee()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -2751,19 +2912,21 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
// optional string type_name = 6;
if (has_type_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_default_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -2773,19 +2936,27 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -2793,9 +2964,10 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
// optional string extendee = 2;
if (has_extendee()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -2820,9 +2992,10 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
// optional string type_name = 6;
if (has_type_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -2830,9 +3003,10 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
// optional string default_value = 7;
if (has_default_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -2845,10 +3019,16 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
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;
}
@@ -2903,6 +3083,15 @@ int FieldDescriptorProto::ByteSize() const {
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 +
@@ -2958,6 +3147,11 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
if (from.has_default_value()) {
set_default_value(from.default_value());
}
+ 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());
}
@@ -2994,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_);
@@ -3013,6 +3208,249 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) {
// ===================================================================
#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<const OneofDescriptorProto*>(
+ &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;
const int EnumDescriptorProto::kOptionsFieldNumber;
@@ -3021,6 +3459,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber;
EnumDescriptorProto::EnumDescriptorProto()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto)
}
void EnumDescriptorProto::InitAsDefaultInstance() {
@@ -3031,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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (this != default_instance_) {
@@ -3075,9 +3517,9 @@ EnumDescriptorProto* EnumDescriptorProto::New() const {
}
void EnumDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 5) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
@@ -3092,21 +3534,25 @@ 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;
@@ -3114,13 +3560,12 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -3129,23 +3574,23 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
// 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()));
@@ -3153,18 +3598,25 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -3184,15 +3636,18 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
::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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -3216,6 +3671,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto)
return target;
}
@@ -3297,9 +3753,7 @@ 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;
}
@@ -3337,6 +3791,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber;
EnumValueDescriptorProto::EnumValueDescriptorProto()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto)
}
void EnumValueDescriptorProto::InitAsDefaultInstance() {
@@ -3347,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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (this != default_instance_) {
@@ -3392,9 +3850,9 @@ EnumValueDescriptorProto* EnumValueDescriptorProto::New() const {
}
void EnumValueDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 7) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
@@ -3409,21 +3867,25 @@ 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;
@@ -3431,15 +3893,14 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
// 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_has_number();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(26)) goto parse_options;
break;
@@ -3447,23 +3908,23 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
// 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()));
@@ -3471,18 +3932,25 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -3501,15 +3969,18 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
::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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -3531,6 +4002,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto)
return target;
}
@@ -3650,6 +4122,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber;
ServiceDescriptorProto::ServiceDescriptorProto()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto)
}
void ServiceDescriptorProto::InitAsDefaultInstance() {
@@ -3660,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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (this != default_instance_) {
@@ -3704,9 +4180,9 @@ ServiceDescriptorProto* ServiceDescriptorProto::New() const {
}
void ServiceDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 5) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
@@ -3721,21 +4197,25 @@ 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;
@@ -3743,13 +4223,12 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -3758,23 +4237,23 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
// 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()));
@@ -3782,18 +4261,25 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -3813,15 +4299,18 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
::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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -3845,6 +4334,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto)
return target;
}
@@ -3926,9 +4416,7 @@ 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;
}
@@ -3967,6 +4455,7 @@ const int MethodDescriptorProto::kOptionsFieldNumber;
MethodDescriptorProto::MethodDescriptorProto()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto)
}
void MethodDescriptorProto::InitAsDefaultInstance() {
@@ -3977,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*>(&::google::protobuf::internal::GetEmptyString());
- input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
- output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
- if (input_type_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete input_type_;
}
- if (output_type_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete output_type_;
}
if (this != default_instance_) {
@@ -4029,19 +4521,19 @@ MethodDescriptorProto* MethodDescriptorProto::New() const {
}
void MethodDescriptorProto::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 15) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
}
if (has_input_type()) {
- if (input_type_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
input_type_->clear();
}
}
if (has_output_type()) {
- if (output_type_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
output_type_->clear();
}
}
@@ -4055,21 +4547,25 @@ 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;
@@ -4077,16 +4573,16 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -4094,16 +4590,16 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
// 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;
@@ -4111,23 +4607,23 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
// 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()));
@@ -4135,36 +4631,45 @@ 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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_input_type()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_output_type()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -4178,15 +4683,18 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
::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_name()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -4194,9 +4702,10 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
// optional string input_type = 2;
if (has_input_type()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -4204,9 +4713,10 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
// optional string output_type = 3;
if (has_output_type()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -4223,6 +4733,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto)
return target;
}
@@ -4372,17 +4883,20 @@ 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() {
@@ -4392,34 +4906,39 @@ 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*>(&::google::protobuf::internal::GetEmptyString());
- java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
- go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete java_package_;
}
- if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete java_outer_classname_;
}
- if (go_package_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete go_package_;
}
if (this != default_instance_) {
@@ -4449,31 +4968,40 @@ FileOptions* FileOptions::New() const {
void FileOptions::Clear() {
_extensions_.Clear();
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
+ &reinterpret_cast<FileOptions*>(16)->f) - \
+ reinterpret_cast<char*>(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::GetEmptyString()) {
+ if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
java_package_->clear();
}
}
if (has_java_outer_classname()) {
- if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
java_outer_classname_->clear();
}
}
- java_multiple_files_ = false;
- java_generate_equals_and_hash_ = false;
optimize_for_ = 1;
if (has_go_package()) {
- if (go_package_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
go_package_->clear();
}
}
- cc_generic_services_ = false;
- java_generic_services_ = false;
- }
- if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
- py_generic_services_ = false;
}
+ 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();
@@ -4481,21 +5009,25 @@ 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;
@@ -4503,16 +5035,16 @@ bool FileOptions::MergePartialFromCodedStream(
// 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;
@@ -4520,8 +5052,7 @@ bool FileOptions::MergePartialFromCodedStream(
// 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<
@@ -4533,7 +5064,7 @@ 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;
@@ -4541,15 +5072,14 @@ bool FileOptions::MergePartialFromCodedStream(
// 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_has_java_multiple_files();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(90)) goto parse_go_package;
break;
@@ -4557,16 +5087,16 @@ bool FileOptions::MergePartialFromCodedStream(
// optional string go_package = 11;
case 11: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ if (tag == 90) {
parse_go_package:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_go_package()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->go_package().data(), this->go_package().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "go_package");
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(128)) goto parse_cc_generic_services;
break;
@@ -4574,15 +5104,14 @@ bool FileOptions::MergePartialFromCodedStream(
// 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_has_cc_generic_services();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(136)) goto parse_java_generic_services;
break;
@@ -4590,15 +5119,14 @@ bool FileOptions::MergePartialFromCodedStream(
// 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_has_java_generic_services();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(144)) goto parse_py_generic_services;
break;
@@ -4606,15 +5134,14 @@ bool FileOptions::MergePartialFromCodedStream(
// 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_has_py_generic_services();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash;
break;
@@ -4622,15 +5149,44 @@ bool FileOptions::MergePartialFromCodedStream(
// optional bool java_generate_equals_and_hash = 20 [default = false];
case 20: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ 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_uninterpreted;
+ 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_unusual;
}
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
@@ -4638,24 +5194,24 @@ bool FileOptions::MergePartialFromCodedStream(
// 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_,
@@ -4668,27 +5224,35 @@ 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_java_package()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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_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::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);
}
@@ -4705,10 +5269,11 @@ void FileOptions::SerializeWithCachedSizes(
// optional string go_package = 11;
if (has_go_package()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->go_package().data(), this->go_package().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
- ::google::protobuf::internal::WireFormatLite::WriteString(
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "go_package");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
11, this->go_package(), output);
}
@@ -4732,6 +5297,16 @@ void FileOptions::SerializeWithCachedSizes(
::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(
@@ -4746,15 +5321,18 @@ void FileOptions::SerializeWithCachedSizes(
::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_java_package()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -4762,9 +5340,10 @@ void FileOptions::SerializeWithCachedSizes(
// optional string java_outer_classname = 8;
if (has_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::SERIALIZE);
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "java_outer_classname");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
8, this->java_outer_classname(), target);
@@ -4783,9 +5362,10 @@ void FileOptions::SerializeWithCachedSizes(
// optional string go_package = 11;
if (has_go_package()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->go_package().data(), this->go_package().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "go_package");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
11, this->go_package(), target);
@@ -4811,6 +5391,16 @@ void FileOptions::SerializeWithCachedSizes(
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::
@@ -4826,6 +5416,7 @@ void FileOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions)
return target;
}
@@ -4857,6 +5448,11 @@ int FileOptions::ByteSize() const {
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 +
@@ -4875,18 +5471,23 @@ int FileOptions::ByteSize() const {
total_size += 2 + 1;
}
+ }
+ 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;
}
- }
- if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
// 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();
@@ -4937,6 +5538,9 @@ void FileOptions::MergeFrom(const FileOptions& from) {
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());
}
@@ -4946,14 +5550,17 @@ void FileOptions::MergeFrom(const FileOptions& from) {
if (from.has_cc_generic_services()) {
set_cc_generic_services(from.cc_generic_services());
}
+ }
+ 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_bits_[8 / 32] & (0xffu << (8 % 32))) {
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());
@@ -4973,9 +5580,7 @@ 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;
}
@@ -4986,11 +5591,13 @@ void FileOptions::Swap(FileOptions* other) {
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_);
@@ -5013,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() {
@@ -5028,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();
}
@@ -5069,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<char*>( \
+ &reinterpret_cast<MessageOptions*>(16)->f) - \
+ reinterpret_cast<char*>(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();
@@ -5080,20 +5703,23 @@ 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_has_message_set_wire_format();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor;
break;
@@ -5101,15 +5727,29 @@ bool MessageOptions::MergePartialFromCodedStream(
// 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_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;
@@ -5117,24 +5757,24 @@ bool MessageOptions::MergePartialFromCodedStream(
// 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_,
@@ -5147,12 +5787,18 @@ 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_message_set_wire_format()) {
::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output);
@@ -5163,6 +5809,11 @@ void MessageOptions::SerializeWithCachedSizes(
::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(
@@ -5177,10 +5828,12 @@ void MessageOptions::SerializeWithCachedSizes(
::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_message_set_wire_format()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target);
@@ -5191,6 +5844,11 @@ void MessageOptions::SerializeWithCachedSizes(
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::
@@ -5206,6 +5864,7 @@ void MessageOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions)
return target;
}
@@ -5223,6 +5882,11 @@ int MessageOptions::ByteSize() const {
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();
@@ -5267,6 +5931,9 @@ void MessageOptions::MergeFrom(const MessageOptions& from) {
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());
@@ -5286,9 +5953,7 @@ 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;
}
@@ -5297,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_);
@@ -5352,6 +6018,7 @@ const int FieldOptions::kUninterpretedOptionFieldNumber;
FieldOptions::FieldOptions()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.FieldOptions)
}
void FieldOptions::InitAsDefaultInstance() {
@@ -5361,25 +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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete experimental_map_key_;
}
if (this != default_instance_) {
@@ -5409,18 +6079,28 @@ FieldOptions* FieldOptions::New() const {
void FieldOptions::Clear() {
_extensions_.Clear();
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- ctype_ = 0;
- packed_ = false;
- lazy_ = false;
- deprecated_ = false;
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
+ &reinterpret_cast<FieldOptions*>(16)->f) - \
+ reinterpret_cast<char*>(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::GetEmptyString()) {
+ if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
experimental_map_key_->clear();
}
}
- weak_ = false;
}
+
+#undef OFFSET_OF_FIELD_
+#undef ZR_
+
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
mutable_unknown_fields()->Clear();
@@ -5428,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>(
@@ -5446,7 +6129,7 @@ bool FieldOptions::MergePartialFromCodedStream(
mutable_unknown_fields()->AddVarint(1, value);
}
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(16)) goto parse_packed;
break;
@@ -5454,15 +6137,14 @@ bool FieldOptions::MergePartialFromCodedStream(
// 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_has_packed();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(24)) goto parse_deprecated;
break;
@@ -5470,15 +6152,14 @@ bool FieldOptions::MergePartialFromCodedStream(
// 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_has_deprecated();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(40)) goto parse_lazy;
break;
@@ -5486,15 +6167,14 @@ bool FieldOptions::MergePartialFromCodedStream(
// optional bool lazy = 5 [default = false];
case 5: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ 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;
@@ -5502,16 +6182,16 @@ bool FieldOptions::MergePartialFromCodedStream(
// 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_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(80)) goto parse_weak;
break;
@@ -5519,15 +6199,14 @@ bool FieldOptions::MergePartialFromCodedStream(
// optional bool weak = 10 [default = false];
case 10: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ 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;
@@ -5535,24 +6214,24 @@ bool FieldOptions::MergePartialFromCodedStream(
// 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_,
@@ -5565,12 +6244,18 @@ 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_ctype()) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
@@ -5594,10 +6279,11 @@ void FieldOptions::SerializeWithCachedSizes(
// optional string experimental_map_key = 9;
if (has_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::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);
}
@@ -5620,10 +6306,12 @@ void FieldOptions::SerializeWithCachedSizes(
::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_ctype()) {
target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
@@ -5647,9 +6335,10 @@ void FieldOptions::SerializeWithCachedSizes(
// optional string experimental_map_key = 9;
if (has_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::SERIALIZE);
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "experimental_map_key");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
9, this->experimental_map_key(), target);
@@ -5675,6 +6364,7 @@ void FieldOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions)
return target;
}
@@ -5790,9 +6480,7 @@ 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;
}
@@ -5826,12 +6514,14 @@ 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() {
@@ -5841,15 +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_ = true;
+ allow_alias_ = false;
+ deprecated_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
EnumOptions::~EnumOptions() {
+ // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions)
SharedDtor();
}
@@ -5881,9 +6574,21 @@ EnumOptions* EnumOptions::New() const {
void EnumOptions::Clear() {
_extensions_.Clear();
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- allow_alias_ = true;
- }
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
+ &reinterpret_cast<EnumOptions*>(16)->f) - \
+ reinterpret_cast<char*>(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();
@@ -5891,20 +6596,38 @@ void EnumOptions::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 [default = true];
+ // optional bool allow_alias = 2;
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+ 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_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;
@@ -5912,24 +6635,24 @@ bool EnumOptions::MergePartialFromCodedStream(
// 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_,
@@ -5942,17 +6665,28 @@ 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 {
- // optional bool allow_alias = 2 [default = true];
+ // @@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(
@@ -5967,15 +6701,22 @@ void EnumOptions::SerializeWithCachedSizes(
::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 {
- // optional bool allow_alias = 2 [default = true];
+ // @@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::
@@ -5991,6 +6732,7 @@ void EnumOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions)
return target;
}
@@ -5998,11 +6740,16 @@ int EnumOptions::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // optional bool allow_alias = 2 [default = true];
+ // 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();
@@ -6044,6 +6791,9 @@ void EnumOptions::MergeFrom(const EnumOptions& from) {
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());
@@ -6063,9 +6813,7 @@ 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;
}
@@ -6073,6 +6821,7 @@ bool EnumOptions::IsInitialized() const {
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_);
@@ -6093,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() {
@@ -6108,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();
}
@@ -6147,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();
@@ -6154,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_,
@@ -6190,12 +6963,23 @@ 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(
@@ -6210,10 +6994,17 @@ void EnumValueOptions::SerializeWithCachedSizes(
::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::
@@ -6229,12 +7020,20 @@ void EnumValueOptions::SerializeWithCachedSizes(
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++) {
@@ -6271,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());
}
@@ -6289,15 +7093,14 @@ 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_);
@@ -6318,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() {
@@ -6333,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();
}
@@ -6372,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();
@@ -6379,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_,
@@ -6415,12 +7242,23 @@ 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(
@@ -6435,10 +7273,17 @@ void ServiceOptions::SerializeWithCachedSizes(
::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::
@@ -6454,12 +7299,20 @@ void ServiceOptions::SerializeWithCachedSizes(
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++) {
@@ -6496,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());
}
@@ -6514,15 +7372,14 @@ 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_);
@@ -6543,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() {
@@ -6558,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();
}
@@ -6597,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();
@@ -6604,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_,
@@ -6640,12 +7521,23 @@ 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(
@@ -6660,10 +7552,17 @@ void MethodOptions::SerializeWithCachedSizes(
::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::
@@ -6679,12 +7578,20 @@ void MethodOptions::SerializeWithCachedSizes(
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++) {
@@ -6721,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());
}
@@ -6739,15 +7651,14 @@ 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_);
@@ -6775,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() {
@@ -6784,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*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_part_;
}
if (this != default_instance_) {
@@ -6827,9 +7742,9 @@ UninterpretedOption_NamePart* UninterpretedOption_NamePart::New() const {
}
void UninterpretedOption_NamePart::Clear() {
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 3) {
if (has_name_part()) {
- if (name_part_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_part_->clear();
}
}
@@ -6841,21 +7756,25 @@ 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;
@@ -6863,25 +7782,25 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
// 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_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()));
@@ -6889,18 +7808,25 @@ 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_name_part()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -6913,15 +7839,18 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
::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_name_part()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -6936,6 +7865,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart)
return target;
}
@@ -7044,6 +7974,7 @@ const int UninterpretedOption::kAggregateValueFieldNumber;
UninterpretedOption::UninterpretedOption()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption)
}
void UninterpretedOption::InitAsDefaultInstance() {
@@ -7053,31 +7984,34 @@ 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*>(&::google::protobuf::internal::GetEmptyString());
+ 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*>(&::google::protobuf::internal::GetEmptyString());
- aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete identifier_value_;
}
- if (string_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete string_value_;
}
- if (aggregate_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete aggregate_value_;
}
if (this != default_instance_) {
@@ -7106,26 +8040,38 @@ UninterpretedOption* UninterpretedOption::New() const {
}
void UninterpretedOption::Clear() {
- if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
+ &reinterpret_cast<UninterpretedOption*>(16)->f) - \
+ reinterpret_cast<char*>(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::GetEmptyString()) {
+ 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_string_value()) {
- if (string_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
string_value_->clear();
}
}
if (has_aggregate_value()) {
- if (aggregate_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ 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();
@@ -7133,19 +8079,22 @@ 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;
@@ -7154,16 +8103,16 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// 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;
@@ -7171,15 +8120,14 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// 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_has_positive_int_value();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(40)) goto parse_negative_int_value;
break;
@@ -7187,15 +8135,14 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// 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_has_negative_int_value();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(49)) goto parse_double_value;
break;
@@ -7203,15 +8150,14 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// 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_has_double_value();
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(58)) goto parse_string_value;
break;
@@ -7219,13 +8165,12 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// 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;
@@ -7233,26 +8178,27 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// optional string aggregate_value = 8;
case 8: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ if (tag == 66) {
parse_aggregate_value:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_aggregate_value()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->aggregate_value().data(), this->aggregate_value().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "aggregate_value");
} 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()));
@@ -7260,12 +8206,18 @@ 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(
@@ -7274,10 +8226,11 @@ void UninterpretedOption::SerializeWithCachedSizes(
// optional string identifier_value = 3;
if (has_identifier_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
}
@@ -7298,16 +8251,17 @@ void UninterpretedOption::SerializeWithCachedSizes(
// optional bytes string_value = 7;
if (has_string_value()) {
- ::google::protobuf::internal::WireFormatLite::WriteBytes(
+ ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased(
7, this->string_value(), output);
}
// optional string aggregate_value = 8;
if (has_aggregate_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->aggregate_value().data(), this->aggregate_value().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
- ::google::protobuf::internal::WireFormatLite::WriteString(
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "aggregate_value");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
8, this->aggregate_value(), output);
}
@@ -7315,10 +8269,12 @@ void UninterpretedOption::SerializeWithCachedSizes(
::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::
@@ -7328,9 +8284,10 @@ void UninterpretedOption::SerializeWithCachedSizes(
// optional string identifier_value = 3;
if (has_identifier_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::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);
@@ -7360,9 +8317,10 @@ void UninterpretedOption::SerializeWithCachedSizes(
// optional string aggregate_value = 8;
if (has_aggregate_value()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->aggregate_value().data(), this->aggregate_value().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "aggregate_value");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
8, this->aggregate_value(), target);
@@ -7372,6 +8330,7 @@ void UninterpretedOption::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption)
return target;
}
@@ -7491,9 +8450,7 @@ 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;
}
@@ -7533,6 +8490,7 @@ const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
SourceCodeInfo_Location::SourceCodeInfo_Location()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location)
}
void SourceCodeInfo_Location::InitAsDefaultInstance() {
@@ -7542,24 +8500,27 @@ SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location&
: ::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::GetEmptyString());
- trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete leading_comments_;
}
- if (trailing_comments_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete trailing_comments_;
}
if (this != default_instance_) {
@@ -7588,14 +8549,14 @@ SourceCodeInfo_Location* SourceCodeInfo_Location::New() const {
}
void SourceCodeInfo_Location::Clear() {
- if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+ if (_has_bits_[0 / 32] & 12) {
if (has_leading_comments()) {
- if (leading_comments_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
leading_comments_->clear();
}
}
if (has_trailing_comments()) {
- if (trailing_comments_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
trailing_comments_->clear();
}
}
@@ -7608,25 +8569,26 @@ void SourceCodeInfo_Location::Clear() {
bool SourceCodeInfo_Location::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.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 (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ if (tag == 10) {
DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
input, this->mutable_path())));
- } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_VARINT) {
+ } 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_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(18)) goto parse_span;
break;
@@ -7634,20 +8596,17 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
// repeated int32 span = 2 [packed = true];
case 2: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ 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 (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)
- == ::google::protobuf::internal::WireFormatLite::
- WIRETYPE_VARINT) {
+ } 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_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(26)) goto parse_leading_comments;
break;
@@ -7655,16 +8614,16 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
// optional string leading_comments = 3;
case 3: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ if (tag == 26) {
parse_leading_comments:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_leading_comments()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->leading_comments().data(), this->leading_comments().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "leading_comments");
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(34)) goto parse_trailing_comments;
break;
@@ -7672,26 +8631,27 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
// optional string trailing_comments = 4;
case 4: {
- if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ if (tag == 34) {
parse_trailing_comments:
DO_(::google::protobuf::internal::WireFormatLite::ReadString(
input, this->mutable_trailing_comments()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->trailing_comments().data(), this->trailing_comments().length(),
- ::google::protobuf::internal::WireFormat::PARSE);
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "trailing_comments");
} 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()));
@@ -7699,12 +8659,18 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
}
}
}
+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);
@@ -7727,19 +8693,21 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
// optional string leading_comments = 3;
if (has_leading_comments()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->leading_comments().data(), this->leading_comments().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
- ::google::protobuf::internal::WireFormatLite::WriteString(
+ ::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::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->trailing_comments().data(), this->trailing_comments().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
- ::google::protobuf::internal::WireFormatLite::WriteString(
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "trailing_comments");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
4, this->trailing_comments(), output);
}
@@ -7747,10 +8715,12 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
::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(
@@ -7781,9 +8751,10 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
// optional string leading_comments = 3;
if (has_leading_comments()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->leading_comments().data(), this->leading_comments().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "leading_comments");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
3, this->leading_comments(), target);
@@ -7791,9 +8762,10 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
// optional string trailing_comments = 4;
if (has_trailing_comments()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->trailing_comments().data(), this->trailing_comments().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE);
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "trailing_comments");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
4, this->trailing_comments(), target);
@@ -7803,6 +8775,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location)
return target;
}
@@ -7944,6 +8917,7 @@ const int SourceCodeInfo::kLocationFieldNumber;
SourceCodeInfo::SourceCodeInfo()
: ::google::protobuf::Message() {
SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo)
}
void SourceCodeInfo::InitAsDefaultInstance() {
@@ -7953,6 +8927,7 @@ SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
: ::google::protobuf::Message() {
SharedCtor();
MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo)
}
void SourceCodeInfo::SharedCtor() {
@@ -7961,6 +8936,7 @@ void SourceCodeInfo::SharedCtor() {
}
SourceCodeInfo::~SourceCodeInfo() {
+ // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo)
SharedDtor();
}
@@ -7998,30 +8974,34 @@ void SourceCodeInfo::Clear() {
bool SourceCodeInfo::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.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 (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
- ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+ if (tag == 10) {
parse_location:
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
input, add_location()));
} else {
- goto handle_uninterpreted;
+ goto handle_unusual;
}
if (input->ExpectTag(10)) goto parse_location;
- 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()));
@@ -8029,12 +9009,18 @@ bool SourceCodeInfo::MergePartialFromCodedStream(
}
}
}
+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(
@@ -8045,10 +9031,12 @@ void SourceCodeInfo::SerializeWithCachedSizes(
::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::
@@ -8060,6 +9048,7 @@ void SourceCodeInfo::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo)
return target;
}
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index cfed2883..36d4d1b7 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -40,6 +40,7 @@ class FileDescriptorProto;
class DescriptorProto;
class DescriptorProto_ExtensionRange;
class FieldDescriptorProto;
+class OneofDescriptorProto;
class EnumDescriptorProto;
class EnumValueDescriptorProto;
class ServiceDescriptorProto;
@@ -200,7 +201,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -224,11 +224,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
::google::protobuf::UnknownFieldSet _unknown_fields_;
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
-
+ ::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+ ::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();
@@ -285,7 +283,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -435,6 +432,8 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* name_;
::std::string* package_;
::google::protobuf::RepeatedPtrField< ::std::string> dependency_;
@@ -446,10 +445,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
::google::protobuf::FileOptions* options_;
::google::protobuf::SourceCodeInfo* source_code_info_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32];
-
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();
@@ -506,7 +501,6 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -536,12 +530,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::google::protobuf::int32 start_;
::google::protobuf::int32 end_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
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();
@@ -598,7 +590,6 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -679,6 +670,18 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
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();
@@ -697,17 +700,16 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* 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_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-
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();
@@ -764,7 +766,6 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -905,6 +906,13 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
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();
@@ -930,29 +938,114 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
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_;
::google::protobuf::int32 number_;
int label_;
::std::string* type_name_;
::std::string* extendee_;
+ int type_;
+ ::google::protobuf::int32 oneof_index_;
::std::string* default_value_;
::google::protobuf::FieldOptions* options_;
- int type_;
+ 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();
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32];
+ 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 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 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_;
};
// -------------------------------------------------------------------
@@ -1003,7 +1096,6 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1052,13 +1144,11 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
::google::protobuf::EnumOptions* options_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
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();
@@ -1115,7 +1205,6 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1161,13 +1250,11 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* name_;
::google::protobuf::EnumValueOptions* options_;
::google::protobuf::int32 number_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
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();
@@ -1224,7 +1311,6 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1273,13 +1359,11 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
::google::protobuf::ServiceOptions* options_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
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();
@@ -1336,7 +1420,6 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1401,14 +1484,12 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* name_;
::std::string* input_type_;
::std::string* output_type_;
::google::protobuf::MethodOptions* options_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
-
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();
@@ -1465,7 +1546,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1535,6 +1615,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
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();
@@ -1575,6 +1662,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
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();
@@ -1598,6 +1692,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
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();
@@ -1608,25 +1704,27 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
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_;
::std::string* java_outer_classname_;
- int optimize_for_;
bool java_multiple_files_;
bool java_generate_equals_and_hash_;
+ bool java_string_check_utf8_;
bool cc_generic_services_;
- bool java_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_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32];
-
+ 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();
@@ -1683,7 +1781,6 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1704,6 +1801,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
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();
@@ -1723,18 +1827,19 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
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_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
-
+ 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();
@@ -1791,7 +1896,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1902,6 +2006,8 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
int ctype_;
bool packed_;
bool lazy_;
@@ -1909,10 +2015,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
bool weak_;
::std::string* experimental_map_key_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-
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();
@@ -1969,20 +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 [default = true];
+ // 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();
@@ -2000,17 +2108,18 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
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_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
+ 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();
@@ -2067,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();
@@ -2089,16 +2204,17 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
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::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+ ::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+ ::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();
@@ -2155,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();
@@ -2177,16 +2299,17 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
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::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+ ::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+ ::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();
@@ -2243,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();
@@ -2265,16 +2394,17 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
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::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
-
+ ::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+ ::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();
@@ -2331,7 +2461,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2366,12 +2495,10 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
::google::protobuf::UnknownFieldSet _unknown_fields_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
::std::string* name_part_;
bool is_extension_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
-
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();
@@ -2428,7 +2555,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2523,6 +2649,8 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
::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_;
::google::protobuf::uint64 positive_int_value_;
@@ -2530,10 +2658,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
double double_value_;
::std::string* string_value_;
::std::string* aggregate_value_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32];
-
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();
@@ -2590,7 +2714,6 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2654,16 +2777,14 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
::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_;
-
- mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
-
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();
@@ -2720,7 +2841,6 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
void SharedDtor();
void SetCachedSize(int size) const;
public:
-
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2746,11 +2866,9 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
::google::protobuf::UnknownFieldSet _unknown_fields_;
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
-
+ ::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32];
-
+ ::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();
@@ -2773,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_;
}
@@ -2805,54 +2928,59 @@ inline void FileDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void FileDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
}
inline ::std::string* FileDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -2860,8 +2988,9 @@ inline void FileDescriptorProto::set_allocated_name(::std::string* name) {
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
}
// optional string package = 2;
@@ -2875,54 +3004,59 @@ inline void FileDescriptorProto::clear_has_package() {
_has_bits_[0] &= ~0x00000002u;
}
inline void FileDescriptorProto::clear_package() {
- if (package_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
package_->clear();
}
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_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
package_ = new ::std::string;
}
package_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
}
inline ::std::string* FileDescriptorProto::mutable_package() {
set_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = package_;
- package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete package_;
}
if (package) {
@@ -2930,8 +3064,9 @@ inline void FileDescriptorProto::set_allocated_package(::std::string* package) {
package_ = package;
} else {
clear_has_package();
- package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
}
// repeated string dependency = 3;
@@ -2942,39 +3077,49 @@ 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<const char*>(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<const char*>(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_;
}
@@ -2986,20 +3131,25 @@ 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_;
}
@@ -3011,20 +3161,25 @@ 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_;
}
@@ -3036,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_;
}
@@ -3061,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_;
}
@@ -3086,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_;
}
@@ -3111,20 +3281,25 @@ 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_;
}
@@ -3143,11 +3318,13 @@ inline void FileDescriptorProto::clear_options() {
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_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() {
@@ -3164,6 +3341,7 @@ inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileO
} else {
clear_has_options();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
}
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
@@ -3181,11 +3359,13 @@ inline void FileDescriptorProto::clear_source_code_info() {
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() {
@@ -3202,6 +3382,7 @@ inline void FileDescriptorProto::set_allocated_source_code_info(::google::protob
} else {
clear_has_source_code_info();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
}
// -------------------------------------------------------------------
@@ -3223,11 +3404,13 @@ inline void DescriptorProto_ExtensionRange::clear_start() {
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_has_start();
start_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start)
}
// optional int32 end = 2;
@@ -3245,11 +3428,13 @@ inline void DescriptorProto_ExtensionRange::clear_end() {
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_has_end();
end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
}
// -------------------------------------------------------------------
@@ -3267,54 +3452,59 @@ inline void DescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void DescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
}
inline ::std::string* DescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -3322,8 +3512,9 @@ inline void DescriptorProto::set_allocated_name(::std::string* name) {
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -3334,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_;
}
@@ -3359,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_;
}
@@ -3384,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_;
}
@@ -3409,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_;
}
@@ -3434,43 +3645,80 @@ 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_bits_[0] & 0x00000040u) != 0;
+ return (_has_bits_[0] & 0x00000080u) != 0;
}
inline void DescriptorProto::set_has_options() {
- _has_bits_[0] |= 0x00000040u;
+ _has_bits_[0] |= 0x00000080u;
}
inline void DescriptorProto::clear_has_options() {
- _has_bits_[0] &= ~0x00000040u;
+ _has_bits_[0] &= ~0x00000080u;
}
inline void DescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
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_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() {
@@ -3487,6 +3735,7 @@ inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOp
} else {
clear_has_options();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
}
// -------------------------------------------------------------------
@@ -3504,54 +3753,59 @@ inline void FieldDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void FieldDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
}
inline ::std::string* FieldDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -3559,8 +3813,9 @@ inline void FieldDescriptorProto::set_allocated_name(::std::string* name) {
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
}
// optional int32 number = 3;
@@ -3578,11 +3833,13 @@ inline void FieldDescriptorProto::clear_number() {
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_has_number();
number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number)
}
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
@@ -3600,12 +3857,14 @@ inline void FieldDescriptorProto::clear_label() {
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) {
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;
@@ -3623,12 +3882,14 @@ inline void FieldDescriptorProto::clear_type() {
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) {
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;
@@ -3642,54 +3903,59 @@ inline void FieldDescriptorProto::clear_has_type_name() {
_has_bits_[0] &= ~0x00000010u;
}
inline void FieldDescriptorProto::clear_type_name() {
- if (type_name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
type_name_->clear();
}
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_has_type_name();
- if (type_name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_type_name();
- if (type_name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_type_name();
- if (type_name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
type_name_ = new ::std::string;
}
type_name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
}
inline ::std::string* FieldDescriptorProto::mutable_type_name() {
set_has_type_name();
- if (type_name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = type_name_;
- type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete type_name_;
}
if (type_name) {
@@ -3697,8 +3963,9 @@ inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_na
type_name_ = type_name;
} else {
clear_has_type_name();
- type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -3712,54 +3979,59 @@ inline void FieldDescriptorProto::clear_has_extendee() {
_has_bits_[0] &= ~0x00000020u;
}
inline void FieldDescriptorProto::clear_extendee() {
- if (extendee_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
extendee_->clear();
}
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_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
extendee_ = new ::std::string;
}
extendee_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
}
inline ::std::string* FieldDescriptorProto::mutable_extendee() {
set_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = extendee_;
- extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete extendee_;
}
if (extendee) {
@@ -3767,8 +4039,9 @@ inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee
extendee_ = extendee;
} else {
clear_has_extendee();
- extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
}
// optional string default_value = 7;
@@ -3782,54 +4055,59 @@ inline void FieldDescriptorProto::clear_has_default_value() {
_has_bits_[0] &= ~0x00000040u;
}
inline void FieldDescriptorProto::clear_default_value() {
- if (default_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
default_value_->clear();
}
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_has_default_value();
- if (default_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_default_value();
- if (default_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_default_value();
- if (default_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
default_value_ = new ::std::string;
}
default_value_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
}
inline ::std::string* FieldDescriptorProto::mutable_default_value() {
set_has_default_value();
- if (default_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = default_value_;
- default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete default_value_;
}
if (default_value) {
@@ -3837,30 +4115,57 @@ inline void FieldDescriptorProto::set_allocated_default_value(::std::string* def
default_value_ = default_value;
} else {
clear_has_default_value();
- default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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_bits_[0] & 0x00000080u) != 0;
+ return (_has_bits_[0] & 0x00000100u) != 0;
}
inline void FieldDescriptorProto::set_has_options() {
- _has_bits_[0] |= 0x00000080u;
+ _has_bits_[0] |= 0x00000100u;
}
inline void FieldDescriptorProto::clear_has_options() {
- _has_bits_[0] &= ~0x00000080u;
+ _has_bits_[0] &= ~0x00000100u;
}
inline void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
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_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() {
@@ -3877,6 +4182,87 @@ inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::Fiel
} else {
clear_has_options();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options)
+}
+
+// -------------------------------------------------------------------
+
+// OneofDescriptorProto
+
+// optional string name = 1;
+inline bool OneofDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+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_has_name();
+}
+inline const ::std::string& OneofDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
+ return *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 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 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<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.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_;
+}
+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 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)
}
// -------------------------------------------------------------------
@@ -3894,54 +4280,59 @@ inline void EnumDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void EnumDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -3949,8 +4340,9 @@ inline void EnumDescriptorProto::set_allocated_name(::std::string* name) {
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -3961,20 +4353,25 @@ 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_;
}
@@ -3993,11 +4390,13 @@ inline void EnumDescriptorProto::clear_options() {
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_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() {
@@ -4014,6 +4413,7 @@ inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumO
} else {
clear_has_options();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options)
}
// -------------------------------------------------------------------
@@ -4031,54 +4431,59 @@ inline void EnumValueDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void EnumValueDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
}
inline ::std::string* EnumValueDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -4086,8 +4491,9 @@ inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
}
// optional int32 number = 2;
@@ -4105,11 +4511,13 @@ inline void EnumValueDescriptorProto::clear_number() {
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_has_number();
number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number)
}
// optional .google.protobuf.EnumValueOptions options = 3;
@@ -4127,11 +4535,13 @@ inline void EnumValueDescriptorProto::clear_options() {
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_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() {
@@ -4148,6 +4558,7 @@ inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::
} else {
clear_has_options();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
}
// -------------------------------------------------------------------
@@ -4165,54 +4576,59 @@ inline void ServiceDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void ServiceDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
}
inline ::std::string* ServiceDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -4220,8 +4636,9 @@ inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -4232,20 +4649,25 @@ 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_;
}
@@ -4264,11 +4686,13 @@ inline void ServiceDescriptorProto::clear_options() {
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_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() {
@@ -4285,6 +4709,7 @@ inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::Se
} else {
clear_has_options();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options)
}
// -------------------------------------------------------------------
@@ -4302,54 +4727,59 @@ inline void MethodDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void MethodDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_->clear();
}
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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_ = new ::std::string;
}
name_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
}
inline ::std::string* MethodDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_;
}
if (name) {
@@ -4357,8 +4787,9 @@ inline void MethodDescriptorProto::set_allocated_name(::std::string* name) {
name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
}
// optional string input_type = 2;
@@ -4372,54 +4803,59 @@ inline void MethodDescriptorProto::clear_has_input_type() {
_has_bits_[0] &= ~0x00000002u;
}
inline void MethodDescriptorProto::clear_input_type() {
- if (input_type_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
input_type_->clear();
}
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_has_input_type();
- if (input_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_input_type();
- if (input_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_input_type();
- if (input_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
input_type_ = new ::std::string;
}
input_type_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
}
inline ::std::string* MethodDescriptorProto::mutable_input_type() {
set_has_input_type();
- if (input_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = input_type_;
- input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete input_type_;
}
if (input_type) {
@@ -4427,8 +4863,9 @@ inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input
input_type_ = input_type;
} else {
clear_has_input_type();
- input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -4442,54 +4879,59 @@ inline void MethodDescriptorProto::clear_has_output_type() {
_has_bits_[0] &= ~0x00000004u;
}
inline void MethodDescriptorProto::clear_output_type() {
- if (output_type_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
output_type_->clear();
}
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_has_output_type();
- if (output_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_output_type();
- if (output_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_output_type();
- if (output_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
output_type_ = new ::std::string;
}
output_type_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
}
inline ::std::string* MethodDescriptorProto::mutable_output_type() {
set_has_output_type();
- if (output_type_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = output_type_;
- output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete output_type_;
}
if (output_type) {
@@ -4497,8 +4939,9 @@ inline void MethodDescriptorProto::set_allocated_output_type(::std::string* outp
output_type_ = output_type;
} else {
clear_has_output_type();
- output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -4516,11 +4959,13 @@ inline void MethodDescriptorProto::clear_options() {
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_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() {
@@ -4537,6 +4982,7 @@ inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::Met
} else {
clear_has_options();
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options)
}
// -------------------------------------------------------------------
@@ -4554,54 +5000,59 @@ inline void FileOptions::clear_has_java_package() {
_has_bits_[0] &= ~0x00000001u;
}
inline void FileOptions::clear_java_package() {
- if (java_package_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
java_package_->clear();
}
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_has_java_package();
- if (java_package_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_java_package();
- if (java_package_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_java_package();
- if (java_package_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
java_package_ = new ::std::string;
}
java_package_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
}
inline ::std::string* FileOptions::mutable_java_package() {
set_has_java_package();
- if (java_package_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = java_package_;
- java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete java_package_;
}
if (java_package) {
@@ -4609,8 +5060,9 @@ inline void FileOptions::set_allocated_java_package(::std::string* java_package)
java_package_ = java_package;
} else {
clear_has_java_package();
- java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -4624,54 +5076,59 @@ inline void FileOptions::clear_has_java_outer_classname() {
_has_bits_[0] &= ~0x00000002u;
}
inline void FileOptions::clear_java_outer_classname() {
- if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
java_outer_classname_->clear();
}
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_has_java_outer_classname();
- if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_java_outer_classname();
- if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_java_outer_classname();
- if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
java_outer_classname_ = new ::std::string;
}
java_outer_classname_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
}
inline ::std::string* FileOptions::mutable_java_outer_classname() {
set_has_java_outer_classname();
- if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete java_outer_classname_;
}
if (java_outer_classname) {
@@ -4679,8 +5136,9 @@ inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_
java_outer_classname_ = java_outer_classname;
} else {
clear_has_java_outer_classname();
- java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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];
@@ -4698,11 +5156,13 @@ inline void FileOptions::clear_java_multiple_files() {
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_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];
@@ -4720,95 +5180,128 @@ inline void FileOptions::clear_java_generate_equals_and_hash() {
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_bits_[0] & 0x00000010u) != 0;
+ return (_has_bits_[0] & 0x00000020u) != 0;
}
inline void FileOptions::set_has_optimize_for() {
- _has_bits_[0] |= 0x00000010u;
+ _has_bits_[0] |= 0x00000020u;
}
inline void FileOptions::clear_has_optimize_for() {
- _has_bits_[0] &= ~0x00000010u;
+ _has_bits_[0] &= ~0x00000020u;
}
inline void FileOptions::clear_optimize_for() {
optimize_for_ = 1;
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) {
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] & 0x00000020u) != 0;
+ return (_has_bits_[0] & 0x00000040u) != 0;
}
inline void FileOptions::set_has_go_package() {
- _has_bits_[0] |= 0x00000020u;
+ _has_bits_[0] |= 0x00000040u;
}
inline void FileOptions::clear_has_go_package() {
- _has_bits_[0] &= ~0x00000020u;
+ _has_bits_[0] &= ~0x00000040u;
}
inline void FileOptions::clear_go_package() {
- if (go_package_ != &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
go_package_ = new ::std::string;
}
go_package_->assign(reinterpret_cast<const char*>(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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = go_package_;
- go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete go_package_;
}
if (go_package) {
@@ -4816,74 +5309,105 @@ inline void FileOptions::set_allocated_go_package(::std::string* go_package) {
go_package_ = go_package;
} else {
clear_has_go_package();
- go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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 = false];
inline bool FileOptions::has_cc_generic_services() const {
- return (_has_bits_[0] & 0x00000040u) != 0;
+ return (_has_bits_[0] & 0x00000080u) != 0;
}
inline void FileOptions::set_has_cc_generic_services() {
- _has_bits_[0] |= 0x00000040u;
+ _has_bits_[0] |= 0x00000080u;
}
inline void FileOptions::clear_has_cc_generic_services() {
- _has_bits_[0] &= ~0x00000040u;
+ _has_bits_[0] &= ~0x00000080u;
}
inline void FileOptions::clear_cc_generic_services() {
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_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 = false];
inline bool FileOptions::has_java_generic_services() const {
- return (_has_bits_[0] & 0x00000080u) != 0;
+ return (_has_bits_[0] & 0x00000100u) != 0;
}
inline void FileOptions::set_has_java_generic_services() {
- _has_bits_[0] |= 0x00000080u;
+ _has_bits_[0] |= 0x00000100u;
}
inline void FileOptions::clear_has_java_generic_services() {
- _has_bits_[0] &= ~0x00000080u;
+ _has_bits_[0] &= ~0x00000100u;
}
inline void FileOptions::clear_java_generic_services() {
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_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 = false];
inline bool FileOptions::has_py_generic_services() const {
- return (_has_bits_[0] & 0x00000100u) != 0;
+ return (_has_bits_[0] & 0x00000200u) != 0;
}
inline void FileOptions::set_has_py_generic_services() {
- _has_bits_[0] |= 0x00000100u;
+ _has_bits_[0] |= 0x00000200u;
}
inline void FileOptions::clear_has_py_generic_services() {
- _has_bits_[0] &= ~0x00000100u;
+ _has_bits_[0] &= ~0x00000200u;
}
inline void FileOptions::clear_py_generic_services() {
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_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;
@@ -4894,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_;
}
@@ -4930,11 +5459,13 @@ inline void MessageOptions::clear_message_set_wire_format() {
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_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];
@@ -4952,11 +5483,37 @@ inline void MessageOptions::clear_no_standard_descriptor_accessor() {
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_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;
@@ -4967,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_;
}
@@ -5003,12 +5565,14 @@ inline void FieldOptions::clear_ctype() {
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) {
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;
@@ -5026,11 +5590,13 @@ inline void FieldOptions::clear_packed() {
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_has_packed();
packed_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
}
// optional bool lazy = 5 [default = false];
@@ -5048,11 +5614,13 @@ inline void FieldOptions::clear_lazy() {
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];
@@ -5070,11 +5638,13 @@ inline void FieldOptions::clear_deprecated() {
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_has_deprecated();
deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated)
}
// optional string experimental_map_key = 9;
@@ -5088,54 +5658,59 @@ inline void FieldOptions::clear_has_experimental_map_key() {
_has_bits_[0] &= ~0x00000010u;
}
inline void FieldOptions::clear_experimental_map_key() {
- if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
experimental_map_key_->clear();
}
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_has_experimental_map_key();
- if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_experimental_map_key();
- if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_experimental_map_key();
- if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
experimental_map_key_ = new ::std::string;
}
experimental_map_key_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldOptions.experimental_map_key)
}
inline ::std::string* FieldOptions::mutable_experimental_map_key() {
set_has_experimental_map_key();
- if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete experimental_map_key_;
}
if (experimental_map_key) {
@@ -5143,8 +5718,9 @@ inline void FieldOptions::set_allocated_experimental_map_key(::std::string* expe
experimental_map_key_ = experimental_map_key;
} else {
clear_has_experimental_map_key();
- experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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];
@@ -5162,11 +5738,13 @@ inline void FieldOptions::clear_weak() {
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;
@@ -5177,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_;
}
@@ -5198,7 +5781,7 @@ FieldOptions::mutable_uninterpreted_option() {
// EnumOptions
-// optional bool allow_alias = 2 [default = true];
+// optional bool allow_alias = 2;
inline bool EnumOptions::has_allow_alias() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
@@ -5209,15 +5792,41 @@ inline void EnumOptions::clear_has_allow_alias() {
_has_bits_[0] &= ~0x00000001u;
}
inline void EnumOptions::clear_allow_alias() {
- allow_alias_ = true;
+ 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;
@@ -5228,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_;
}
@@ -5249,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();
@@ -5257,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_;
}
@@ -5278,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();
@@ -5286,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_;
}
@@ -5307,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();
@@ -5315,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_;
}
@@ -5347,54 +6048,59 @@ inline void UninterpretedOption_NamePart::clear_has_name_part() {
_has_bits_[0] &= ~0x00000001u;
}
inline void UninterpretedOption_NamePart::clear_name_part() {
- if (name_part_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_part_->clear();
}
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_has_name_part();
- if (name_part_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name_part();
- if (name_part_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_name_part();
- if (name_part_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
name_part_ = new ::std::string;
}
name_part_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
}
inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
set_has_name_part();
- if (name_part_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = name_part_;
- name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete name_part_;
}
if (name_part) {
@@ -5402,8 +6108,9 @@ inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string*
name_part_ = name_part;
} else {
clear_has_name_part();
- name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -5421,11 +6128,13 @@ inline void UninterpretedOption_NamePart::clear_is_extension() {
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_has_is_extension();
is_extension_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension)
}
// -------------------------------------------------------------------
@@ -5440,20 +6149,25 @@ 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_;
}
@@ -5468,54 +6182,59 @@ inline void UninterpretedOption::clear_has_identifier_value() {
_has_bits_[0] &= ~0x00000002u;
}
inline void UninterpretedOption::clear_identifier_value() {
- if (identifier_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
identifier_value_->clear();
}
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_has_identifier_value();
- if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_identifier_value();
- if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_identifier_value();
- if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
identifier_value_ = new ::std::string;
}
identifier_value_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
}
inline ::std::string* UninterpretedOption::mutable_identifier_value() {
set_has_identifier_value();
- if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = identifier_value_;
- identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete identifier_value_;
}
if (identifier_value) {
@@ -5523,8 +6242,9 @@ inline void UninterpretedOption::set_allocated_identifier_value(::std::string* i
identifier_value_ = identifier_value;
} else {
clear_has_identifier_value();
- identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -5542,11 +6262,13 @@ inline void UninterpretedOption::clear_positive_int_value() {
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_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;
@@ -5564,11 +6286,13 @@ inline void UninterpretedOption::clear_negative_int_value() {
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_has_negative_int_value();
negative_int_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value)
}
// optional double double_value = 6;
@@ -5586,11 +6310,13 @@ inline void UninterpretedOption::clear_double_value() {
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_has_double_value();
double_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value)
}
// optional bytes string_value = 7;
@@ -5604,54 +6330,59 @@ inline void UninterpretedOption::clear_has_string_value() {
_has_bits_[0] &= ~0x00000020u;
}
inline void UninterpretedOption::clear_string_value() {
- if (string_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
string_value_->clear();
}
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_has_string_value();
- if (string_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_string_value();
- if (string_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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_has_string_value();
- if (string_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
string_value_ = new ::std::string;
}
string_value_->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
}
inline ::std::string* UninterpretedOption::mutable_string_value() {
set_has_string_value();
- if (string_value_ == &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = string_value_;
- string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete string_value_;
}
if (string_value) {
@@ -5659,8 +6390,9 @@ inline void UninterpretedOption::set_allocated_string_value(::std::string* strin
string_value_ = string_value;
} else {
clear_has_string_value();
- string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -5674,54 +6406,59 @@ inline void UninterpretedOption::clear_has_aggregate_value() {
_has_bits_[0] &= ~0x00000040u;
}
inline void UninterpretedOption::clear_aggregate_value() {
- if (aggregate_value_ != &::google::protobuf::internal::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
aggregate_value_ = new ::std::string;
}
aggregate_value_->assign(reinterpret_cast<const char*>(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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = aggregate_value_;
- aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete aggregate_value_;
}
if (aggregate_value) {
@@ -5729,8 +6466,9 @@ inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* ag
aggregate_value_ = aggregate_value;
} else {
clear_has_aggregate_value();
- aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
}
// -------------------------------------------------------------------
@@ -5745,20 +6483,25 @@ 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_;
}
@@ -5770,20 +6513,25 @@ 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_;
}
@@ -5798,54 +6546,59 @@ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
leading_comments_ = new ::std::string;
}
leading_comments_->assign(reinterpret_cast<const char*>(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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = leading_comments_;
- leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete leading_comments_;
}
if (leading_comments) {
@@ -5853,8 +6606,9 @@ inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::strin
leading_comments_ = leading_comments;
} else {
clear_has_leading_comments();
- leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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;
@@ -5868,54 +6622,59 @@ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
trailing_comments_ = new ::std::string;
}
trailing_comments_->assign(reinterpret_cast<const char*>(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::GetEmptyString()) {
+ 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::GetEmptyString()) {
+ if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
return NULL;
} else {
::std::string* temp = trailing_comments_;
- trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ 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::GetEmptyString()) {
+ if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
delete trailing_comments_;
}
if (trailing_comments) {
@@ -5923,8 +6682,9 @@ inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::stri
trailing_comments_ = trailing_comments;
} else {
clear_has_trailing_comments();
- trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
}
// -------------------------------------------------------------------
@@ -5939,20 +6699,25 @@ 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_;
}
@@ -5966,18 +6731,22 @@ SourceCodeInfo::mutable_location() {
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 a785f79f..45141646 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -96,6 +96,8 @@ message DescriptorProto {
}
repeated ExtensionRange extension_range = 5;
+ repeated OneofDescriptorProto oneof_decl = 8;
+
optional MessageOptions options = 7;
}
@@ -143,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
@@ -164,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;
@@ -263,11 +276,26 @@ message FileOptions {
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. This is
- // purely a speed optimization, as the AbstractMessage base class includes
- // reflection-based implementations of these methods.
+ // 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,
@@ -297,6 +325,13 @@ message FileOptions {
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;
@@ -330,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;
@@ -412,6 +453,8 @@ message FieldOptions {
// 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;
@@ -421,9 +464,15 @@ message FieldOptions {
message EnumOptions {
- // Set this option to false to disallow mapping different tag names to a same
+ // Set this option to true to allow mapping different tag names to the same
// value.
- optional bool allow_alias = 2 [default=true];
+ 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;
@@ -433,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;
@@ -447,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;
@@ -461,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;
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index 35e459d5..e5c25366 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -40,7 +40,7 @@
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
namespace google {
namespace protobuf {
@@ -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 604648f8..c35e4785 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -101,6 +101,7 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase {
return false;
}
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
};
@@ -356,6 +357,7 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
bool FindAllExtensionNumbers(const string& extendee_type,
vector<int>* output);
+
private:
vector<DescriptorDatabase*> 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 00000000..1c222288
--- /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 86e6a49d..9b77fbe8 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -646,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() {
@@ -1516,6 +1614,40 @@ 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 {
@@ -1567,6 +1699,18 @@ class MiscTest : public testing::Test {
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<DescriptorPool> pool_;
};
@@ -1595,6 +1739,31 @@ TEST_F(MiscTest, TypeNames) {
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.
@@ -1645,6 +1814,74 @@ TEST_F(MiscTest, CppTypeNames) {
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;
@@ -1910,10 +2147,12 @@ class AllowUnknownDependenciesTest
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()));
@@ -1923,19 +2162,20 @@ TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
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()));
@@ -1993,6 +2233,7 @@ TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) {
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);
@@ -2111,13 +2352,13 @@ TEST_P(AllowUnknownDependenciesTest,
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_EQ("undeclared.Quux.placeholder.proto",
- quux_field->message_type()->file()->name());
+ EXPECT_TRUE(quux_field->message_type()->is_placeholder());
// The place holder type should not be findable.
ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
}
@@ -2167,7 +2408,7 @@ TEST(CustomOptions, OptionTypes) {
options =
&protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
- EXPECT_FALSE( options->GetExtension(protobuf_unittest::bool_opt));
+ EXPECT_EQ(false , options->GetExtension(protobuf_unittest::bool_opt));
EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt));
EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt));
EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt));
@@ -2181,7 +2422,7 @@ TEST(CustomOptions, OptionTypes) {
options =
&protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options();
- EXPECT_TRUE( options->GetExtension(protobuf_unittest::bool_opt));
+ EXPECT_EQ(true , options->GetExtension(protobuf_unittest::bool_opt));
EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt));
EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt));
EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt));
@@ -2389,6 +2630,170 @@ 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) {
@@ -2429,6 +2834,27 @@ TEST(CustomOptions, AggregateOptions) {
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);
+}
+
// ===================================================================
// The tests below trigger every unique call to AddError() in descriptor.cc,
@@ -2442,6 +2868,7 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector {
~MockErrorCollector() {}
string text_;
+ string warning_text_;
// implements ErrorCollector ---------------------------------------
void AddError(const string& filename,
@@ -2465,6 +2892,29 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector {
&text_, "$0: $1: $2: $3\n",
filename, element_name, location_name, message);
}
+
+ // 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 {
@@ -2491,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;
@@ -2744,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"
@@ -2828,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\" "
@@ -2988,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\" "
@@ -2999,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\" "
@@ -3174,7 +3721,8 @@ TEST_F(ValidationErrorTest,
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 {
@@ -3200,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) {
@@ -3342,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\" "
@@ -3366,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\" "
@@ -3527,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 } "
- " 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");
+ "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 } "
+ " name { name_part: \"foo\" "
+ " is_extension: false } "
+ " positive_int_value: 1 } }",
+
+ "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n");
}
TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) {
@@ -3813,6 +4468,25 @@ TEST_F(ValidationErrorTest, StringOptionValueIsNotString) {
"string option \"foo\".\n");
}
+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.
@@ -3998,7 +4672,6 @@ TEST_F(ValidationErrorTest, DisallowEnumAlias) {
" name: \"Bar\""
" value { name:\"ENUM_A\" number:0 }"
" value { name:\"ENUM_B\" number:0 }"
- " options { allow_alias: false }"
"}",
"foo.proto: Bar: NUMBER: "
"\"ENUM_B\" uses the same enum value as \"ENUM_A\". "
@@ -4006,6 +4679,64 @@ TEST_F(ValidationErrorTest, DisallowEnumAlias) {
"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
@@ -4328,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) {
@@ -4396,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) {
@@ -4489,6 +5302,17 @@ const char *const kSourceLocationTestInput =
" 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 {
@@ -4550,6 +5374,27 @@ TEST_F(SourceLocationTest, GetSourceLocation) {
}
+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;
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 09bec543..d3d52113 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -141,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;
@@ -168,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;
@@ -185,11 +217,13 @@ class DynamicMessage : public Message {
// 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) {}
+ TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {}
~TypeInfo() {
delete prototype;
+ operator delete(default_oneof_instance);
}
};
@@ -208,6 +242,7 @@ class DynamicMessage : public Message {
Metadata GetMetadata() const;
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
@@ -245,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) {
@@ -254,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: \
@@ -327,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<const uint32*>(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<string**>(field_ptr);
+ break;
+ }
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ delete *reinterpret_cast<Message**>(field_ptr);
+ }
+ }
+ continue;
+ }
void* field_ptr = OffsetToPointer(type_info_->offsets[i]);
if (field->is_repeated()) {
@@ -402,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<uint8*>(
+ type_info_->default_oneof_instance) + type_info_->offsets[i];
+ }
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
!field->is_repeated()) {
@@ -429,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 {
@@ -459,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;
}
}
@@ -497,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.
@@ -513,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;
@@ -526,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.
@@ -549,23 +642,125 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
type_info->prototype = prototype;
// Construct the reflection object.
- 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));
-
+ 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<uint8*>(
+ 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<string*>(&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);
+ void* field_ptr = reinterpret_cast<uint8*>(
+ default_oneof_instance) + offsets[field->index()];
+ 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 b3d1e5d2..a09593c3 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 <memory>
+
#include <google/protobuf/message.h>
#include <google/protobuf/stubs/common.h>
@@ -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 e4615970..a7866d9c 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_) {}
@@ -98,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_);
}
};
@@ -147,6 +154,63 @@ TEST_F(DynamicMessageTest, PackedFields) {
reflection_tester.ExpectPackedFieldsSetViaReflection(*message);
}
+TEST_F(DynamicMessageTest, Oneof) {
+ // Check that oneof fields work properly.
+ scoped_ptr<Message> 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 2cbba8f5..81ff89fe 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -38,10 +38,9 @@
#include <google/protobuf/extension_set.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
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<pair<const MessageLite*, int>,
ExtensionInfo> ExtensionRegistry;
@@ -304,14 +319,80 @@ PRIMITIVE_ACCESSORS( BOOL, bool, Bool)
#undef PRIMITIVE_ACCESSORS
+const void* ExtensionSet::GetRawRepeatedField(int number,
+ const void* default_value) const {
+ map<int, Extension>::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<WireFormatLite::FieldType>(field_type))) {
+ case WireFormatLite::CPPTYPE_INT32:
+ extension->repeated_int32_value = new RepeatedField<int32>();
+ break;
+ case WireFormatLite::CPPTYPE_INT64:
+ extension->repeated_int64_value = new RepeatedField<int64>();
+ break;
+ case WireFormatLite::CPPTYPE_UINT32:
+ extension->repeated_uint32_value = new RepeatedField<uint32>();
+ break;
+ case WireFormatLite::CPPTYPE_UINT64:
+ extension->repeated_uint64_value = new RepeatedField<uint64>();
+ break;
+ case WireFormatLite::CPPTYPE_DOUBLE:
+ extension->repeated_double_value = new RepeatedField<double>();
+ break;
+ case WireFormatLite::CPPTYPE_FLOAT:
+ extension->repeated_float_value = new RepeatedField<float>();
+ break;
+ case WireFormatLite::CPPTYPE_BOOL:
+ extension->repeated_bool_value = new RepeatedField<bool>();
+ break;
+ case WireFormatLite::CPPTYPE_ENUM:
+ extension->repeated_enum_value = new RepeatedField<int>();
+ break;
+ case WireFormatLite::CPPTYPE_STRING:
+ extension->repeated_string_value = new RepeatedPtrField< ::std::string>();
+ break;
+ case WireFormatLite::CPPTYPE_MESSAGE:
+ extension->repeated_message_value = new RepeatedPtrField<MessageLite>();
+ 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<int, Extension>::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.
- map<int, Extension>::const_iterator iter = extensions_.find(number);
- GOOGLE_CHECK(iter != extensions_.end()) << "no extension numbered " << number;
return iter->second.repeated_int32_value;
}
+
// -------------------------------------------------------------------
// Enums
@@ -826,6 +907,36 @@ void ExtensionSet::Swap(ExtensionSet* x) {
extensions_.swap(x->extensions_);
}
+void ExtensionSet::SwapExtension(ExtensionSet* other,
+ int number) {
+ if (this == other) return;
+ map<int, Extension>::iterator this_iter = extensions_.find(number);
+ map<int, Extension>::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.
@@ -855,41 +966,59 @@ bool ExtensionSet::IsInitialized() const {
}
bool ExtensionSet::FindExtensionInfoFromTag(
- uint32 tag, ExtensionFinder* extension_finder,
- int* field_number, ExtensionInfo* extension) {
+ 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 is_unknown;
- if (!extension_finder->Find(*field_number, extension)) {
- is_unknown = true;
- } else if (extension->is_packed) {
- is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
- } else {
- WireFormatLite::WireType expected_wire_type =
- WireFormatLite::WireTypeForFieldType(real_type(extension->type));
- is_unknown = (wire_type != expected_wire_type);
+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;
}
- return !is_unknown;
+ // 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;
+ bool was_packed_on_wire;
ExtensionInfo extension;
- if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension)) {
+ if (!FindExtensionInfoFromTag(
+ tag, extension_finder, &number, &extension, &was_packed_on_wire)) {
return field_skipper->SkipField(input, tag);
} else {
- return ParseFieldWithExtensionInfo(number, extension, input, field_skipper);
+ return ParseFieldWithExtensionInfo(
+ number, was_packed_on_wire, extension, input, field_skipper);
}
}
bool ExtensionSet::ParseFieldWithExtensionInfo(
- int number, const ExtensionInfo& extension,
+ int number, bool was_packed_on_wire, const ExtensionInfo& extension,
io::CodedInputStream* input,
FieldSkipper* field_skipper) {
- if (extension.is_packed) {
+ // 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);
@@ -903,7 +1032,8 @@ bool ExtensionSet::ParseFieldWithExtensionInfo(
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
@@ -929,8 +1059,8 @@ bool ExtensionSet::ParseFieldWithExtensionInfo(
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;
@@ -952,9 +1082,10 @@ bool ExtensionSet::ParseFieldWithExtensionInfo(
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); \
@@ -986,7 +1117,7 @@ bool ExtensionSet::ParseFieldWithExtensionInfo(
// 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,
@@ -1045,6 +1176,14 @@ 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,
@@ -1456,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<TYPE>* \
+ 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<int32>;
+ RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ =
+ new RepeatedField<int64>;
+ RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ =
+ new RepeatedField<uint32>;
+ RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ =
+ new RepeatedField<uint64>;
+ RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ =
+ new RepeatedField<double>;
+ RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ =
+ new RepeatedField<float>;
+ RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ =
+ new RepeatedField<bool>;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 73529e52..6bdb3d6e 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -46,6 +46,8 @@
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/repeated_field.h>
+
namespace google {
namespace protobuf {
@@ -62,10 +64,7 @@ namespace protobuf {
}
namespace internal {
class FieldSkipper; // wire_format_lite.h
- class RepeatedPtrFieldBase; // repeated_field.h
}
- template <typename Element> class RepeatedField; // repeated_field.h
- template <typename Element> class RepeatedPtrField; // repeated_field.h
}
namespace protobuf {
@@ -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.
@@ -265,6 +267,20 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// 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;
@@ -323,6 +339,7 @@ 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
@@ -342,12 +359,15 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
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).
@@ -505,23 +525,38 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// 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);
+ 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 is extracted from the wire tag and
- // ExtensionInfo is found by the field number.
+ // 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(uint32 tag, io::CodedInputStream* input,
+ bool ParseFieldMaybeLazily(int wire_type, int field_number,
+ io::CodedInputStream* input,
ExtensionFinder* extension_finder,
- FieldSkipper* field_skipper);
+ 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.
@@ -532,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
@@ -587,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);
@@ -625,6 +670,8 @@ template <typename Type>
class PrimitiveTypeTraits {
public:
typedef Type ConstType;
+ typedef Type MutableType;
+ typedef PrimitiveTypeTraits<Type> Singular;
static inline ConstType Get(int number, const ExtensionSet& set,
ConstType default_value);
@@ -636,11 +683,39 @@ template <typename Type>
class RepeatedPrimitiveTypeTraits {
public:
typedef Type ConstType;
+ typedef Type MutableType;
+ typedef RepeatedPrimitiveTypeTraits<Type> Repeated;
+
+ typedef RepeatedField<Type> 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<ConstType>&
+ GetRepeated(int number, const ExtensionSet& set);
+ static inline RepeatedField<Type>*
+ 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<typename Type> friend class RepeatedPrimitiveTypeTraits;
+ friend void InitializeDefaultRepeatedFields();
+ static const RepeatedField<int32>* default_repeated_field_int32_;
+ static const RepeatedField<int64>* default_repeated_field_int64_;
+ static const RepeatedField<uint32>* default_repeated_field_uint32_;
+ static const RepeatedField<uint64>* default_repeated_field_uint64_;
+ static const RepeatedField<double>* default_repeated_field_double_;
+ static const RepeatedField<float>* default_repeated_field_float_;
+ static const RepeatedField<bool>* default_repeated_field_bool_;
};
#define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \
@@ -665,6 +740,26 @@ template<> inline void RepeatedPrimitiveTypeTraits<TYPE>::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<TYPE>* \
+ RepeatedPrimitiveTypeTraits<TYPE>::GetDefaultRepeatedField() { \
+ return RepeatedPrimitiveGenericTypeTraits:: \
+ default_repeated_field_##TYPE##_; \
+} \
+template<> inline const RepeatedField<TYPE>& \
+ RepeatedPrimitiveTypeTraits<TYPE>::GetRepeated(int number, \
+ const ExtensionSet& set) { \
+ return *reinterpret_cast<const RepeatedField<TYPE>*>( \
+ set.GetRawRepeatedField( \
+ number, GetDefaultRepeatedField())); \
+} \
+template<> inline RepeatedField<TYPE>* \
+ RepeatedPrimitiveTypeTraits<TYPE>::MutableRepeated(int number, \
+ FieldType field_type, \
+ bool is_packed, \
+ ExtensionSet* set) { \
+ return reinterpret_cast<RepeatedField<TYPE>*>( \
+ set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); \
}
PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32)
@@ -685,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) {
@@ -704,6 +800,9 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
public:
typedef const string& ConstType;
typedef string* MutableType;
+ typedef RepeatedStringTypeTraits Repeated;
+
+ typedef RepeatedPtrField<string> RepeatedFieldType;
static inline const string& Get(int number, const ExtensionSet& set,
int index) {
@@ -725,6 +824,27 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits {
ExtensionSet* set) {
return set->AddString(number, field_type, NULL);
}
+ static inline const RepeatedPtrField<string>&
+ GetRepeated(int number, const ExtensionSet& set) {
+ return *reinterpret_cast<const RepeatedPtrField<string>*>(
+ set.GetRawRepeatedField(number, GetDefaultRepeatedField()));
+ }
+
+ static inline RepeatedPtrField<string>*
+ MutableRepeated(int number, FieldType field_type,
+ bool is_packed, ExtensionSet* set) {
+ return reinterpret_cast<RepeatedPtrField<string>*>(
+ 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_;
};
// -------------------------------------------------------------------
@@ -736,6 +856,8 @@ template <typename Type, bool IsValid(int)>
class EnumTypeTraits {
public:
typedef Type ConstType;
+ typedef Type MutableType;
+ typedef EnumTypeTraits<Type, IsValid> Singular;
static inline ConstType Get(int number, const ExtensionSet& set,
ConstType default_value) {
@@ -752,6 +874,10 @@ template <typename Type, bool IsValid(int)>
class RepeatedEnumTypeTraits {
public:
typedef Type ConstType;
+ typedef Type MutableType;
+ typedef RepeatedEnumTypeTraits<Type, IsValid> Repeated;
+
+ typedef RepeatedField<Type> RepeatedFieldType;
static inline ConstType Get(int number, const ExtensionSet& set, int index) {
return static_cast<Type>(set.GetRepeatedEnum(number, index));
@@ -766,6 +892,35 @@ class RepeatedEnumTypeTraits {
GOOGLE_DCHECK(IsValid(value));
set->AddEnum(number, field_type, is_packed, value, NULL);
}
+ static inline const RepeatedField<Type>& GetRepeated(int number,
+ const ExtensionSet&
+ set) {
+ // Hack: the `Extension` struct stores a RepeatedField<int> for enums.
+ // RepeatedField<int> cannot implicitly convert to RepeatedField<EnumType>
+ // so we need to do some casting magic. See message.h for similar
+ // contortions for non-extension fields.
+ return *reinterpret_cast<const RepeatedField<Type>*>(
+ set.GetRawRepeatedField(number, GetDefaultRepeatedField()));
+ }
+
+ static inline RepeatedField<Type>* MutableRepeated(int number,
+ FieldType field_type,
+ bool is_packed,
+ ExtensionSet* set) {
+ return reinterpret_cast<RepeatedField<Type>*>(
+ 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<int>. 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<const RepeatedField<Type>*>(
+ RepeatedPrimitiveTypeTraits<int32>::GetDefaultRepeatedField());
+ }
};
// -------------------------------------------------------------------
@@ -779,6 +934,7 @@ class MessageTypeTraits {
public:
typedef const Type& ConstType;
typedef Type* MutableType;
+ typedef MessageTypeTraits<Type> Singular;
static inline ConstType Get(int number, const ExtensionSet& set,
ConstType default_value) {
@@ -801,11 +957,17 @@ class MessageTypeTraits {
}
};
+// forward declaration
+class RepeatedMessageGenericTypeTraits;
+
template <typename Type>
class RepeatedMessageTypeTraits {
public:
typedef const Type& ConstType;
typedef Type* MutableType;
+ typedef RepeatedMessageTypeTraits<Type> Repeated;
+
+ typedef RepeatedPtrField<Type> RepeatedFieldType;
static inline ConstType Get(int number, const ExtensionSet& set, int index) {
return static_cast<const Type&>(set.GetRepeatedMessage(number, index));
@@ -818,8 +980,46 @@ class RepeatedMessageTypeTraits {
return static_cast<Type*>(
set->AddMessage(number, field_type, Type::default_instance(), NULL));
}
+ static inline const RepeatedPtrField<Type>& GetRepeated(int number,
+ const ExtensionSet&
+ set) {
+ // See notes above in RepeatedEnumTypeTraits::GetRepeated(): same
+ // casting hack applies here, because a RepeatedPtrField<MessageLite>
+ // cannot naturally become a RepeatedPtrType<Type> even though Type is
+ // presumably a message. google::protobuf::Message goes through similar contortions
+ // with a reinterpret_cast<>.
+ return *reinterpret_cast<const RepeatedPtrField<Type>*>(
+ set.GetRawRepeatedField(number, GetDefaultRepeatedField()));
+ }
+ static inline RepeatedPtrField<Type>* MutableRepeated(int number,
+ FieldType field_type,
+ bool is_packed,
+ ExtensionSet* set) {
+ return reinterpret_cast<RepeatedPtrField<Type>*>(
+ 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<typename Type> friend class RepeatedMessageTypeTraits;
+ friend void InitializeDefaultRepeatedFields();
+ static const RepeatedFieldType* default_repeated_field_;
};
+template<typename Type> inline
+ const typename RepeatedMessageTypeTraits<Type>::RepeatedFieldType*
+ RepeatedMessageTypeTraits<Type>::GetDefaultRepeatedField() {
+ return reinterpret_cast<const RepeatedFieldType*>(
+ RepeatedMessageGenericTypeTraits::default_repeated_field_);
+}
+
// -------------------------------------------------------------------
// ExtensionIdentifier
@@ -902,7 +1102,7 @@ class ExtensionIdentifier {
template <typename _proto_TypeTraits, \
::google::protobuf::internal::FieldType _field_type, \
bool _is_packed> \
- inline typename _proto_TypeTraits::ConstType GetExtension( \
+ inline typename _proto_TypeTraits::Singular::ConstType GetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \
return _proto_TypeTraits::Get(id.number(), _extensions_, \
@@ -912,7 +1112,7 @@ class ExtensionIdentifier {
template <typename _proto_TypeTraits, \
::google::protobuf::internal::FieldType _field_type, \
bool _is_packed> \
- inline typename _proto_TypeTraits::MutableType MutableExtension( \
+ 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, \
@@ -925,7 +1125,7 @@ class ExtensionIdentifier {
inline void SetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
- typename _proto_TypeTraits::ConstType value) { \
+ typename _proto_TypeTraits::Singular::ConstType value) { \
_proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_); \
} \
\
@@ -935,14 +1135,14 @@ class ExtensionIdentifier {
inline void SetAllocatedExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
- typename _proto_TypeTraits::MutableType value) { \
+ typename _proto_TypeTraits::Singular::MutableType value) { \
_proto_TypeTraits::SetAllocated(id.number(), _field_type, \
value, &_extensions_); \
} \
template <typename _proto_TypeTraits, \
::google::protobuf::internal::FieldType _field_type, \
bool _is_packed> \
- inline typename _proto_TypeTraits::MutableType ReleaseExtension( \
+ 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, \
@@ -953,7 +1153,7 @@ class ExtensionIdentifier {
template <typename _proto_TypeTraits, \
::google::protobuf::internal::FieldType _field_type, \
bool _is_packed> \
- inline typename _proto_TypeTraits::ConstType GetExtension( \
+ inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index) const { \
@@ -963,7 +1163,7 @@ class ExtensionIdentifier {
template <typename _proto_TypeTraits, \
::google::protobuf::internal::FieldType _field_type, \
bool _is_packed> \
- inline typename _proto_TypeTraits::MutableType MutableExtension( \
+ inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
int index) { \
@@ -976,14 +1176,14 @@ class ExtensionIdentifier {
inline void SetExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
- int index, typename _proto_TypeTraits::ConstType value) { \
+ int index, typename _proto_TypeTraits::Repeated::ConstType value) { \
_proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \
} \
\
template <typename _proto_TypeTraits, \
::google::protobuf::internal::FieldType _field_type, \
bool _is_packed> \
- inline typename _proto_TypeTraits::MutableType AddExtension( \
+ 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_); \
@@ -995,9 +1195,32 @@ class ExtensionIdentifier {
inline void AddExtension( \
const ::google::protobuf::internal::ExtensionIdentifier< \
CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \
- typename _proto_TypeTraits::ConstType value) { \
+ typename _proto_TypeTraits::Repeated::ConstType value) { \
_proto_TypeTraits::Add(id.number(), _field_type, _is_packed, \
value, &_extensions_); \
+ } \
+ \
+ template <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
+ 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 <typename _proto_TypeTraits, \
+ ::google::protobuf::internal::FieldType _field_type, \
+ bool _is_packed> \
+ 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 483d7055..a58c99d2 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -48,6 +48,29 @@ 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.
@@ -172,7 +195,7 @@ MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
MessageLite* ret = NULL;
if (iter->second.is_lazy) {
ret = iter->second.lazymessage_value->ReleaseMessage(
- *factory->GetPrototype(descriptor->message_type()));
+ *factory->GetPrototype(descriptor->message_type()));
delete iter->second.lazymessage_value;
} else {
ret = iter->second.message_value;
@@ -261,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);
@@ -511,17 +534,19 @@ uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray(
bool ExtensionSet::ParseFieldMaybeLazily(
- uint32 tag, io::CodedInputStream* input,
+ int wire_type, int field_number, io::CodedInputStream* input,
ExtensionFinder* extension_finder,
- FieldSkipper* field_skipper) {
- return ParseField(tag, input, extension_finder, field_skipper);
+ MessageSetFieldSkipper* field_skipper) {
+ return ParseField(WireFormatLite::MakeTag(
+ field_number, static_cast<WireFormatLite::WireType>(wire_type)),
+ input, extension_finder, field_skipper);
}
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
ExtensionFinder* extension_finder,
- FieldSkipper* field_skipper) {
+ MessageSetFieldSkipper* field_skipper) {
while (true) {
- uint32 tag = input->ReadTag();
+ const uint32 tag = input->ReadTag();
switch (tag) {
case 0:
return true;
@@ -541,14 +566,14 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input,
const MessageLite* containing_type) {
- FieldSkipper skipper;
+ MessageSetFieldSkipper skipper(NULL);
GeneratedExtensionFinder finder(containing_type);
return ParseMessageSet(input, &finder, &skipper);
}
bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
ExtensionFinder* extension_finder,
- FieldSkipper* field_skipper) {
+ 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.
@@ -557,25 +582,21 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
// 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;
// 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) {
- uint32 tag = input->ReadTag();
+ 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;
- fake_tag = WireFormatLite::MakeTag(type_id,
- WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ last_type_id = type_id;
if (!message_data.empty()) {
// We saw some message data before the type_id. Have to parse it
@@ -583,7 +604,8 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
io::CodedInputStream sub_input(
reinterpret_cast<const uint8*>(message_data.data()),
message_data.size());
- if (!ParseFieldMaybeLazily(fake_tag, &sub_input,
+ if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+ last_type_id, &sub_input,
extension_finder, field_skipper)) {
return false;
}
@@ -594,7 +616,7 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
}
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;
@@ -606,7 +628,8 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input,
coded_output.WriteString(temp);
} else {
// Already saw type_id, so we can parse this directly.
- if (!ParseFieldMaybeLazily(fake_tag, input,
+ if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
+ last_type_id, input,
extension_finder, field_skipper)) {
return false;
}
@@ -689,8 +712,8 @@ int ExtensionSet::Extension::MessageSetItemByteSize(int number) const {
void ExtensionSet::SerializeMessageSetWithCachedSizes(
io::CodedOutputStream* output) const {
- map<int, Extension>::const_iterator iter;
- for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) {
+ for (map<int, Extension>::const_iterator iter = extensions_.begin();
+ iter != extensions_.end(); ++iter) {
iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output);
}
}
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 559de6e1..52e551cd 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -142,7 +142,7 @@ TEST(ExtensionSetTest, ClearOneField) {
TestUtil::ExpectAllExtensionsSet(message);
}
-TEST(ExtensionSetTest, SetAllocatedExtensin) {
+TEST(ExtensionSetTest, SetAllocatedExtension) {
unittest::TestAllExtensions message;
EXPECT_FALSE(message.HasExtension(
unittest::optional_foreign_message_extension));
@@ -162,11 +162,11 @@ TEST(ExtensionSetTest, SetAllocatedExtensin) {
// 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());
+ new unittest::ForeignMessage());
// SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion.
message.SetAllocatedExtension(unittest::optional_foreign_message_extension,
- NULL);
+ NULL);
EXPECT_FALSE(message.HasExtension(
unittest::optional_foreign_message_extension));
}
@@ -186,7 +186,7 @@ TEST(ExtensionSetTest, ReleaseExtension) {
// Release the extension using ReleaseExtension
unittest::TestMessageSetExtension1* released_extension =
message.ReleaseExtension(
- unittest::TestMessageSetExtension1::message_set_extension);
+ unittest::TestMessageSetExtension1::message_set_extension);
EXPECT_EQ(extension, released_extension);
EXPECT_FALSE(message.HasExtension(
unittest::TestMessageSetExtension1::message_set_extension));
@@ -198,7 +198,7 @@ TEST(ExtensionSetTest, ReleaseExtension) {
message.ClearExtension(
unittest::TestMessageSetExtension1::message_set_extension);
released_extension = message.ReleaseExtension(
- unittest::TestMessageSetExtension1::message_set_extension);
+ unittest::TestMessageSetExtension1::message_set_extension);
EXPECT_TRUE(released_extension != NULL);
delete released_extension;
}
@@ -256,6 +256,82 @@ TEST(ExtensionSetTest, SwapWithSelf) {
TestUtil::ExpectAllExtensionsSet(message);
}
+TEST(ExtensionSetTest, SwapExtension) {
+ unittest::TestAllExtensions message1;
+ unittest::TestAllExtensions message2;
+
+ TestUtil::SetAllExtensions(&message1);
+ vector<const FieldDescriptor*> 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<const FieldDescriptor*> 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<const FieldDescriptor*> 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<const FieldDescriptor*> 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.
@@ -353,6 +429,7 @@ TEST(ExtensionSetTest, Parsing) {
TestUtil::SetAllFields(&source);
source.SerializeToString(&data);
EXPECT_TRUE(destination.ParseFromString(data));
+ TestUtil::SetOneofFields(&destination);
TestUtil::ExpectAllExtensionsSet(destination);
}
@@ -368,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.
@@ -550,6 +669,256 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) {
}
}
+// N.B.: We do not test range-based for here because we remain C++03 compatible.
+template<typename T, typename M, typename ID>
+inline T SumAllExtensions(const M& message, ID extension, T zero) {
+ T sum = zero;
+ typename RepeatedField<T>::const_iterator iter =
+ message.GetRepeatedExtension(extension).begin();
+ typename RepeatedField<T>::const_iterator end =
+ message.GetRepeatedExtension(extension).end();
+ for (; iter != end; ++iter) {
+ sum += *iter;
+ }
+ return sum;
+}
+
+template<typename T, typename M, typename ID>
+inline void IncAllExtensions(M* message, ID extension,
+ T val) {
+ typename RepeatedField<T>::iterator iter =
+ message->MutableRepeatedExtension(extension)->begin();
+ typename RepeatedField<T>::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<int32>(
+ message, unittest::repeated_int32_extension, 0));
+ IncAllExtensions<int32>(
+ &message, unittest::repeated_int32_extension, 1);
+ ASSERT_EQ(20, SumAllExtensions<int32>(
+ message, unittest::repeated_int32_extension, 0));
+
+ ASSERT_EQ(20, SumAllExtensions<int64>(
+ message, unittest::repeated_int64_extension, 0));
+ IncAllExtensions<int64>(
+ &message, unittest::repeated_int64_extension, 1);
+ ASSERT_EQ(30, SumAllExtensions<int64>(
+ message, unittest::repeated_int64_extension, 0));
+
+ ASSERT_EQ(30, SumAllExtensions<uint32>(
+ message, unittest::repeated_uint32_extension, 0));
+ IncAllExtensions<uint32>(
+ &message, unittest::repeated_uint32_extension, 1);
+ ASSERT_EQ(40, SumAllExtensions<uint32>(
+ message, unittest::repeated_uint32_extension, 0));
+
+ ASSERT_EQ(40, SumAllExtensions<uint64>(
+ message, unittest::repeated_uint64_extension, 0));
+ IncAllExtensions<uint64>(
+ &message, unittest::repeated_uint64_extension, 1);
+ ASSERT_EQ(50, SumAllExtensions<uint64>(
+ message, unittest::repeated_uint64_extension, 0));
+
+ ASSERT_EQ(50, SumAllExtensions<int32>(
+ message, unittest::repeated_sint32_extension, 0));
+ IncAllExtensions<int32>(
+ &message, unittest::repeated_sint32_extension, 1);
+ ASSERT_EQ(60, SumAllExtensions<int32>(
+ message, unittest::repeated_sint32_extension, 0));
+
+ ASSERT_EQ(60, SumAllExtensions<int64>(
+ message, unittest::repeated_sint64_extension, 0));
+ IncAllExtensions<int64>(
+ &message, unittest::repeated_sint64_extension, 1);
+ ASSERT_EQ(70, SumAllExtensions<int64>(
+ message, unittest::repeated_sint64_extension, 0));
+
+ ASSERT_EQ(70, SumAllExtensions<uint32>(
+ message, unittest::repeated_fixed32_extension, 0));
+ IncAllExtensions<uint32>(
+ &message, unittest::repeated_fixed32_extension, 1);
+ ASSERT_EQ(80, SumAllExtensions<uint32>(
+ message, unittest::repeated_fixed32_extension, 0));
+
+ ASSERT_EQ(80, SumAllExtensions<uint64>(
+ message, unittest::repeated_fixed64_extension, 0));
+ IncAllExtensions<uint64>(
+ &message, unittest::repeated_fixed64_extension, 1);
+ ASSERT_EQ(90, SumAllExtensions<uint64>(
+ 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<float>(
+ message, unittest::repeated_float_extension, 0));
+ IncAllExtensions<float>(
+ &message, unittest::repeated_float_extension, 1);
+ ASSERT_EQ(100, SumAllExtensions<float>(
+ message, unittest::repeated_float_extension, 0));
+
+ ASSERT_EQ(100, SumAllExtensions<double>(
+ message, unittest::repeated_double_extension, 0));
+ IncAllExtensions<double>(
+ &message, unittest::repeated_double_extension, 1);
+ ASSERT_EQ(110, SumAllExtensions<double>(
+ message, unittest::repeated_double_extension, 0));
+
+ typename RepeatedPtrField< ::std::string>::iterator string_iter;
+ typename 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";
+ }
+ typename RepeatedPtrField< ::std::string>::const_iterator string_const_iter;
+ typename 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");
+ }
+
+ typename RepeatedField<unittest::TestAllTypes_NestedEnum>::iterator enum_iter;
+ typename RepeatedField<unittest::TestAllTypes_NestedEnum>::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;
+ }
+ typename RepeatedField<unittest::TestAllTypes_NestedEnum>::const_iterator
+ enum_const_iter;
+ typename RepeatedField<unittest::TestAllTypes_NestedEnum>::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);
+ }
+
+ typename RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::iterator
+ msg_iter;
+ typename RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::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);
+ }
+ typename RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::
+ const_iterator msg_const_iter;
+ typename RepeatedPtrField<unittest::TestAllTypes_NestedMessage>::
+ 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) {
diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h
index a09a540b..2780a9b3 100644
--- a/src/google/protobuf/generated_enum_reflection.h
+++ b/src/google/protobuf/generated_enum_reflection.h
@@ -41,6 +41,8 @@
#include <string>
+#include <google/protobuf/stubs/template_util.h>
+
namespace google {
namespace protobuf {
class EnumDescriptor;
@@ -48,6 +50,10 @@ namespace protobuf {
namespace protobuf {
+// This type trait can be used to cause templates to only match proto2 enum
+// types.
+template <typename T> 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.
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 33297ed1..853aadbf 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <algorithm>
+#include <set>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/descriptor.h>
@@ -41,6 +42,8 @@
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/stubs/common.h>
+#define GOOGLE_PROTOBUF_HAS_ONEOF
+
namespace google {
namespace protobuf {
namespace internal {
@@ -49,7 +52,7 @@ 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 {
@@ -188,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(
@@ -254,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 :
@@ -306,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<RepeatedField<TYPE> >(message1, field)->Swap( \
+ MutableRaw<RepeatedField<TYPE> >(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<RepeatedPtrFieldBase>(message1, field)->Swap(
+ MutableRaw<RepeatedPtrFieldBase>(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<TYPE>(message1, field), \
+ *MutableRaw<TYPE>(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<Message*>(message1, field),
+ *MutableRaw<Message*>(message2, field));
+ break;
+
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING:
+ std::swap(*MutableRaw<string*>(message1, field),
+ *MutableRaw<string*>(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<TYPE>(*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<TYPE>(message1, field2, GetField<TYPE>(*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<TYPE>(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 {
@@ -337,76 +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<RepeatedField<TYPE> >(message1, field)->Swap( \
- MutableRaw<RepeatedField<TYPE> >(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<RepeatedPtrFieldBase>(message1, field)->Swap(
- MutableRaw<RepeatedPtrFieldBase>(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<TYPE>(message1, field), \
- *MutableRaw<TYPE>(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 );
-#undef SWAP_VALUES
- case FieldDescriptor::CPPTYPE_MESSAGE:
- std::swap(*MutableRaw<Message*>(message1, field),
- *MutableRaw<Message*>(message2, field));
- break;
+void GeneratedMessageReflection::SwapFields(
+ Message* message1,
+ Message* message2,
+ const vector<const FieldDescriptor*>& 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<string*>(message1, field),
- *MutableRaw<string*>(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.";
+
+ std::set<int> swapped_oneof;
- default:
- GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type();
+ 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);
@@ -667,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);
}
}
@@ -777,7 +1005,7 @@ string GeneratedMessageReflection::GetString(
const string& GeneratedMessageReflection::GetStringReference(
const Message& message,
- const FieldDescriptor* field, string* /* scratch */) const {
+ const FieldDescriptor* field, string* scratch) const {
USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
if (field->is_extension()) {
return GetExtensionSet(message).GetString(field->number(),
@@ -806,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<string*>(message, field) = new string;
+ }
string** ptr = MutableField<string*>(message, field);
if (*ptr == DefaultRaw<const string*>(field)) {
*ptr = new string(value);
@@ -838,7 +1070,7 @@ string GeneratedMessageReflection::GetRepeatedString(
const string& GeneratedMessageReflection::GetRepeatedStringReference(
const Message& message, const FieldDescriptor* field,
- int index, string* /* scratch */) const {
+ int index, string* scratch) const {
USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
if (field->is_extension()) {
return GetExtensionSet(message).GetRepeatedString(field->number(), index);
@@ -1000,8 +1232,6 @@ 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()) {
@@ -1009,7 +1239,19 @@ Message* GeneratedMessageReflection::MutableMessage(
MutableExtensionSet(message)->MutableMessage(field, factory));
} else {
Message* result;
- Message** result_holder = MutableField<Message*>(message, field);
+ Message** result_holder = MutableRaw<Message*>(message, field);
+
+ if (field->containing_oneof()) {
+ if (!HasOneofField(*message, field)) {
+ ClearOneof(message, field->containing_oneof());
+ result_holder = MutableField<Message*>(message, field);
+ const Message* default_message = DefaultRaw<const Message*>(field);
+ *result_holder = default_message->New();
+ }
+ } else {
+ SetBit(message, field);
+ }
+
if (*result_holder == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
*result_holder = default_message->New();
@@ -1019,6 +1261,38 @@ Message* GeneratedMessageReflection::MutableMessage(
}
}
+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*>(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*>(message, field);
+ delete *sub_message_holder;
+ *sub_message_holder = sub_message;
+ }
+}
+
Message* GeneratedMessageReflection::ReleaseMessage(
Message* message,
const FieldDescriptor* field,
@@ -1032,6 +1306,13 @@ Message* GeneratedMessageReflection::ReleaseMessage(
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*>(message, field);
Message* ret = *result;
*result = NULL;
@@ -1111,11 +1392,21 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
if (field->is_extension())
return MutableExtensionSet(message)->MutableRawRepeatedField(
- field->number());
+ field->number(), field->type(), field->is_packed(), field);
else
return reinterpret_cast<uint8*>(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(
@@ -1162,23 +1453,35 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
template <typename Type>
inline const Type& GeneratedMessageReflection::GetRaw(
const Message& message, const FieldDescriptor* field) const {
+ if (field->containing_oneof() && !HasOneofField(message, field)) {
+ return DefaultRaw<Type>(field);
+ }
+ int index = field->containing_oneof() ?
+ descriptor_->field_count() + field->containing_oneof()->index() :
+ field->index();
const void* ptr = reinterpret_cast<const uint8*>(&message) +
- offsets_[field->index()];
+ offsets_[index];
return *reinterpret_cast<const Type*>(ptr);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableRaw(
Message* message, const FieldDescriptor* field) const {
- void* ptr = reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+ int index = field->containing_oneof() ?
+ descriptor_->field_count() + field->containing_oneof()->index() :
+ field->index();
+ void* ptr = reinterpret_cast<uint8*>(message) + offsets_[index];
return reinterpret_cast<Type*>(ptr);
}
template <typename Type>
inline const Type& GeneratedMessageReflection::DefaultRaw(
const FieldDescriptor* field) const {
- const void* ptr = reinterpret_cast<const uint8*>(default_instance_) +
- offsets_[field->index()];
+ const void* ptr = field->containing_oneof() ?
+ reinterpret_cast<const uint8*>(default_oneof_instance_) +
+ offsets_[field->index()] :
+ reinterpret_cast<const uint8*>(default_instance_) +
+ offsets_[field->index()];
return *reinterpret_cast<const Type*>(ptr);
}
@@ -1193,6 +1496,21 @@ inline uint32* GeneratedMessageReflection::MutableHasBits(
return reinterpret_cast<uint32*>(ptr);
}
+inline const uint32 GeneratedMessageReflection::GetOneofCase(
+ const Message& message,
+ const OneofDescriptor* oneof_descriptor) const {
+ const void* ptr = reinterpret_cast<const uint8*>(&message)
+ + oneof_case_offset_;
+ return reinterpret_cast<const uint32*>(ptr)[oneof_descriptor->index()];
+}
+
+inline uint32* GeneratedMessageReflection::MutableOneofCase(
+ Message* message,
+ const OneofDescriptor* oneof_descriptor) const {
+ void* ptr = reinterpret_cast<uint8*>(message) + oneof_case_offset_;
+ return &(reinterpret_cast<uint32*>(ptr)[oneof_descriptor->index()]);
+}
+
inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
const Message& message) const {
GOOGLE_DCHECK_NE(extensions_offset_, -1);
@@ -1224,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<string*>(message, field);
+ break;
+ }
+ break;
+ }
+
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ delete *MutableRaw<Message*>(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.
@@ -1236,14 +1621,19 @@ inline const Type& GeneratedMessageReflection::GetField(
template <typename Type>
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<Type>(message, field) = value;
- SetBit(message, field);
+ field->containing_oneof() ?
+ SetOneofCase(message, field) : SetBit(message, field);
}
template <typename Type>
inline Type* GeneratedMessageReflection::MutableField(
Message* message, const FieldDescriptor* field) const {
- SetBit(message, field);
+ field->containing_oneof() ?
+ SetOneofCase(message, field) : SetBit(message, field);
return MutableRaw<Type>(message, field);
}
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index c1c142fa..0a31057a 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -61,6 +61,7 @@ namespace protobuf {
namespace protobuf {
namespace internal {
+class DefaultEmptyOneof;
// Defined in this file.
class GeneratedMessageReflection;
@@ -134,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 -------------------------------------------
@@ -146,11 +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<const FieldDescriptor*>& 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<const FieldDescriptor*>* output) const;
@@ -179,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,
@@ -200,6 +247,9 @@ 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;
@@ -293,9 +343,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
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_;
@@ -311,9 +363,17 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const FieldDescriptor* field) const;
template <typename Type>
inline const Type& DefaultRaw(const FieldDescriptor* field) const;
+ template <typename Type>
+ inline const Type& DefaultOneofRaw(const FieldDescriptor* field) const;
inline const uint32* GetHasBits(const Message& message) const;
inline uint32* MutableHasBits(Message* message) const;
+ inline const 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;
@@ -323,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 <typename Type>
inline const Type& GetField(const Message& message,
@@ -376,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<int>( \
- reinterpret_cast<const char*>( \
- &reinterpret_cast<const TYPE*>(16)->FIELD) - \
- reinterpret_cast<const char*>(16))
+ reinterpret_cast<const char*>( \
+ &reinterpret_cast<const TYPE*>(16)->FIELD) - \
+ reinterpret_cast<const char*>(16))
+
+#define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD) \
+ static_cast<int>( \
+ reinterpret_cast<const char*>(&(ONEOF->FIELD)) \
+ - reinterpret_cast<const char*>(ONEOF))
// There are some places in proto2 where dynamic_cast would be useful as an
// optimization. For example, take Message::MergeFrom(const Message& other).
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index 39aa55fb..99c28188 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<const FieldDescriptor*> 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<const FieldDescriptor*> 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<const FieldDescriptor*> 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<const FieldDescriptor*> 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(
@@ -375,6 +480,192 @@ TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) {
FindKnownExtensionByName(extension1->full_name()) == NULL);
}
+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<const FieldDescriptor*> 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(
@@ -427,6 +718,26 @@ TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) {
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) {
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 58d6bce4..c0726a67 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -36,6 +36,7 @@
#include <limits>
+
namespace google {
namespace protobuf {
namespace internal {
@@ -48,12 +49,13 @@ double NaN() {
}
const ::std::string* empty_string_;
-ProtobufOnceType empty_string_once_init_;
+GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
void InitEmptyString() {
- empty_string_ = new std::string;
+ empty_string_ = new string;
}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 098f3219..b6c0cf92 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -38,14 +38,18 @@
#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
+#include <assert.h>
#include <string>
-#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
+
+#include <google/protobuf/stubs/common.h>
namespace google {
+
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.
@@ -60,17 +64,26 @@ namespace internal {
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& GetEmptyString() {
- GoogleOnceInit(&empty_string_once_init_, &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.
@@ -80,6 +93,19 @@ LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
// 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<some message type>. 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 <class Type> 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 36add8c3..f6a84533 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -83,6 +83,10 @@ CodedInputStream::~CodedInputStream() {
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_;
if (backup_bytes > 0) {
@@ -167,6 +171,11 @@ void CodedInputStream::SetTotalBytesLimit(
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_
@@ -247,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).
@@ -313,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.
@@ -347,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;
@@ -391,8 +413,8 @@ uint32 CodedInputStream::ReadTagSlow() {
uint32 CodedInputStream::ReadTagFallback() {
const int buf_size = BufferSize();
if (buf_size >= 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.
(buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
uint32 tag;
const uint8* end = ReadVarint32FromArray(buffer_, &tag);
@@ -444,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.
@@ -457,16 +479,26 @@ 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.
@@ -555,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,
@@ -609,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)];
@@ -852,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 66cbee00..50a03a11 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -233,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<uint32, bool> 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
@@ -264,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
@@ -333,7 +344,7 @@ 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. For backwards compatibility all negative values get squached to -1,
+ // 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.
//
@@ -356,6 +367,10 @@ 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
@@ -466,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
@@ -638,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
@@ -649,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.
@@ -725,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);
@@ -733,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
@@ -850,6 +886,45 @@ inline uint32 CodedInputStream::ReadTag() {
}
}
+inline std::pair<uint32, bool> 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<int8>(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<uint32>(last_tag_ - 1) < cutoff);
+}
+
inline bool CodedInputStream::LastTagWas(uint32 expected) {
return last_tag_ == expected;
}
@@ -1029,6 +1104,15 @@ inline void CodedOutputStream::WriteString(const string& str) {
WriteRaw(str.data(), static_cast<int>(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(), static_cast<int>(str.size()), target);
diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h
index 144f44f0..41dc10e3 100644
--- a/src/google/protobuf/io/coded_stream_inl.h
+++ b/src/google/protobuf/io/coded_stream_inl.h
@@ -37,6 +37,7 @@
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <string>
#include <google/protobuf/stubs/stl_util.h>
@@ -53,7 +54,7 @@ inline bool CodedInputStream::InternalReadStringInline(string* buffer,
// 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(string_as_array(buffer), buffer_, size);
+ 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 2daab194..b39987ca 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -144,6 +144,10 @@ uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize];
// checks.
const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024};
+// In several ReadCord test functions, we either clear the Cord before ReadCord
+// calls or not.
+const bool kResetCords[] = {false, true};
+
// -------------------------------------------------------------------
// Varint tests.
@@ -682,6 +686,191 @@ 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
@@ -980,9 +1169,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<string> errors;
@@ -997,7 +1188,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) {
diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
index 365e9ea5..7ee24bc3 100644
--- a/src/google/protobuf/io/gzip_stream.h
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -118,7 +118,7 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream {
ZLIB = 2,
};
- struct LIBPROTOBUF_EXPORT Options {
+ struct Options {
// Defaults to GZIP.
Format format;
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index c9b30359..76fb9442 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -231,7 +231,7 @@ TEST(Printer, Death) {
EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name");
EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent");
}
-#endif // PROTOBUF__HAS_DEATH_TEST
+#endif // PROTOBUF_HAS_DEATH_TEST
TEST(Printer, WriteFailurePartial) {
char buffer[17];
diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc
new file mode 100644
index 00000000..cf0c6e10
--- /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 <google/protobuf/io/strtod.h>
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+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<char*>(
+ text + (localized_endptr - localized_cstr - size_diff));
+ }
+ }
+
+ return result;
+}
+
+} // namespace io
+} // namespace protobuf
+} // namespace google
diff --git a/python/google/protobuf/pyext/python_protobuf.h b/src/google/protobuf/io/strtod.h
index c5b0b1cd..2be3c43d 100644
--- a/python/google/protobuf/pyext/python_protobuf.h
+++ b/src/google/protobuf/io/strtod.h
@@ -28,30 +28,23 @@
// (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__
+// A locale-independent version of strtod(), used to parse floating
+// point default values in .proto files, where the decimal separator
+// is always a dot.
-#include <Python.h>
+#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__
+#define GOOGLE_PROTOBUF_IO_STRTOD_H__
namespace google {
namespace protobuf {
+namespace io {
-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);
+// 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 python
+} // namespace io
} // namespace protobuf
} // namespace google
-#endif // GOOGLE_PROTOBUF_PYTHON_PYTHON_PROTOBUF_H__
+#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index a022b71d..d149305a 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -91,6 +91,7 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/io/strtod.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -195,7 +196,9 @@ Tokenizer::Tokenizer(ZeroCopyInputStream* input,
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;
@@ -350,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 '\\': {
@@ -449,7 +459,7 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero,
}
}
- if (LookingAt<Letter>()) {
+ if (LookingAt<Letter>() && require_space_after_number_) {
AddError("Need space between number and identifier.");
} else if (current_char_ == '.') {
if (is_float) {
@@ -618,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<unsigned char>(current_char_)));
+ }
NextChar();
current_.type = TYPE_SYMBOL;
}
@@ -1086,6 +1102,26 @@ void Tokenizer::ParseStringAppend(const string& text, string* output) {
}
}
+template<typename CharacterClass>
+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<Alphanumeric>(text.substr(1)))
+ return false;
+ return true;
+}
+
} // namespace io
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 6b727d9f..2f07116e 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -229,6 +229,21 @@ 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);
@@ -259,6 +274,8 @@ class LIBPROTOBUF_EXPORT Tokenizer {
// 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.
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index dbb5be4f..b39279b7 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -411,12 +411,6 @@ MultiTokenCase kMultiTokenCases[] = {
{ Tokenizer::TYPE_END , "" , 1, 3, 3 },
}},
- // Bytes with the high-order bit set should not be seen as control characters.
- { "\300", {
- { Tokenizer::TYPE_SYMBOL, "\300", 0, 0, 1 },
- { Tokenizer::TYPE_END , "" , 0, 1, 1 },
- }},
-
// Test all whitespace chars
{ "foo\n\t\r\v\fbar", {
{ Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 },
@@ -741,7 +735,7 @@ TEST_F(TokenizerTest, ParseInteger) {
EXPECT_EQ(0, ParseInteger("0x"));
uint64 i;
-#ifdef PROTOBUF_HASDEATH_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");
@@ -753,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 // PROTOBUF_HASDEATH_TEST
+#endif // PROTOBUF_HAS_DEATH_TEST
// Test overflows.
EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i));
@@ -796,7 +790,7 @@ TEST_F(TokenizerTest, ParseFloat) {
EXPECT_EQ( 0.0, Tokenizer::ParseFloat("1e-9999999999999999999999999999"));
EXPECT_EQ(HUGE_VAL, Tokenizer::ParseFloat("1e+9999999999999999999999999999"));
-#ifdef PROTOBUF_HASDEATH_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");
@@ -804,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 // PROTOBUF_HASDEATH_TEST
+#endif // PROTOBUF_HAS_DEATH_TEST
}
TEST_F(TokenizerTest, ParseString) {
@@ -843,10 +837,10 @@ TEST_F(TokenizerTest, ParseString) {
EXPECT_EQ("u0", output);
// Test invalid strings that will never be tokenized as strings.
-#ifdef PROTOBUF_HASDEATH_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 // PROTOBUF_HASDEATH_TEST
+#endif // PROTOBUF_HAS_DEATH_TEST
}
TEST_F(TokenizerTest, ParseStringAppend) {
@@ -883,7 +877,7 @@ 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,
@@ -951,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) {
diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc
index dad6ff14..4d53f29b 100644
--- a/src/google/protobuf/io/zero_copy_stream.cc
+++ b/src/google/protobuf/io/zero_copy_stream.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/common.h>
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 db5326f7..f8921228 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 9fcbb622..7829a29f 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -413,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.
@@ -457,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 9fedb005..83827097 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 b3a71ce3..d186a98b 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -33,10 +33,12 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stl_util.h>
#include <algorithm>
+#include <limits>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stl_util.h>
namespace google {
namespace protobuf {
@@ -161,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<int>::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 153f543e..b980143e 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 <iosfwd>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stl_util.h>
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 6f155df7..75eb2a43 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -560,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);
@@ -923,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 7a0a57b7..6f385bd3 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -36,6 +36,10 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/test_util_lite.h>
#include <google/protobuf/unittest_lite.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/wire_format_lite_inl.h>
using namespace std;
@@ -57,10 +61,31 @@ void AssignParsingMergeMessages(
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;
@@ -84,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);
@@ -180,6 +204,147 @@ int main(int argc, char* argv[]) {
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 0c305d56..e838d30c 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -32,7 +32,6 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <istream>
#include <stack>
#include <google/protobuf/stubs/hash.h>
@@ -48,7 +47,7 @@
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
namespace google {
@@ -75,7 +74,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);
@@ -100,7 +99,7 @@ void Message::FindInitializationErrors(vector<string>* errors) const {
string Message::InitializationErrorString() const {
vector<string> errors;
FindInitializationErrors(&errors);
- return JoinStrings(errors, ", ");
+ return Join(errors, ", ");
}
void Message::CheckInitialized() const {
@@ -216,8 +215,7 @@ HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
#undef HANDLE_TYPE
void* Reflection::MutableRawRepeatedString(
- Message* message, const FieldDescriptor* field,
- bool /* is_string */) const {
+ Message* message, const FieldDescriptor* field, bool is_string) const {
return MutableRawRepeatedField(message, field,
FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL);
}
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 0f90bc1a..34a8dd1d 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -110,15 +110,9 @@
#ifndef GOOGLE_PROTOBUF_MESSAGE_H__
#define GOOGLE_PROTOBUF_MESSAGE_H__
-#include <vector>
-#include <string>
-
-#ifdef __DECCXX
-// HP C++'s iosfwd doesn't work.
-#include <iostream>
-#else
#include <iosfwd>
-#endif
+#include <string>
+#include <vector>
#include <google/protobuf/message_lite.h>
@@ -126,6 +120,8 @@
#include <google/protobuf/descriptor.h>
+#define GOOGLE_PROTOBUF_HAS_ONEOF
+
namespace google {
namespace protobuf {
@@ -184,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
@@ -388,6 +385,26 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void ClearField(Message* message,
const FieldDescriptor* field) const = 0;
+ // 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
@@ -405,11 +422,17 @@ class LIBPROTOBUF_EXPORT Reflection {
// 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 vector<const FieldDescriptor*>& 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
@@ -502,6 +525,13 @@ 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
@@ -699,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
@@ -757,7 +787,6 @@ const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>( \
const Message& message, const FieldDescriptor* field) const; \
\
template<> \
-LIBPROTOBUF_EXPORT \
RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>( \
Message* message, const FieldDescriptor* field) const;
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 49dbe6e0..af6b301a 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -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<uint8*>(string_as_array(output) + old_size);
+ uint8* start =
+ reinterpret_cast<uint8*>(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 1ec3068c..a976e5a2 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -109,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
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index a1449c76..8b6fd6fd 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -45,7 +45,6 @@
#include <sstream>
#include <fstream>
-#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/descriptor.h>
@@ -53,6 +52,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -205,7 +205,7 @@ TEST(MessageTest, InitializationErrorString) {
EXPECT_EQ("a, b, c", message.InitializationErrorString());
}
-#ifdef PROTOBUF_HAS_DEATH_TEST
+#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet.
TEST(MessageTest, SerializeFailsIfNotInitialized) {
unittest::TestRequired message;
@@ -222,6 +222,24 @@ TEST(MessageTest, CheckInitialized) {
"fields: a, b, c");
}
+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) {
@@ -329,6 +347,61 @@ TEST(MessageTest, ParsingMerge) {
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(
diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc
index f00997c6..8993a24d 100644
--- a/src/google/protobuf/reflection_ops.cc
+++ b/src/google/protobuf/reflection_ops.cc
@@ -56,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();
diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
index 29229b5a..898c20c0 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,6 +164,24 @@ TEST(ReflectionOpsTest, MergeUnknown) {
EXPECT_EQ(2, message1.unknown_fields().field(1).varint());
}
+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) {
@@ -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<string> 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.h b/src/google/protobuf/repeated_field.h
index ff5d1f4b..1e9728ac 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -46,7 +46,6 @@
#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__
#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__
-#include <algorithm>
#include <string>
#include <iterator>
#include <google/protobuf/stubs/common.h>
@@ -72,6 +71,22 @@ static const int kMinRepeatedFieldAllocationSize = 4;
// A utility function for logging that doesn't need any template types.
void LogIndexOutOfBounds(int index, int size);
+
+template <typename Iter>
+inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) {
+ return std::distance(begin, end);
+}
+
+template <typename Iter>
+inline int CalculateReserve(Iter begin, Iter end, std::input_iterator_tag) {
+ return -1;
+}
+
+template <typename Iter>
+inline int CalculateReserve(Iter begin, Iter end) {
+ typedef typename std::iterator_traits<Iter>::iterator_category Category;
+ return CalculateReserve(begin, end, Category());
+}
} // namespace internal
@@ -90,6 +105,7 @@ class RepeatedField {
RepeatedField& operator=(const RepeatedField& other);
+ bool empty() const;
int size() const;
const Element& Get(int index) const;
@@ -121,6 +137,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();
@@ -245,6 +266,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
void Destroy();
+ bool empty() const;
int size() const;
template <typename TypeHandler>
@@ -309,8 +331,6 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
typename TypeHandler::Type* ReleaseCleared();
private:
- GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
-
static const int kInitialSize = 0;
void** elements_;
@@ -326,6 +346,8 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
static inline const typename TypeHandler::Type* cast(const void* element) {
return reinterpret_cast<const typename TypeHandler::Type*>(element);
}
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
};
template <typename GenericType>
@@ -410,6 +432,7 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
RepeatedPtrField& operator=(const RepeatedPtrField& other);
+ bool empty() const;
int size() const;
const Element& Get(int index) const;
@@ -568,8 +591,16 @@ inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
: elements_(NULL),
current_size_(0),
total_size_(kInitialSize) {
- for (; begin != end; ++begin) {
- Add(*begin);
+ int reserve = internal::CalculateReserve(begin, end);
+ if (reserve != -1) {
+ Reserve(reserve);
+ for (; begin != end; ++begin) {
+ AddAlreadyReserved(*begin);
+ }
+ } else {
+ for (; begin != end; ++begin) {
+ Add(*begin);
+ }
}
}
@@ -587,6 +618,11 @@ RepeatedField<Element>::operator=(const RepeatedField& other) {
}
template <typename Element>
+inline bool RepeatedField<Element>::empty() const {
+ return current_size_ == 0;
+}
+
+template <typename Element>
inline int RepeatedField<Element>::size() const {
return current_size_;
}
@@ -608,20 +644,33 @@ inline Element* RepeatedField<Element>::AddAlreadyReserved() {
return &elements_[current_size_++];
}
+template<typename Element>
+inline void RepeatedField<Element>::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 <typename Element>
inline const Element& RepeatedField<Element>::Get(int index) const {
+ GOOGLE_DCHECK_GE(index, 0);
GOOGLE_DCHECK_LT(index, size());
return elements_[index];
}
template <typename Element>
inline Element* RepeatedField<Element>::Mutable(int index) {
+ GOOGLE_DCHECK_GE(index, 0);
GOOGLE_DCHECK_LT(index, size());
return elements_ + index;
}
template <typename Element>
inline void RepeatedField<Element>::Set(int index, const Element& value) {
+ GOOGLE_DCHECK_GE(index, 0);
GOOGLE_DCHECK_LT(index, size());
elements_[index] = value;
}
@@ -672,6 +721,7 @@ inline void RepeatedField<Element>::Clear() {
template <typename Element>
inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
+ 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_);
@@ -681,6 +731,7 @@ inline void RepeatedField<Element>::MergeFrom(const RepeatedField& other) {
template <typename Element>
inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) {
+ if (&other == this) return;
Clear();
MergeFrom(other);
}
@@ -714,7 +765,8 @@ void RepeatedField<Element>::Swap(RepeatedField* other) {
template <typename Element>
void RepeatedField<Element>::SwapElements(int index1, int index2) {
- std::swap(elements_[index1], elements_[index2]);
+ using std::swap; // enable ADL with fallback
+ swap(elements_[index1], elements_[index2]);
}
template <typename Element>
@@ -814,6 +866,10 @@ void RepeatedPtrFieldBase::Destroy() {
delete [] elements_;
}
+inline bool RepeatedPtrFieldBase::empty() const {
+ return current_size_ == 0;
+}
+
inline int RepeatedPtrFieldBase::size() const {
return current_size_;
}
@@ -821,6 +877,7 @@ inline int RepeatedPtrFieldBase::size() const {
template <typename TypeHandler>
inline const typename TypeHandler::Type&
RepeatedPtrFieldBase::Get(int index) const {
+ GOOGLE_DCHECK_GE(index, 0);
GOOGLE_DCHECK_LT(index, size());
return *cast<TypeHandler>(elements_[index]);
}
@@ -829,6 +886,7 @@ RepeatedPtrFieldBase::Get(int index) const {
template <typename TypeHandler>
inline typename TypeHandler::Type*
RepeatedPtrFieldBase::Mutable(int index) {
+ GOOGLE_DCHECK_GE(index, 0);
GOOGLE_DCHECK_LT(index, size());
return cast<TypeHandler>(elements_[index]);
}
@@ -861,6 +919,7 @@ void RepeatedPtrFieldBase::Clear() {
template <typename TypeHandler>
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.template Get<TypeHandler>(i), Add<TypeHandler>());
@@ -869,6 +928,7 @@ inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) {
template <typename TypeHandler>
inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) {
+ if (&other == this) return;
RepeatedPtrFieldBase::Clear<TypeHandler>();
RepeatedPtrFieldBase::MergeFrom<TypeHandler>(other);
}
@@ -901,7 +961,8 @@ 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 <typename TypeHandler>
@@ -1001,7 +1062,8 @@ inline RepeatedPtrField<Element>::RepeatedPtrField() {}
template <typename Element>
inline RepeatedPtrField<Element>::RepeatedPtrField(
- const RepeatedPtrField& other) {
+ const RepeatedPtrField& other)
+ : RepeatedPtrFieldBase() {
CopyFrom(other);
}
@@ -1009,6 +1071,10 @@ template <typename Element>
template <typename Iter>
inline RepeatedPtrField<Element>::RepeatedPtrField(
Iter begin, const Iter& end) {
+ int reserve = internal::CalculateReserve(begin, end);
+ if (reserve != -1) {
+ Reserve(reserve);
+ }
for (; begin != end; ++begin) {
*Add() = *begin;
}
@@ -1028,6 +1094,11 @@ inline RepeatedPtrField<Element>& RepeatedPtrField<Element>::operator=(
}
template <typename Element>
+inline bool RepeatedPtrField<Element>::empty() const {
+ return RepeatedPtrFieldBase::empty();
+}
+
+template <typename Element>
inline int RepeatedPtrField<Element>::size() const {
return RepeatedPtrFieldBase::size();
}
@@ -1182,6 +1253,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<Element>::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;
@@ -1273,6 +1348,10 @@ class RepeatedPtrOverPtrsIterator
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<Element*>::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;
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 257701eb..334fdfc2 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -59,32 +59,38 @@ namespace {
TEST(RepeatedField, Small) {
RepeatedField<int> 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);
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);
int expected_usage = 4 * sizeof(int);
EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage);
@@ -100,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++) {
@@ -118,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);
@@ -212,6 +230,22 @@ TEST(RepeatedField, ReserveLessThanExisting) {
EXPECT_EQ(20, ReservedSpace(&field));
}
+TEST(RepeatedField, Resize) {
+ RepeatedField<int> 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<int> source, destination;
source.Add(4);
@@ -230,6 +264,14 @@ TEST(RepeatedField, MergeFrom) {
EXPECT_EQ(5, destination.Get(4));
}
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(RepeatedField, MergeFromSelf) {
+ RepeatedField<int> me;
+ me.Add(3);
+ EXPECT_DEATH(me.MergeFrom(me), "");
+}
+#endif // PROTOBUF_HAS_DEATH_TEST
+
TEST(RepeatedField, CopyFrom) {
RepeatedField<int> source, destination;
source.Add(4);
@@ -245,6 +287,14 @@ TEST(RepeatedField, CopyFrom) {
EXPECT_EQ(5, destination.Get(1));
}
+TEST(RepeatedField, CopyFromSelf) {
+ RepeatedField<int> me;
+ me.Add(3);
+ me.CopyFrom(me);
+ ASSERT_EQ(1, me.size());
+ EXPECT_EQ(3, me.Get(0));
+}
+
TEST(RepeatedField, CopyConstruct) {
RepeatedField<int> source;
source.Add(1);
@@ -379,36 +429,41 @@ TEST(RepeatedField, ExtractSubrange) {
TEST(RepeatedPtrField, Small) {
RepeatedPtrField<string> 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);
}
-
TEST(RepeatedPtrField, Large) {
RepeatedPtrField<string> field;
@@ -431,11 +486,27 @@ TEST(RepeatedPtrField, SwapSmallSmall) {
RepeatedPtrField<string> field1;
RepeatedPtrField<string> 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");
@@ -639,6 +710,14 @@ TEST(RepeatedPtrField, MergeFrom) {
EXPECT_EQ("5", destination.Get(4));
}
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST(RepeatedPtrField, MergeFromSelf) {
+ RepeatedPtrField<string> me;
+ me.Add()->assign("1");
+ EXPECT_DEATH(me.MergeFrom(me), "");
+}
+#endif // PROTOBUF_HAS_DEATH_TEST
+
TEST(RepeatedPtrField, CopyFrom) {
RepeatedPtrField<string> source, destination;
source.Add()->assign("4");
@@ -654,6 +733,14 @@ TEST(RepeatedPtrField, CopyFrom) {
EXPECT_EQ("5", destination.Get(1));
}
+TEST(RepeatedPtrField, CopyFromSelf) {
+ RepeatedPtrField<string> me;
+ me.Add()->assign("1");
+ me.CopyFrom(me);
+ ASSERT_EQ(1, me.size());
+ EXPECT_EQ("1", me.Get(0));
+}
+
TEST(RepeatedPtrField, CopyConstruct) {
RepeatedPtrField<string> source;
source.Add()->assign("1");
@@ -1007,13 +1094,13 @@ class RepeatedPtrFieldPtrsIteratorTest : public testing::Test {
TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) {
RepeatedPtrField<string>::pointer_iterator iter =
proto_array_.pointer_begin();
- (void) iter;
+ static_cast<void>(iter);
}
TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) {
RepeatedPtrField<string>::const_pointer_iterator iter =
const_proto_array_->pointer_begin();
- (void) iter;
+ static_cast<void>(iter);
}
TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) {
@@ -1122,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) {
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index c24be485..0c79fae3 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -685,6 +685,7 @@ 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
@@ -711,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))
diff --git a/src/google/protobuf/stubs/map-util.h b/src/google/protobuf/stubs/map-util.h
deleted file mode 100644
index 775848b9..00000000
--- a/src/google/protobuf/stubs/map-util.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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/map-util.h
-// Author: Anton Carver
-
-#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
-#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
-
-#include <google/protobuf/stubs/common.h>
-
-namespace google {
-namespace protobuf {
-
-// Perform a lookup in a map or hash_map.
-// If the key is present in the map then the value associated with that
-// key is returned, otherwise the value passed as a default is returned.
-template <class Collection>
-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;
-}
-
-// Perform a lookup in a map or hash_map.
-// If the key is present a const pointer to the associated value is returned,
-// otherwise a NULL pointer is returned.
-template <class Collection>
-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;
-}
-
-// Perform a lookup in a map or hash_map, assuming that the key exists.
-// Crash if it does not.
-//
-// This is intended as a replacement for operator[] as an rvalue (for reading)
-// when the key is guaranteed to exist.
-//
-// operator[] 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 <class Collection>
-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;
-}
-
-// Perform a lookup in a map or hash_map whose values are pointers.
-// If the key is present a const pointer to the associated value is returned,
-// otherwise a NULL pointer is returned.
-// This function does not distinguish between a missing key and a key mapped
-// to a NULL value.
-template <class Collection>
-const 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 0;
- }
- return it->second;
-}
-
-// Change the value associated with a particular key in a map or hash_map.
-// If the key is not present in the map the key and value are inserted,
-// otherwise the value is updated to be a copy of the value provided.
-// True indicates that an insert took place, false indicates an update.
-template <class Collection, class Key, class Value>
-bool InsertOrUpdate(Collection * const collection,
- const Key& key, const Value& value) {
- pair<typename Collection::iterator, bool> ret =
- collection->insert(typename Collection::value_type(key, value));
- if (!ret.second) {
- // update
- ret.first->second = value;
- return false;
- }
- return true;
-}
-
-// Insert a new key and value into a map or hash_map.
-// If the key is not present in the map the key and value are
-// inserted, otherwise nothing happens. True indicates that an insert
-// took place, false indicates the key was already present.
-template <class Collection, class Key, class Value>
-bool InsertIfNotPresent(Collection * const collection,
- const Key& key, const Value& value) {
- pair<typename Collection::iterator, bool> ret =
- collection->insert(typename Collection::value_type(key, value));
- return ret.second;
-}
-
-} // namespace protobuf
-} // namespace google
-
-#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h
new file mode 100644
index 00000000..fb2f5f3f
--- /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 <stddef.h>
+#include <iterator>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// Local implementation of RemoveConst to avoid including base/type_traits.h.
+template <class T> struct RemoveConst { typedef T type; };
+template <class T> struct RemoveConst<const T> : RemoveConst<T> {};
+} // 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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection, class Key, class Value>
+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 <class Collection, class Key>
+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 <class Collection, class Key, class Value>
+bool ContainsKeyValuePair(const Collection& collection,
+ const Key& key,
+ const Value& value) {
+ typedef typename Collection::const_iterator const_iterator;
+ std::pair<const_iterator, const_iterator> 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 <class Collection>
+bool InsertOrUpdate(Collection* const collection,
+ const typename Collection::value_type& vt) {
+ std::pair<typename Collection::iterator, bool> 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 <class Collection>
+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 <class Collection, class InputIterator>
+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<Key, Value*> 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 <class Collection>
+bool InsertAndDeleteExisting(
+ Collection* const collection,
+ const typename Collection::value_type::first_type& key,
+ const typename Collection::value_type::second_type& value) {
+ std::pair<typename Collection::iterator, bool> 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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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 <class Collection>
+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<int, SomeProto> m;
+// SomeProto& proto = InsertKeyOrDie(&m, 3);
+// proto.set_field("foo");
+template <class Collection>
+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<typename Collection::iterator, bool> 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 <class Collection>
+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 <class Collection>
+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<string> v = {"a", "b", "c", "a", "b"};
+// map<string, int> m;
+// AddTokenCounts(v, 1, &m);
+// assert(m["a"] == 2);
+// assert(m["b"] == 2);
+// assert(m["c"] == 1);
+template <typename Sequence, typename Collection>
+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<Key, Value*>, where
+// inserting a new key, value pair involves constructing a new heap-allocated
+// Value, and storing a pointer to that in the collection.
+template <class Collection>
+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<typename Collection::iterator, bool> ret =
+ collection->insert(typename Collection::value_type(
+ key,
+ static_cast<typename Collection::value_type::second_type>(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 <class Collection, class Arg>
+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<typename Collection::iterator, bool> ret =
+ collection->insert(typename Collection::value_type(
+ key,
+ static_cast<typename Collection::value_type::second_type>(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 <class Collection>
+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<typename Collection::iterator, bool> 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 <class Collection, class Arg>
+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<typename Collection::iterator, bool> 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 <class Collection>
+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<typename Collection::iterator, bool> 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 <class Collection, class Arg>
+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<typename Collection::iterator, bool> 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 <class Collection>
+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<typename Collection::iterator, bool> 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 <class Collection>
+bool UpdateReturnCopy(Collection* const collection,
+ const typename Collection::value_type& vt,
+ typename Collection::value_type::second_type* previous) {
+ std::pair<typename Collection::iterator, bool> 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 <class Collection>
+typename Collection::value_type::second_type* const
+InsertOrReturnExisting(Collection* const collection,
+ const typename Collection::value_type& vt) {
+ std::pair<typename Collection::iterator, bool> 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 <class Collection>
+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<string, MyType*> my_map;
+//
+// One line cleanup:
+// delete EraseKeyReturnValuePtr(&my_map, "abc");
+//
+// Use returned value:
+// scoped_ptr<MyType> value_ptr(EraseKeyReturnValuePtr(&my_map, "abc"));
+// if (value_ptr.get())
+// value_ptr->DoSomething();
+//
+template <class Collection>
+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 <class MapContainer, class KeyContainer>
+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 <class MapContainer, class KeyContainer>
+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 <class MapContainer, class KeyType>
+void AppendKeysFromMap(const MapContainer& map_container,
+ vector<KeyType>* 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 <class MapContainer, class ValueContainer>
+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 <class MapContainer, class ValueType>
+void AppendValuesFromMap(const MapContainer& map_container,
+ vector<ValueType>* 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.h b/src/google/protobuf/stubs/once.h
index 7fbc117f..86a4c01f 100644
--- a/src/google/protobuf/stubs/once.h
+++ b/src/google/protobuf/stubs/once.h
@@ -139,6 +139,24 @@ inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*),
#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<typename T>
+ void Init(void (*func_with_arg)(T*), T* arg) {
+ GoogleOnceInit<T>(&this->state_,
+ func_with_arg,
+ arg);
+ }
+ private:
+ ProtobufOnceType state_;
+};
+
#define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \
::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 917b3e9f..814d1b91 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -596,6 +596,120 @@ uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) {
return static_cast<uint32>(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<int32>::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<unsigned char>(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<int32>::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<unsigned char>(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()
@@ -1143,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<char*>(
- 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 a401c63a..20cea2d2 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
@@ -181,6 +188,21 @@ LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full,
vector<string>* result);
// ----------------------------------------------------------------------
+// Split()
+// Split a string using a character delimiter.
+// ----------------------------------------------------------------------
+inline vector<string> Split(
+ const string& full, const char* delim, bool skip_empty = true) {
+ vector<string> 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
// the C-string "delim" as a separator between components. There are two
@@ -327,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()
@@ -454,12 +485,76 @@ 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);
+}
+
+inline string ToString(string a) {
+ return a;
+}
+} // namespace internal
+
+// ----------------------------------------------------------------------
+// StrCat()
+// These methods join some strings together.
// ----------------------------------------------------------------------
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+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 <typename T1, typename T2, typename T3, typename T4>
+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 <typename T1, typename T2, typename T3>
+string StrCat(const T1& a, const T2& b, const T3& c) {
+ return internal::ToString(a) + internal::ToString(b) +
+ internal::ToString(c);
+}
+
+template <typename T1, typename T2>
+string StrCat(const T1& a, const T2& b) {
+ return internal::ToString(a) + internal::ToString(b);
+}
-LIBPROTOBUF_EXPORT double NoLocaleStrtod(const char* text, char** endptr);
+// ----------------------------------------------------------------------
+// Join()
+// These methods concatenate a range of components into a C++ string, using
+// the C-string "delim" as a separator between components.
+// ----------------------------------------------------------------------
+template <typename Iterator>
+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 <typename Range>
+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
diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc
index b9c9253b..fde54f05 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/test_util.cc b/src/google/protobuf/test_util.cc
index a9666fe4..f3cf7a9a 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -54,6 +54,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) {
AddRepeatedFields1(message);
AddRepeatedFields2(message);
SetDefaultFields(message);
+ SetOneofFields(message);
}
void TestUtil::SetOptionalFields(unittest::TestAllTypes* message) {
@@ -255,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) {
@@ -454,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());
}
// -------------------------------------------------------------------
@@ -600,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 ());
}
// -------------------------------------------------------------------
@@ -1078,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");
}
// -------------------------------------------------------------------
@@ -1331,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));
}
// -------------------------------------------------------------------
@@ -1489,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));
}
// -------------------------------------------------------------------
@@ -1765,6 +1810,57 @@ void TestUtil::ExpectPackedExtensionsModified(
// -------------------------------------------------------------------
+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.
@@ -2119,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(
@@ -2335,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(
@@ -2473,6 +2718,20 @@ 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(
@@ -3013,6 +3272,45 @@ void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) {
}
}
+void TestUtil::ReflectionTester::
+SetAllocatedOptionalMessageFieldsToNullViaReflection(
+ Message* message) {
+ const Reflection* reflection = message->GetReflection();
+
+ vector<const FieldDescriptor*> 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<const FieldDescriptor*> 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) {
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index 45519573..6e2d552a 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -54,11 +54,15 @@ class TestUtil {
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
@@ -79,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().
@@ -97,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
@@ -119,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:
@@ -143,6 +155,11 @@ class TestUtil {
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,
@@ -152,6 +169,11 @@ class TestUtil {
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);
diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc
index 9099292a..cbf808be 100644
--- a/src/google/protobuf/test_util_lite.cc
+++ b/src/google/protobuf/test_util_lite.cc
@@ -153,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");
}
// -------------------------------------------------------------------
@@ -378,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());
}
// -------------------------------------------------------------------
@@ -518,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 ());
}
// -------------------------------------------------------------------
@@ -900,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");
}
// -------------------------------------------------------------------
@@ -1126,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));
}
// -------------------------------------------------------------------
@@ -1274,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));
}
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/testdata/bad_utf8_string b/src/google/protobuf/testdata/bad_utf8_string
new file mode 100644
index 00000000..a1337ec6
--- /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 4dd62cd3..0b7e6552 100644
--- a/src/google/protobuf/testdata/golden_message
+++ b/src/google/protobuf/testdata/golden_message
Binary files 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 00000000..b48c8985
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message_oneof_implemented
Binary files differ
diff --git a/src/google/protobuf/testdata/text_format_unittest_data.txt b/src/google/protobuf/testdata/text_format_unittest_data.txt
index bbe58826..7a874b54 100644
--- a/src/google/protobuf/testdata/text_format_unittest_data.txt
+++ b/src/google/protobuf/testdata/text_format_unittest_data.txt
@@ -126,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 00000000..ec95e1e8
--- /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 00000000..e1011ebf
--- /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_extensions_data.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
index 0a217f02..8c8b1eb4 100644
--- a/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
+++ b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
@@ -126,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 00000000..132f7445
--- /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 e224781d..9a5b35e8 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 a6b1c764..91ecce92 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/text_format.cc b/src/google/protobuf/text_format.cc
index b2ea7ee8..3ecb110f 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <algorithm>
#include <float.h>
#include <math.h>
#include <stdio.h>
@@ -42,6 +43,7 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -49,12 +51,26 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/map-util.h>
+#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
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;
@@ -177,9 +193,10 @@ TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested(
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
@@ -191,7 +208,11 @@ class TextFormat::Parser::ParserImpl {
TextFormat::Finder* finder,
ParseInfoTree* parse_info_tree,
SingularOverwritePolicy singular_overwrite_policy,
- bool allow_unknown_field)
+ 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),
@@ -199,7 +220,10 @@ class TextFormat::Parser::ParserImpl {
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.
@@ -208,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();
}
@@ -219,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_;
}
@@ -304,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) {
@@ -346,23 +376,38 @@ class TextFormat::Parser::ParserImpl {
} 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) {
@@ -393,33 +438,53 @@ class TextFormat::Parser::ParserImpl {
}
}
- // 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;
+ 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->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 {
- 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
@@ -595,9 +660,9 @@ class TextFormat::Parser::ParserImpl {
} else {
string value;
DO(ConsumeIdentifier(&value));
- if (value == "true" || value == "t") {
+ if (value == "true" || value == "True" || value == "t") {
SET_FIELD(Bool, true);
- } else if (value == "false" || value == "f") {
+ } else if (value == "false" || value == "False" || value == "f") {
SET_FIELD(Bool, false);
} else {
ReportError("Invalid value for boolean field \"" + field->name()
@@ -630,9 +695,15 @@ class TextFormat::Parser::ParserImpl {
}
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);
@@ -717,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.
@@ -792,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
@@ -809,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<double>(integer_value);
} else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) {
@@ -879,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);
@@ -901,7 +1003,10 @@ class TextFormat::Parser::ParserImpl {
io::Tokenizer tokenizer_;
const Descriptor* root_message_type_;
SingularOverwritePolicy singular_overwrite_policy_;
- bool allow_unknown_field_;
+ const bool allow_case_insensitive_field_;
+ const bool allow_unknown_field_;
+ const bool allow_unknown_enum_;
+ const bool allow_field_number_;
bool had_errors_;
};
@@ -1039,7 +1144,12 @@ TextFormat::Parser::Parser()
finder_(NULL),
parse_info_tree_(NULL),
allow_partial_(false),
- allow_unknown_field_(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() {}
@@ -1047,10 +1157,18 @@ 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_,
finder_, parse_info_tree_,
- ParserImpl::FORBID_SINGULAR_OVERWRITES,
- allow_unknown_field_);
+ overwrites_policy,
+ allow_case_insensitive_field_, allow_unknown_field_,
+ allow_unknown_enum_, allow_field_number_,
+ allow_relaxed_whitespace_);
return MergeUsingImpl(input, output, &parser);
}
@@ -1065,7 +1183,9 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
ParserImpl parser(output->GetDescriptor(), input, error_collector_,
finder_, parse_info_tree_,
ParserImpl::ALLOW_SINGULAR_OVERWRITES,
- allow_unknown_field_);
+ allow_case_insensitive_field_, allow_unknown_field_,
+ allow_unknown_enum_, allow_field_number_,
+ allow_relaxed_whitespace_);
return MergeUsingImpl(input, output, &parser);
}
@@ -1083,7 +1203,7 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */,
vector<string> 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;
@@ -1097,7 +1217,9 @@ bool TextFormat::Parser::ParseFieldValueFromString(
ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_,
finder_, parse_info_tree_,
ParserImpl::ALLOW_SINGULAR_OVERWRITES,
- allow_unknown_field_);
+ allow_case_insensitive_field_, allow_unknown_field_,
+ allow_unknown_enum_, allow_field_number_,
+ allow_relaxed_whitespace_);
return parser.ParseField(field, output);
}
@@ -1123,13 +1245,124 @@ 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) const {
@@ -1138,9 +1371,7 @@ bool TextFormat::Printer::PrintToString(const Message& message,
output->clear();
io::StringOutputStream output_stream(output);
- bool result = Print(message, &output_stream);
-
- return result;
+ return Print(message, &output_stream);
}
bool TextFormat::Printer::PrintUnknownFieldsToString(
@@ -1174,15 +1405,30 @@ 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) const {
const Reflection* reflection = message.GetReflection();
vector<const FieldDescriptor*> 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(
@@ -1221,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 {
@@ -1280,30 +1521,20 @@ void TextFormat::Printer::PrintShortRepeatedField(
}
}
-void TextFormat::Printer::PrintFieldName(const Message& /* message */,
- const Reflection* /* reflection */,
+void TextFormat::Printer::PrintFieldName(const Message& message,
+ const Reflection* reflection,
const FieldDescriptor* field,
TextGenerator& generator) const {
- 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());
- }
+ // 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(
@@ -1315,62 +1546,56 @@ void TextFormat::Printer::PrintFieldValue(
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;
}
}
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 01f3ffb0..b4cba1db 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -39,11 +39,13 @@
#define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
#include <map>
+#include <memory>
#include <string>
#include <vector>
+
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
namespace google {
namespace protobuf {
@@ -85,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 {
@@ -120,6 +157,15 @@ 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
@@ -132,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).
@@ -184,9 +260,18 @@ class LIBPROTOBUF_EXPORT TextFormat {
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<const FieldValuePrinter> default_field_value_printer_;
+ typedef map<const FieldDescriptor*,
+ const FieldValuePrinter*> CustomPrinterMap;
+ CustomPrinterMap custom_printers_;
};
// Parses a text-format protocol message from the given input stream to
@@ -314,12 +399,24 @@ class LIBPROTOBUF_EXPORT TextFormat {
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).
@@ -335,9 +432,15 @@ class LIBPROTOBUF_EXPORT TextFormat {
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
@@ -358,6 +461,7 @@ inline void TextFormat::RecordLocation(ParseInfoTree* info_tree,
info_tree->RecordLocation(field, location);
}
+
inline TextFormat::ParseInfoTree* TextFormat::CreateNested(
ParseInfoTree* info_tree, const FieldDescriptor* field) {
return info_tree->CreateNested(field);
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 304fb844..b3cf7b8e 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.
@@ -354,6 +388,146 @@ TEST_F(TextFormatTest, PrintBufferTooSmall) {
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());
@@ -449,7 +623,11 @@ TEST_F(TextFormatTest, ParseShortRepeatedForm) {
" 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_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_));
@@ -466,8 +644,17 @@ TEST_F(TextFormatTest, ParseShortRepeatedForm) {
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.
@@ -720,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,
@@ -738,7 +946,8 @@ 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_);
}
@@ -927,11 +1136,14 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) {
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");
@@ -948,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\"");
@@ -1010,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);
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 6eb2d86f..969684fd 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -69,6 +69,7 @@ message TestAllTypes {
FOO = 1;
BAR = 2;
BAZ = 3;
+ NEG = -1; // Intentionally negative.
}
// Singular
@@ -167,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 {
@@ -294,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 {
@@ -301,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;
}
}
@@ -435,6 +459,7 @@ 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;
@@ -535,6 +560,7 @@ message TestExtremeDefaultValues {
default="ab\000c"];
optional string cord_with_zero = 26 [ctype=CORD,
default="12\0003"];
+ optional string replacement_string = 27 [default="${unknown}"];
}
message SparseEnumMessage {
@@ -558,6 +584,100 @@ 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
@@ -618,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.
@@ -717,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 e591d294..52ee6c71 100644
--- a/src/google/protobuf/unittest_custom_options.proto
+++ b/src/google/protobuf/unittest_custom_options.proto
@@ -218,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;
}
@@ -235,6 +236,7 @@ message ComplexOptionType2 {
}
optional ComplexOptionType4 fred = 3;
+ repeated ComplexOptionType4 barney = 4;
extensions 100 to max;
}
@@ -271,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;
@@ -281,6 +285,8 @@ 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;
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index a1764aac..ffff012f 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -151,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 {
@@ -293,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 {
@@ -358,3 +372,13 @@ message TestParsingMergeLite {
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 3497f09f..1d325592 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 cffb4122..a414220a 100644
--- a/src/google/protobuf/unittest_no_generic_services.proto
+++ b/src/google/protobuf/unittest_no_generic_services.proto
@@ -32,6 +32,7 @@
package google.protobuf.no_generic_services_test;
+
// *_generic_services are false by default.
message TestMessage {
diff --git a/src/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto
index feecbef8..541d47fe 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 841433d5..c0356af6 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -45,7 +45,7 @@ namespace google {
namespace protobuf {
UnknownFieldSet::UnknownFieldSet()
- : fields_(NULL) {}
+ : fields_(NULL) {}
UnknownFieldSet::~UnknownFieldSet() {
Clear();
@@ -104,7 +104,7 @@ void UnknownFieldSet::AddVarint(int number, uint64 value) {
if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
- field.type_ = UnknownField::TYPE_VARINT;
+ field.SetType(UnknownField::TYPE_VARINT);
field.varint_ = value;
fields_->push_back(field);
}
@@ -113,7 +113,7 @@ void UnknownFieldSet::AddFixed32(int number, uint32 value) {
if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
- field.type_ = UnknownField::TYPE_FIXED32;
+ field.SetType(UnknownField::TYPE_FIXED32);
field.fixed32_ = value;
fields_->push_back(field);
}
@@ -122,7 +122,7 @@ void UnknownFieldSet::AddFixed64(int number, uint64 value) {
if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
- field.type_ = UnknownField::TYPE_FIXED64;
+ field.SetType(UnknownField::TYPE_FIXED64);
field.fixed64_ = value;
fields_->push_back(field);
}
@@ -131,7 +131,7 @@ string* UnknownFieldSet::AddLengthDelimited(int number) {
if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
- field.type_ = UnknownField::TYPE_LENGTH_DELIMITED;
+ field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
field.length_delimited_.string_value_ = new string;
fields_->push_back(field);
return field.length_delimited_.string_value_;
@@ -142,7 +142,7 @@ UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
if (fields_ == NULL) fields_ = new vector<UnknownField>;
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_;
@@ -188,10 +188,9 @@ void UnknownFieldSet::DeleteByNumber(int number) {
}
bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
-
UnknownFieldSet other;
if (internal::WireFormat::SkipMessage(input, &other) &&
- input->ConsumedEntireMessage()) {
+ input->ConsumedEntireMessage()) {
MergeFrom(other);
return true;
} else {
@@ -206,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) {
@@ -248,14 +247,14 @@ void UnknownField::DeepCopy() {
void UnknownField::SerializeLengthDelimitedNoTag(
io::CodedOutputStream* output) const {
- GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+ GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type());
const string& data = *length_delimited_.string_value_;
output->WriteVarint32(data.size());
- output->WriteString(data);
+ output->WriteRawMaybeAliased(data.data(), data.size());
}
uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const {
- GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+ 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);
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 825bba83..efaf78a5 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -42,7 +42,6 @@
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
-// TODO(jasonh): some people seem to rely on protobufs to include this for them!
namespace google {
namespace protobuf {
@@ -53,7 +52,7 @@ namespace protobuf {
}
namespace internal {
class WireFormat; // wire_format.h
- class UnknownFieldSetFieldSkipperUsingCord;
+ class MessageSetFieldSkipperUsingCord;
// extension_set_heavy.cc
}
@@ -202,9 +201,12 @@ class LIBPROTOBUF_EXPORT UnknownField {
// Make a deep copy of any pointers in this UnknownField.
void DeepCopy();
+ // Set the wire type of this UnknownField. Should only be used when this
+ // UnknownField is being created.
+ inline void SetType(Type type);
- unsigned int number_ : 29;
- unsigned int type_ : 3;
+ uint32 number_;
+ uint32 type_;
union {
uint64 varint_;
uint32 fixed32_;
@@ -254,57 +256,62 @@ inline UnknownField::Type UnknownField::type() const {
return static_cast<Type>(type_);
}
-inline uint64 UnknownField::varint () const {
- assert(type_ == TYPE_VARINT);
+inline uint64 UnknownField::varint() const {
+ assert(type() == TYPE_VARINT);
return varint_;
}
inline uint32 UnknownField::fixed32() const {
- assert(type_ == TYPE_FIXED32);
+ assert(type() == TYPE_FIXED32);
return fixed32_;
}
inline uint64 UnknownField::fixed64() const {
- assert(type_ == TYPE_FIXED64);
+ assert(type() == TYPE_FIXED64);
return fixed64_;
}
inline const string& UnknownField::length_delimited() const {
- assert(type_ == TYPE_LENGTH_DELIMITED);
+ assert(type() == TYPE_LENGTH_DELIMITED);
return *length_delimited_.string_value_;
}
inline const UnknownFieldSet& UnknownField::group() const {
- assert(type_ == TYPE_GROUP);
+ assert(type() == TYPE_GROUP);
return *group_;
}
inline void UnknownField::set_varint(uint64 value) {
- assert(type_ == TYPE_VARINT);
+ assert(type() == TYPE_VARINT);
varint_ = value;
}
inline void UnknownField::set_fixed32(uint32 value) {
- assert(type_ == TYPE_FIXED32);
+ assert(type() == TYPE_FIXED32);
fixed32_ = value;
}
inline void UnknownField::set_fixed64(uint64 value) {
- assert(type_ == TYPE_FIXED64);
+ assert(type() == TYPE_FIXED64);
fixed64_ = value;
}
inline void UnknownField::set_length_delimited(const string& value) {
- assert(type_ == TYPE_LENGTH_DELIMITED);
+ assert(type() == TYPE_LENGTH_DELIMITED);
length_delimited_.string_value_->assign(value);
}
inline string* UnknownField::mutable_length_delimited() {
- assert(type_ == TYPE_LENGTH_DELIMITED);
+ assert(type() == TYPE_LENGTH_DELIMITED);
return length_delimited_.string_value_;
}
inline UnknownFieldSet* UnknownField::mutable_group() {
- assert(type_ == TYPE_GROUP);
+ assert(type() == TYPE_GROUP);
return group_;
}
inline int UnknownField::GetLengthDelimitedSize() const {
- GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_);
+ 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 c6b8769f..8e9bc842 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -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());
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index ead763b1..91892897 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.pb.h>
@@ -182,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(),
@@ -411,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
@@ -562,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 {
@@ -626,10 +660,7 @@ 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.
@@ -647,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()) {
@@ -657,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();
@@ -668,7 +698,7 @@ 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;
@@ -680,7 +710,8 @@ bool WireFormat::ParseAndMergeMessageSetItem(
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;
}
}
@@ -828,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;
}
@@ -1038,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) {
@@ -1050,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) << "String field contains invalid UTF-8 data when "
- << operation_str
- << " a protocol buffer. Use the 'bytes' type if you intend to "
- "send 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 6cc90029..0c05c0d8 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -79,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);
@@ -180,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,
@@ -228,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);
@@ -293,13 +313,21 @@ 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
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 0a3357b1..d65844dc 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -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);
@@ -186,6 +264,21 @@ void FieldSkipper::SkipUnknownEnum(
// 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<int>* values) {
@@ -285,6 +378,15 @@ void WireFormatLite::WriteString(int field_number, const string& value,
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);
@@ -292,6 +394,14 @@ void WireFormatLite::WriteBytes(int field_number, const string& value,
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 cb4fc918..4b6b53e7 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -163,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
@@ -340,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);
@@ -490,6 +505,12 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
google::protobuf::io::CodedInputStream* input,
RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
+ template <typename CType, enum FieldType DeclaredType>
+ static inline bool ReadPackedFixedSizePrimitive(
+ google::protobuf::io::CodedInputStream* input,
+ RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
static const CppType kFieldTypeToCppTypeMap[];
static const WireFormatLite::WireType kWireTypeForFieldType[];
@@ -518,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 641cc92f..ba9f9ce3 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -150,8 +150,8 @@ template <>
inline bool WireFormatLite::ReadPrimitive<bool, WireFormatLite::TYPE_BOOL>(
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;
}
@@ -221,10 +221,11 @@ inline const uint8* WireFormatLite::ReadPrimitiveFromArray<
}
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
-inline bool WireFormatLite::ReadRepeatedPrimitive(int, // tag_size, unused.
- uint32 tag,
- io::CodedInputStream* input,
- RepeatedField<CType>* values) {
+inline bool WireFormatLite::ReadRepeatedPrimitive(
+ int, // tag_size, unused.
+ uint32 tag,
+ io::CodedInputStream* input,
+ RepeatedField<CType>* values) {
CType value;
if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false;
values->Add(value);
@@ -284,7 +285,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 <> \
@@ -334,6 +335,86 @@ inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input,
}
template <typename CType, enum WireFormatLite::FieldType DeclaredType>
+inline bool WireFormatLite::ReadPackedFixedSizePrimitive(
+ io::CodedInputStream* input, RepeatedField<CType>* 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<int64>(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<void*>(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<CType, DeclaredType>(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<CType, DeclaredType>(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<CPPTYPE>* 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 <typename CType, enum WireFormatLite::FieldType DeclaredType>
bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
RepeatedField<CType>* values) {
return ReadPackedPrimitive<CType, DeclaredType>(input, values);
@@ -660,15 +741,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);
}
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 9822828b..3a44aaf7 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -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;
@@ -687,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<bool>(data), msg2.data());
+
+ // Test int64 is compatible with uint64
+ unittest::Uint64Message msg3;
+ ASSERT_TRUE(msg3.ParseFromString(serialized));
+ ASSERT_EQ(static_cast<uint64>(data), msg3.data());
+
+ // Test int64 is compatible with int32
+ unittest::Int32Message msg4;
+ ASSERT_TRUE(msg4.ParseFromString(serialized));
+ ASSERT_EQ(static_cast<int32>(data), msg4.data());
+
+ // Test int64 is compatible with uint32
+ unittest::Uint32Message msg5;
+ ASSERT_TRUE(msg5.ParseFromString(serialized));
+ ASSERT_EQ(static_cast<uint32>(data), msg5.data());
+}
+
class WireFormatInvalidInputTest : public testing::Test {
protected:
// Make a serialized TestAllTypes in which the field optional_nested_message
@@ -852,7 +959,16 @@ bool StartsWith(const string& s, const string& prefix) {
return s.substr(0, prefix.length()) == prefix;
}
-TEST(Utf8ValidationTest, WriteInvalidUTF8String) {
+class Utf8ValidationTest : public ::testing::Test {
+ protected:
+ Utf8ValidationTest() {}
+ virtual ~Utf8ValidationTest() {}
+ virtual void SetUp() {
+ }
+
+};
+
+TEST_F(Utf8ValidationTest, WriteInvalidUTF8String) {
string wire_buffer;
protobuf_unittest::OneString input;
vector<string> errors;
@@ -864,7 +980,7 @@ TEST(Utf8ValidationTest, WriteInvalidUTF8String) {
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
ASSERT_EQ(1, errors.size());
EXPECT_TRUE(StartsWith(errors[0],
- "String field contains invalid UTF-8 data when "
+ "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
@@ -872,7 +988,8 @@ TEST(Utf8ValidationTest, WriteInvalidUTF8String) {
#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);
@@ -886,7 +1003,7 @@ TEST(Utf8ValidationTest, ReadInvalidUTF8String) {
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
ASSERT_EQ(1, errors.size());
EXPECT_TRUE(StartsWith(errors[0],
- "String field contains invalid UTF-8 data when "
+ "String field 'data' contains invalid UTF-8 data when "
"parsing a protocol buffer. Use the "
"'bytes' type if you intend to send raw bytes."));
@@ -895,7 +1012,8 @@ TEST(Utf8ValidationTest, ReadInvalidUTF8String) {
#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
}
-TEST(Utf8ValidationTest, WriteValidUTF8String) {
+
+TEST_F(Utf8ValidationTest, WriteValidUTF8String) {
string wire_buffer;
protobuf_unittest::OneString input;
vector<string> errors;
@@ -907,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);
@@ -923,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<string> errors;
@@ -935,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);
@@ -950,7 +1068,7 @@ TEST(Utf8ValidationTest, ReadArbitraryBytes) {
EXPECT_EQ(input.data(), output.data());
}
-TEST(Utf8ValidationTest, ParseRepeatedString) {
+TEST_F(Utf8ValidationTest, ParseRepeatedString) {
protobuf_unittest::MoreBytes input;
input.add_data(kValidUTF8String);
input.add_data(kInvalidUTF8String);
@@ -972,6 +1090,30 @@ TEST(Utf8ValidationTest, ParseRepeatedString) {
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<string> 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