aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFeng Xiao <xfxyjwf@gmail.com>2014-11-10 17:34:54 -0800
committerFeng Xiao <xfxyjwf@gmail.com>2014-11-10 17:34:54 -0800
commit6ef984af4b0c63c1c33127a12dcfc8e6359f0c9e (patch)
treed17c61ff9f3ae28224fbddac6d26bfc59e2cf755
parentbaca1a8a1aa180c42de6278d3b8286c4496c6a10 (diff)
downloadprotobuf-6ef984af4b0c63c1c33127a12dcfc8e6359f0c9e.tar.gz
protobuf-6ef984af4b0c63c1c33127a12dcfc8e6359f0c9e.tar.bz2
protobuf-6ef984af4b0c63c1c33127a12dcfc8e6359f0c9e.zip
Down-integrate from internal code base.
-rw-r--r--Makefile.am25
-rw-r--r--java/pom.xml29
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java60
-rw-r--r--java/src/main/java/com/google/protobuf/CodedInputStream.java30
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java115
-rw-r--r--java/src/main/java/com/google/protobuf/DynamicMessage.java27
-rw-r--r--java/src/main/java/com/google/protobuf/Extension.java23
-rw-r--r--java/src/main/java/com/google/protobuf/ExtensionLite.java63
-rw-r--r--java/src/main/java/com/google/protobuf/FieldSet.java4
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java364
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java319
-rw-r--r--java/src/main/java/com/google/protobuf/Internal.java166
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringArrayList.java4
-rw-r--r--java/src/main/java/com/google/protobuf/LiteralByteString.java9
-rw-r--r--java/src/main/java/com/google/protobuf/MapEntry.java433
-rw-r--r--java/src/main/java/com/google/protobuf/MapEntryLite.java331
-rw-r--r--java/src/main/java/com/google/protobuf/MapField.java259
-rw-r--r--java/src/main/java/com/google/protobuf/MapFieldLite.java182
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java19
-rw-r--r--java/src/main/java/com/google/protobuf/MessageReflection.java33
-rw-r--r--java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java24
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java14
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSet.java15
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java297
-rw-r--r--java/src/test/java/com/google/protobuf/CodedInputStreamTest.java10
-rw-r--r--java/src/test/java/com/google/protobuf/DescriptorsTest.java6
-rw-r--r--java/src/test/java/com/google/protobuf/FieldPresenceTest.java363
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java141
-rw-r--r--java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java31
-rw-r--r--java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java23
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java277
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2Test.java488
-rw-r--r--java/src/test/java/com/google/protobuf/MapTest.java569
-rw-r--r--java/src/test/java/com/google/protobuf/TestBadIdentifiers.java2
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java15
-rw-r--r--java/src/test/java/com/google/protobuf/UnknownEnumValueTest.java255
-rw-r--r--java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java317
-rw-r--r--java/src/test/java/com/google/protobuf/field_presence_test.proto93
-rw-r--r--java/src/test/java/com/google/protobuf/lazy_fields_lite.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto17
-rw-r--r--java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto63
-rw-r--r--java/src/test/java/com/google/protobuf/map_for_proto2_test.proto62
-rw-r--r--java/src/test/java/com/google/protobuf/map_test.proto63
-rw-r--r--java/src/test/java/com/google/protobuf/multiple_files_test.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/nested_builders_test.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/nested_extension.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/nested_extension_lite.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/non_nested_extension_lite.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/outer_class_name_test.proto2
-rw-r--r--java/src/test/java/com/google/protobuf/outer_class_name_test2.proto2
-rw-r--r--java/src/test/java/com/google/protobuf/outer_class_name_test3.proto2
-rw-r--r--java/src/test/java/com/google/protobuf/test_bad_identifiers.proto24
-rw-r--r--java/src/test/java/com/google/protobuf/test_check_utf8.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/test_check_utf8_size.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/test_custom_options.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/test_extra_interfaces.proto1
-rwxr-xr-xpython/google/protobuf/descriptor.py5
-rw-r--r--python/google/protobuf/descriptor_database.py4
-rw-r--r--python/google/protobuf/descriptor_pool.py2
-rw-r--r--python/google/protobuf/internal/descriptor_database_test.py2
-rw-r--r--python/google/protobuf/internal/descriptor_pool_test.py29
-rw-r--r--python/google/protobuf/internal/descriptor_pool_test1.proto2
-rw-r--r--python/google/protobuf/internal/descriptor_pool_test2.proto2
-rwxr-xr-xpython/google/protobuf/internal/descriptor_test.py10
-rw-r--r--python/google/protobuf/internal/factory_test1.proto1
-rw-r--r--python/google/protobuf/internal/factory_test2.proto7
-rwxr-xr-xpython/google/protobuf/internal/generator_test.py4
-rw-r--r--python/google/protobuf/internal/import_test_package/BUILD27
-rw-r--r--python/google/protobuf/internal/import_test_package/__init__.py33
-rw-r--r--python/google/protobuf/internal/import_test_package/inner.proto37
-rw-r--r--python/google/protobuf/internal/import_test_package/outer.proto39
-rwxr-xr-xpython/google/protobuf/internal/message_test.py40
-rw-r--r--python/google/protobuf/internal/missing_enum_values.proto2
-rw-r--r--python/google/protobuf/internal/more_extensions.proto1
-rw-r--r--python/google/protobuf/internal/more_extensions_dynamic.proto1
-rw-r--r--python/google/protobuf/internal/more_messages.proto1
-rw-r--r--python/google/protobuf/internal/proto_builder_test.py77
-rwxr-xr-xpython/google/protobuf/internal/python_message.py24
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py59
-rw-r--r--python/google/protobuf/internal/test_bad_identifiers.proto7
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py21
-rwxr-xr-xpython/google/protobuf/internal/type_checkers.py9
-rwxr-xr-xpython/google/protobuf/internal/unknown_fields_test.py9
-rwxr-xr-xpython/google/protobuf/message.py15
-rw-r--r--python/google/protobuf/proto_builder.py98
-rw-r--r--python/google/protobuf/pyext/cpp_message.py6
-rw-r--r--python/google/protobuf/pyext/descriptor.cc222
-rw-r--r--python/google/protobuf/pyext/descriptor.h70
-rw-r--r--python/google/protobuf/pyext/extension_dict.cc110
-rw-r--r--python/google/protobuf/pyext/extension_dict.h22
-rw-r--r--python/google/protobuf/pyext/message.cc495
-rw-r--r--python/google/protobuf/pyext/message.h45
-rw-r--r--python/google/protobuf/pyext/proto2_api_test.proto2
-rw-r--r--python/google/protobuf/pyext/python.proto2
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc135
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.h13
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.cc102
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.h12
-rw-r--r--python/google/protobuf/pyext/scoped_pyobject_ptr.h2
-rwxr-xr-xpython/google/protobuf/text_format.py8
-rwxr-xr-xpython/setup.py3
-rw-r--r--src/Makefile.am85
-rw-r--r--src/google/protobuf/arena.cc238
-rw-r--r--src/google/protobuf/arena.h479
-rw-r--r--src/google/protobuf/arena_nc.cc45
-rw-r--r--src/google/protobuf/arena_nc_test.py59
-rw-r--r--src/google/protobuf/arena_unittest.cc972
-rw-r--r--src/google/protobuf/arenastring.cc43
-rwxr-xr-xsrc/google/protobuf/arenastring.h314
-rw-r--r--src/google/protobuf/arenastring_unittest.cc112
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc3
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc13
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc118
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc17
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h13
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc17
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h33
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc1014
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc369
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc128
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc538
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto20
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/importer.cc3
-rw-r--r--src/google/protobuf/compiler/importer_unittest.cc124
-rw-r--r--src/google/protobuf/compiler/java/java_context.h3
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc32
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc354
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_field.h3
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc27
-rw-r--r--src/google/protobuf/compiler/java/java_file.h3
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc7
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc20
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h26
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc455
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.h82
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc399
-rw-r--r--src/google/protobuf/compiler/java/java_message.h1
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc54
-rw-r--r--src/google/protobuf/compiler/java/java_plugin_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc20
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc6
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.h4
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc27
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc3
-rw-r--r--src/google/protobuf/compiler/parser.cc149
-rw-r--r--src/google/protobuf/compiler/parser.h24
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc251
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc333
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h455
-rw-r--r--src/google/protobuf/compiler/plugin.proto1
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc116
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h3
-rw-r--r--src/google/protobuf/compiler/python/python_plugin_unittest.cc3
-rw-r--r--src/google/protobuf/descriptor.cc719
-rw-r--r--src/google/protobuf/descriptor.h117
-rw-r--r--src/google/protobuf/descriptor.pb.cc2490
-rw-r--r--src/google/protobuf/descriptor.pb.h2974
-rw-r--r--src/google/protobuf/descriptor.proto51
-rw-r--r--src/google/protobuf/descriptor_pb2_test.py6
-rw-r--r--src/google/protobuf/descriptor_unittest.cc581
-rw-r--r--src/google/protobuf/drop_unknown_fields_test.cc88
-rw-r--r--src/google/protobuf/dynamic_message.cc79
-rw-r--r--src/google/protobuf/dynamic_message.h3
-rw-r--r--src/google/protobuf/dynamic_message_unittest.cc8
-rw-r--r--src/google/protobuf/extension_set.cc402
-rw-r--r--src/google/protobuf/extension_set.h16
-rw-r--r--src/google/protobuf/extension_set_heavy.cc17
-rw-r--r--src/google/protobuf/extension_set_unittest.cc112
-rw-r--r--src/google/protobuf/generated_message_reflection.cc458
-rw-r--r--src/google/protobuf/generated_message_reflection.h69
-rw-r--r--src/google/protobuf/io/coded_stream.cc15
-rw-r--r--src/google/protobuf/io/coded_stream.h48
-rw-r--r--src/google/protobuf/io/coded_stream_inl.h11
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc1
-rw-r--r--src/google/protobuf/io/gzip_stream.cc11
-rw-r--r--src/google/protobuf/io/gzip_stream.h1
-rw-r--r--src/google/protobuf/io/printer.cc13
-rw-r--r--src/google/protobuf/io/printer.h5
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h25
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc37
-rw-r--r--src/google/protobuf/message.cc89
-rw-r--r--src/google/protobuf/message.h187
-rw-r--r--src/google/protobuf/message_lite.cc22
-rw-r--r--src/google/protobuf/message_lite.h23
-rw-r--r--src/google/protobuf/message_unittest.cc19
-rw-r--r--src/google/protobuf/metadata.h164
-rw-r--r--src/google/protobuf/new_delete_capture.cc121
-rw-r--r--src/google/protobuf/new_delete_capture.h175
-rw-r--r--src/google/protobuf/no_field_presence_test.cc526
-rw-r--r--src/google/protobuf/preserve_unknown_enum_test.cc230
-rw-r--r--src/google/protobuf/proto3_arena_unittest.cc185
-rw-r--r--src/google/protobuf/proto_cast.h58
-rw-r--r--src/google/protobuf/proto_cast_test.cc60
-rw-r--r--src/google/protobuf/reflection.h306
-rw-r--r--src/google/protobuf/reflection_internal.h310
-rw-r--r--src/google/protobuf/repeated_field.cc72
-rw-r--r--src/google/protobuf/repeated_field.h1103
-rw-r--r--src/google/protobuf/repeated_field_reflection.h335
-rw-r--r--src/google/protobuf/repeated_field_reflection_unittest.cc518
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc69
-rw-r--r--src/google/protobuf/stubs/atomic_sequence_num.h54
-rw-r--r--src/google/protobuf/stubs/casts.h123
-rw-r--r--src/google/protobuf/stubs/common.cc1
-rw-r--r--src/google/protobuf/stubs/common.h135
-rw-r--r--src/google/protobuf/stubs/common_unittest.cc1
-rw-r--r--src/google/protobuf/stubs/fastmem.h153
-rw-r--r--src/google/protobuf/stubs/singleton.h64
-rw-r--r--src/google/protobuf/stubs/strutil.cc56
-rw-r--r--src/google/protobuf/stubs/strutil.h32
-rw-r--r--src/google/protobuf/stubs/type_traits.h39
-rw-r--r--src/google/protobuf/text_format.cc22
-rw-r--r--src/google/protobuf/text_format.h3
-rw-r--r--src/google/protobuf/unittest.proto12
-rw-r--r--src/google/protobuf/unittest_arena.proto45
-rw-r--r--src/google/protobuf/unittest_custom_options.proto3
-rw-r--r--src/google/protobuf/unittest_drop_unknown_fields.proto55
-rw-r--r--src/google/protobuf/unittest_embed_optimize_for.proto1
-rw-r--r--src/google/protobuf/unittest_empty.proto1
-rw-r--r--src/google/protobuf/unittest_enormous_descriptor.proto1
-rw-r--r--src/google/protobuf/unittest_import.proto1
-rw-r--r--src/google/protobuf/unittest_import_lite.proto1
-rw-r--r--src/google/protobuf/unittest_import_public.proto1
-rw-r--r--src/google/protobuf/unittest_import_public_lite.proto1
-rw-r--r--src/google/protobuf/unittest_lite.proto1
-rw-r--r--src/google/protobuf/unittest_lite_imports_nonlite.proto1
-rw-r--r--src/google/protobuf/unittest_mset.proto1
-rw-r--r--src/google/protobuf/unittest_no_arena.proto199
-rw-r--r--src/google/protobuf/unittest_no_arena_import.proto37
-rw-r--r--src/google/protobuf/unittest_no_field_presence.proto138
-rw-r--r--src/google/protobuf/unittest_no_generic_services.proto1
-rw-r--r--src/google/protobuf/unittest_optimize_for.proto1
-rw-r--r--src/google/protobuf/unittest_preserve_unknown_enum.proto66
-rw-r--r--src/google/protobuf/unittest_proto3_arena.proto143
-rw-r--r--src/google/protobuf/unknown_enum_impl.h132
-rw-r--r--src/google/protobuf/unknown_enum_test.proto61
-rw-r--r--src/google/protobuf/unknown_field_set.cc112
-rw-r--r--src/google/protobuf/unknown_field_set.h29
-rw-r--r--src/google/protobuf/unknown_field_set_unittest.cc7
-rw-r--r--src/google/protobuf/wire_format.cc45
-rw-r--r--src/google/protobuf/wire_format_lite.cc29
-rw-r--r--src/google/protobuf/wire_format_lite.h28
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h24
-rw-r--r--src/google/protobuf/wire_format_unittest.cc6
255 files changed, 25099 insertions, 4893 deletions
diff --git a/Makefile.am b/Makefile.am
index 24e5e55c..4a29e1cf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -79,6 +79,7 @@ EXTRA_DIST = \
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/ExtensionLite.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 \
@@ -91,6 +92,10 @@ EXTRA_DIST = \
java/src/main/java/com/google/protobuf/LazyStringArrayList.java \
java/src/main/java/com/google/protobuf/LazyStringList.java \
java/src/main/java/com/google/protobuf/LiteralByteString.java \
+ java/src/main/java/com/google/protobuf/MapEntry.java \
+ java/src/main/java/com/google/protobuf/MapEntryLite.java \
+ java/src/main/java/com/google/protobuf/MapField.java \
+ java/src/main/java/com/google/protobuf/MapFieldLite.java \
java/src/main/java/com/google/protobuf/Message.java \
java/src/main/java/com/google/protobuf/MessageLite.java \
java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \
@@ -112,6 +117,7 @@ EXTRA_DIST = \
java/src/main/java/com/google/protobuf/TextFormat.java \
java/src/main/java/com/google/protobuf/UninitializedMessageException.java \
java/src/main/java/com/google/protobuf/UnknownFieldSet.java \
+ java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java \
java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java \
java/src/main/java/com/google/protobuf/Utf8.java \
java/src/main/java/com/google/protobuf/WireFormat.java \
@@ -124,18 +130,22 @@ EXTRA_DIST = \
java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \
java/src/test/java/com/google/protobuf/DescriptorsTest.java \
java/src/test/java/com/google/protobuf/DynamicMessageTest.java \
+ java/src/test/java/com/google/protobuf/FieldPresenceTest.java \
java/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java \
java/src/test/java/com/google/protobuf/GeneratedMessageTest.java \
java/src/test/java/com/google/protobuf/IsValidUtf8Test.java \
java/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java \
- java/src/test/java/com/google/protobuf/LazyFieldTest.java \
java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java \
+ java/src/test/java/com/google/protobuf/LazyFieldTest.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/MapForProto2LiteTest.java \
+ java/src/test/java/com/google/protobuf/MapForProto2Test.java \
+ java/src/test/java/com/google/protobuf/MapTest.java \
java/src/test/java/com/google/protobuf/MessageTest.java \
java/src/test/java/com/google/protobuf/NestedBuildersTest.java \
java/src/test/java/com/google/protobuf/ParserTest.java \
@@ -148,20 +158,25 @@ EXTRA_DIST = \
java/src/test/java/com/google/protobuf/TestBadIdentifiers.java \
java/src/test/java/com/google/protobuf/TestUtil.java \
java/src/test/java/com/google/protobuf/TextFormatTest.java \
+ java/src/test/java/com/google/protobuf/UnknownEnumValueTest.java \
+ java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java \
java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java \
java/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java \
java/src/test/java/com/google/protobuf/WireFormatTest.java \
+ java/src/test/java/com/google/protobuf/field_presence_test.proto \
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/map_for_proto2_test.proto \
+ java/src/test/java/com/google/protobuf/map_test.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/outer_class_name_test.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 \
@@ -194,6 +209,7 @@ EXTRA_DIST = \
python/google/protobuf/internal/more_extensions.proto \
python/google/protobuf/internal/more_extensions_dynamic.proto \
python/google/protobuf/internal/more_messages.proto \
+ python/google/protobuf/internal/proto_builder_test.py \
python/google/protobuf/internal/python_message.py \
python/google/protobuf/internal/reflection_test.py \
python/google/protobuf/internal/service_reflection_test.py \
@@ -207,6 +223,10 @@ 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/internal/import_test_package/BUILD \
+ python/google/protobuf/internal/import_test_package/__init__.py \
+ python/google/protobuf/internal/import_test_package/inner.proto \
+ python/google/protobuf/internal/import_test_package/outer.proto \
python/google/protobuf/pyext/README \
python/google/protobuf/pyext/cpp_message.py \
python/google/protobuf/pyext/descriptor.h \
@@ -232,6 +252,7 @@ EXTRA_DIST = \
python/google/protobuf/descriptor_pool.py \
python/google/protobuf/message.py \
python/google/protobuf/message_factory.py \
+ python/google/protobuf/proto_builder.py \
python/google/protobuf/reflection.py \
python/google/protobuf/service.py \
python/google/protobuf/service_reflection.py \
diff --git a/java/pom.xml b/java/pom.xml
index 1e3baa3c..a2bd1d1e 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -130,6 +130,10 @@
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
<arg value="../src/google/protobuf/unittest_no_generic_services.proto" />
+ <arg value="src/test/java/com/google/protobuf/field_presence_test.proto" />
+ <arg value="src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto" />
+ <arg value="src/test/java/com/google/protobuf/map_for_proto2_test.proto" />
+ <arg value="src/test/java/com/google/protobuf/map_test.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
@@ -164,34 +168,37 @@
<configuration>
<includes>
<include>**/AbstractMessageLite.java</include>
+ <include>**/AbstractParser.java</include>
+ <include>**/BoundedByteString.java</include>
<include>**/ByteString.java</include>
<include>**/CodedInputStream.java</include>
<include>**/CodedOutputStream.java</include>
+ <include>**/ExtensionLite.java</include>
<include>**/ExtensionRegistryLite.java</include>
<include>**/FieldSet.java</include>
<include>**/GeneratedMessageLite.java</include>
<include>**/Internal.java</include>
<include>**/InvalidProtocolBufferException.java</include>
+ <include>**/LazyFieldLite.java</include>
<include>**/LazyStringArrayList.java</include>
<include>**/LazyStringList.java</include>
+ <include>**/LiteralByteString.java</include>
+ <include>**/MapEntryLite.java</include>
+ <include>**/MapFieldLite.java</include>
<include>**/MessageLite.java</include>
<include>**/MessageLiteOrBuilder.java</include>
+ <include>**/Parser.java</include>
+ <include>**/ProtocolStringList.java</include>
+ <include>**/RopeByteString.java</include>
<include>**/SmallSortedMap.java</include>
<include>**/UninitializedMessageException.java</include>
+ <include>**/UnknownFieldSetLite.java</include>
<include>**/UnmodifiableLazyStringList.java</include>
- <include>**/WireFormat.java</include>
- <include>**/Parser.java</include>
- <include>**/AbstractParser.java</include>
- <include>**/BoundedByteString.java</include>
- <include>**/LiteralByteString.java</include>
- <include>**/RopeByteString.java</include>
<include>**/Utf8.java</include>
- <include>**/LazyField.java</include>
- <include>**/LazyFieldLite.java</include>
- <include>**/ProtocolStringList.java</include>
+ <include>**/WireFormat.java</include>
</includes>
<testIncludes>
- <testInclude>**/LiteTest.java</testInclude>
+ <testInclude>**/**LiteTest.java</testInclude>
<testInclude>**/*Lite.java</testInclude>
</testIncludes>
</configuration>
@@ -200,7 +207,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
- <include>**/LiteTest.java</include>
+ <include>**/**LiteTest.java</include>
</includes>
</configuration>
</plugin>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index ae9d5e39..6de4cae3 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -37,6 +37,9 @@ import com.google.protobuf.Internal.EnumLite;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -144,6 +147,40 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
/**
+ * Converts a list of MapEntry messages into a Map used for equals() and
+ * hashCode().
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static Map convertMapEntryListToMap(List list) {
+ if (list.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map result = new HashMap();
+ Iterator iterator = list.iterator();
+ Message entry = (Message) iterator.next();
+ Descriptors.Descriptor descriptor = entry.getDescriptorForType();
+ Descriptors.FieldDescriptor key = descriptor.findFieldByName("key");
+ Descriptors.FieldDescriptor value = descriptor.findFieldByName("value");
+ result.put(entry.getField(key), entry.getField(value));
+ while (iterator.hasNext()) {
+ entry = (Message) iterator.next();
+ result.put(entry.getField(key), entry.getField(value));
+ }
+ return result;
+ }
+
+ /**
+ * Compares two map fields. The parameters must be a list of MapEntry
+ * messages.
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static boolean compareMapField(Object a, Object b) {
+ Map ma = convertMapEntryListToMap((List) a);
+ Map mb = convertMapEntryListToMap((List) b);
+ return MapFieldLite.equals(ma, mb);
+ }
+
+ /**
* Compares two set of fields.
* This method is used to implement {@link AbstractMessage#equals(Object)}
* and {@link AbstractMutableMessage#equals(Object)}. It takes special care
@@ -181,6 +218,10 @@ public abstract class AbstractMessage extends AbstractMessageLite
return false;
}
}
+ } else if (descriptor.isMapField()) {
+ if (!compareMapField(value1, value2)) {
+ return false;
+ }
} else {
// Compare non-bytes fields.
if (!value1.equals(value2)) {
@@ -190,6 +231,15 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
return true;
}
+
+ /**
+ * Calculates the hash code of a map field. {@code value} must be a list of
+ * MapEntry messages.
+ */
+ @SuppressWarnings("unchecked")
+ private static int hashMapField(Object value) {
+ return MapFieldLite.calculateHashCodeForMap(convertMapEntryListToMap((List) value));
+ }
/** Get a hash code for given fields and values, using the given seed. */
@SuppressWarnings("unchecked")
@@ -198,7 +248,9 @@ public abstract class AbstractMessage extends AbstractMessageLite
FieldDescriptor field = entry.getKey();
Object value = entry.getValue();
hash = (37 * hash) + field.getNumber();
- if (field.getType() != FieldDescriptor.Type.ENUM){
+ if (field.isMapField()) {
+ hash = (53 * hash) + hashMapField(value);
+ } else if (field.getType() != FieldDescriptor.Type.ENUM){
hash = (53 * hash) + value.hashCode();
} else if (field.isRepeated()) {
List<? extends EnumLite> list = (List<? extends EnumLite>) value;
@@ -359,6 +411,12 @@ public abstract class AbstractMessage extends AbstractMessageLite
"getFieldBuilder() called on an unsupported message type.");
}
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field,
+ int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on an unsupported message type.");
+ }
+
public String toString() {
return TextFormat.printToString(this);
}
diff --git a/java/src/main/java/com/google/protobuf/CodedInputStream.java b/java/src/main/java/com/google/protobuf/CodedInputStream.java
index a00ae86f..0ca00bab 100644
--- a/java/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -612,16 +612,16 @@ public final class CodedInputStream {
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 if ((x ^= (buffer[pos++] << 7)) < 0) {
+ x ^= (~0 << 7);
+ } else if ((x ^= (buffer[pos++] << 14)) >= 0) {
+ x ^= (~0 << 7) ^ (~0 << 14);
+ } else if ((x ^= (buffer[pos++] << 21)) < 0) {
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
} else {
int y = buffer[pos++];
x ^= y << 28;
- x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
if (y < 0 &&
buffer[pos++] < 0 &&
buffer[pos++] < 0 &&
@@ -739,13 +739,13 @@ public final class CodedInputStream {
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) {
+ } else if ((y ^= (buffer[pos++] << 7)) < 0) {
+ x = y ^ (~0 << 7);
+ } else if ((y ^= (buffer[pos++] << 14)) >= 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14));
+ } else if ((y ^= (buffer[pos++] << 21)) < 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
+ } else if ((x = ((long) y) ^ ((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);
@@ -882,7 +882,7 @@ public final class CodedInputStream {
/** See setSizeLimit() */
private int sizeLimit = DEFAULT_SIZE_LIMIT;
- private static final int DEFAULT_RECURSION_LIMIT = 64;
+ private static final int DEFAULT_RECURSION_LIMIT = 100;
private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
private static final int BUFFER_SIZE = 4096;
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index caae0f77..d65e8b49 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.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -40,6 +41,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.WeakHashMap;
import java.util.logging.Logger;
import java.io.UnsupportedEncodingException;
@@ -123,6 +125,26 @@ public final class Descriptors {
return Collections.unmodifiableList(Arrays.asList(publicDependencies));
}
+ /** The syntax of the .proto file. */
+ public enum Syntax {
+ UNKNOWN("unknown"),
+ PROTO2("proto2"),
+ PROTO3("proto3");
+
+ Syntax(String name) {
+ this.name = name;
+ }
+ private final String name;
+ }
+
+ /** Get the syntax of the .proto file. */
+ public Syntax getSyntax() {
+ if (Syntax.PROTO3.name.equals(proto.getSyntax())) {
+ return Syntax.PROTO3;
+ }
+ return Syntax.PROTO2;
+ }
+
/**
* Find a message type in the file by name. Does not find nested types.
*
@@ -539,6 +561,10 @@ public final class Descriptors {
extensions[i].setProto(proto.getExtension(i));
}
}
+
+ boolean supportsUnknownEnumValue() {
+ return getSyntax() == Syntax.PROTO3;
+ }
}
// =================================================================
@@ -871,6 +897,11 @@ public final class Descriptors {
return (type == Type.STRING) && (getFile().getOptions().getJavaStringCheckUtf8());
}
+ boolean isMapField() {
+ return getType() == Type.MESSAGE && isRepeated()
+ && getMessageType().getOptions().getMapEntry();
+ }
+
// 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.
@@ -1001,6 +1032,11 @@ public final class Descriptors {
return getNumber() - other.getNumber();
}
+ @Override
+ public String toString() {
+ return getFullName();
+ }
+
private final int index;
private FieldDescriptorProto proto;
@@ -1420,6 +1456,64 @@ public final class Descriptors {
return file.pool.enumValuesByNumber.get(
new DescriptorPool.DescriptorIntPair(this, number));
}
+
+ /**
+ * Get the enum value for a number. If no enum value has this number,
+ * construct an EnumValueDescriptor for it.
+ */
+ public EnumValueDescriptor findValueByNumberCreatingIfUnknown(final int number) {
+ EnumValueDescriptor result = findValueByNumber(number);
+ if (result != null) {
+ return result;
+ }
+ // The number represents an unknown enum value.
+ synchronized (this) {
+ // Descriptors are compared by object identity so for the same number
+ // we need to return the same EnumValueDescriptor object. This means
+ // we have to store created EnumValueDescriptors. However, as there
+ // are potentially 2G unknown enum values, storing all of these
+ // objects persistently will consume lots of memory for long-running
+ // services and it's also unnecessary as not many EnumValueDescriptors
+ // will be used at the same time.
+ //
+ // To solve the problem we take advantage of Java's weak references and
+ // rely on gc to release unused descriptors.
+ //
+ // Here is how it works:
+ // * We store unknown EnumValueDescriptors in a WeakHashMap with the
+ // value being a weak reference to the descriptor.
+ // * The descriptor holds a strong reference to the key so as long
+ // as the EnumValueDescriptor is in use, the key will be there
+ // and the corresponding map entry will be there. Following-up
+ // queries with the same number will return the same descriptor.
+ // * If the user no longer uses an unknown EnumValueDescriptor,
+ // it will be gc-ed since we only hold a weak reference to it in
+ // the map. The key in the corresponding map entry will also be
+ // gc-ed as the only strong reference to it is in the descriptor
+ // which is just gc-ed. With the key being gone WeakHashMap will
+ // then remove the whole entry. This way unknown descriptors will
+ // be freed automatically and we don't need to do anything to
+ // clean-up unused map entries.
+
+ // Note: We must use "new Integer(number)" here because we don't want
+ // these Integer objects to be cached.
+ Integer key = new Integer(number);
+ WeakReference<EnumValueDescriptor> reference = unknownValues.get(key);
+ if (reference != null) {
+ result = reference.get();
+ }
+ if (result == null) {
+ result = new EnumValueDescriptor(file, this, key);
+ unknownValues.put(key, new WeakReference<EnumValueDescriptor>(result));
+ }
+ }
+ return result;
+ }
+
+ // Used in tests only.
+ int getUnknownEnumValueDescriptorCount() {
+ return unknownValues.size();
+ }
private final int index;
private EnumDescriptorProto proto;
@@ -1427,6 +1521,8 @@ public final class Descriptors {
private final FileDescriptor file;
private final Descriptor containingType;
private EnumValueDescriptor[] values;
+ private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
+ new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
private EnumDescriptor(final EnumDescriptorProto proto,
final FileDescriptor file,
@@ -1531,6 +1627,25 @@ public final class Descriptors {
file.pool.addSymbol(this);
file.pool.addEnumValueByNumber(this);
}
+
+ private Integer number;
+ // Create an unknown enum value.
+ private EnumValueDescriptor(
+ final FileDescriptor file,
+ final EnumDescriptor parent,
+ final Integer number) {
+ String name = "UNKNOWN_ENUM_VALUE_" + parent.getName() + "_" + number;
+ EnumValueDescriptorProto proto = EnumValueDescriptorProto
+ .newBuilder().setName(name).setNumber(number).build();
+ this.index = -1;
+ this.proto = proto;
+ this.file = file;
+ this.type = parent;
+ this.fullName = parent.getFullName() + '.' + proto.getName();
+ this.number = number;
+
+ // Don't add this descriptor into pool.
+ }
/** See {@link FileDescriptor#setProto}. */
private void setProto(final EnumValueDescriptorProto proto) {
diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java
index c9ce667b..06b30fff 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -549,12 +549,22 @@ public final class DynamicMessage extends AbstractMessage {
}
public Builder setUnknownFields(UnknownFieldSet unknownFields) {
+ if (getDescriptorForType().getFile().getSyntax()
+ == Descriptors.FileDescriptor.Syntax.PROTO3) {
+ // Proto3 discards unknown fields.
+ return this;
+ }
this.unknownFields = unknownFields;
return this;
}
@Override
public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
+ if (getDescriptorForType().getFile().getSyntax()
+ == Descriptors.FileDescriptor.Syntax.PROTO3) {
+ // Proto3 discards unknown fields.
+ return this;
+ }
this.unknownFields =
UnknownFieldSet.newBuilder(this.unknownFields)
.mergeFrom(unknownFields)
@@ -588,10 +598,12 @@ public final class DynamicMessage extends AbstractMessage {
throw new IllegalArgumentException(
"DynamicMessage should use EnumValueDescriptor to set Enum Value.");
}
- if (field.getEnumType() != ((EnumValueDescriptor) value).getType()) {
- throw new IllegalArgumentException(
- "EnumValueDescriptor doesn't much Enum Field.");
- }
+ // TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not
+ // set incorrect EnumValueDescriptors.
+ // if (field.getEnumType() != ((EnumValueDescriptor) value).getType()) {
+ // throw new IllegalArgumentException(
+ // "EnumValueDescriptor doesn't match Enum Field.");
+ // }
}
/** Verifies the value for an enum field. */
@@ -618,5 +630,12 @@ public final class DynamicMessage extends AbstractMessage {
throw new UnsupportedOperationException(
"getFieldBuilder() called on a dynamic message type.");
}
+
+ @Override
+ public com.google.protobuf.Message.Builder getRepeatedFieldBuilder(FieldDescriptor field,
+ int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a dynamic message type.");
+ }
}
}
diff --git a/java/src/main/java/com/google/protobuf/Extension.java b/java/src/main/java/com/google/protobuf/Extension.java
index 0baa22b3..68d29f33 100644
--- a/java/src/main/java/com/google/protobuf/Extension.java
+++ b/java/src/main/java/com/google/protobuf/Extension.java
@@ -35,27 +35,16 @@ package com.google.protobuf;
*
* @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();
+public abstract class Extension<ContainingType extends MessageLite, Type>
+ extends ExtensionLite<ContainingType, Type> {
/** 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();
+ /** Returns whether or not this extension is a Lite Extension. */
+ final boolean isLite() {
+ return false;
+ }
// All the methods below are extension implementation details.
diff --git a/java/src/main/java/com/google/protobuf/ExtensionLite.java b/java/src/main/java/com/google/protobuf/ExtensionLite.java
new file mode 100644
index 00000000..f8f5bd2c
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/ExtensionLite.java
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+/**
+ * Lite interface that generated extensions implement.
+ * <p>
+ * Methods are for use by generated code only. You can hold a reference to
+ * extensions using this type name.
+ */
+public abstract class ExtensionLite<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 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();
+
+ /** Returns whether or not this extension is a Lite Extension. */
+ boolean isLite() {
+ return true;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index 392f4efc..ff9b5bc0 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -672,7 +672,7 @@ final class FieldSet<FieldDescriptorType extends
* {@link Message#getField(Descriptors.FieldDescriptor)} for
* this field.
*/
- private static void writeElementNoTag(
+ static void writeElementNoTag(
final CodedOutputStream output,
final WireFormat.FieldType type,
final Object value) throws IOException {
@@ -830,7 +830,7 @@ final class FieldSet<FieldDescriptorType extends
* {@link Message#getField(Descriptors.FieldDescriptor)} for
* this field.
*/
- private static int computeElementSizeNoTag(
+ static int computeElementSizeNoTag(
final WireFormat.FieldType type, final Object value) {
switch (type) {
// Note: Minor violation of 80-char limit rule here because this would
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index a6101cb0..156d1633 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -31,16 +31,20 @@
package com.google.protobuf;
import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
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 com.google.protobuf.GeneratedMessageLite.ExtendableMessage;
+import com.google.protobuf.GeneratedMessageLite.GeneratedExtension;
import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@@ -67,10 +71,15 @@ public abstract class GeneratedMessage extends AbstractMessage
*/
protected static boolean alwaysUseFieldBuilders = false;
+ /** For use by generated code only. */
+ protected UnknownFieldSet unknownFields;
+
protected GeneratedMessage() {
+ unknownFields = UnknownFieldSet.getDefaultInstance();
}
protected GeneratedMessage(Builder<?> builder) {
+ unknownFields = builder.getUnknownFields();
}
public Parser<? extends GeneratedMessage> getParserForType() {
@@ -291,13 +300,12 @@ public abstract class GeneratedMessage extends AbstractMessage
return isClean;
}
- // This is implemented here only to work around an apparent bug in the
- // Java compiler and/or build system. See bug #1898463. The mere presence
- // of this dummy clone() implementation makes it go away.
@Override
public BuilderType clone() {
- throw new UnsupportedOperationException(
- "This is supposed to be overridden by subclasses.");
+ BuilderType builder =
+ (BuilderType) getDefaultInstanceForType().newBuilderForType();
+ builder.mergeFrom(buildPartial());
+ return builder;
}
/**
@@ -358,6 +366,13 @@ public abstract class GeneratedMessage extends AbstractMessage
}
//@Override (Java 1.6 override semantics, but we must support 1.5)
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field,
+ int index) {
+ return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
+ this, index);
+ }
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
public boolean hasOneof(final OneofDescriptor oneof) {
return internalGetFieldAccessorTable().getOneof(oneof).has(this);
}
@@ -428,7 +443,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return (BuilderType) this;
}
- public final BuilderType setUnknownFields(
+ public BuilderType setUnknownFields(
final UnknownFieldSet unknownFields) {
this.unknownFields = unknownFields;
onChanged();
@@ -436,7 +451,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
@Override
- public final BuilderType mergeUnknownFields(
+ public BuilderType mergeUnknownFields(
final UnknownFieldSet unknownFields) {
this.unknownFields =
UnknownFieldSet.newBuilder(this.unknownFields)
@@ -529,6 +544,25 @@ public abstract class GeneratedMessage extends AbstractMessage
isClean = false;
}
}
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"unused", "rawtypes"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
}
// =================================================================
@@ -541,19 +575,19 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Check if a singular extension is present. */
<Type> boolean hasExtension(
- Extension<MessageType, Type> extension);
+ ExtensionLite<MessageType, Type> extension);
/** Get the number of elements in a repeated extension. */
<Type> int getExtensionCount(
- Extension<MessageType, List<Type>> extension);
+ ExtensionLite<MessageType, List<Type>> extension);
/** Get the value of an extension. */
<Type> Type getExtension(
- Extension<MessageType, Type> extension);
+ ExtensionLite<MessageType, Type> extension);
/** Get one element of a repeated extension. */
<Type> Type getExtension(
- Extension<MessageType, List<Type>> extension,
+ ExtensionLite<MessageType, List<Type>> extension,
int index);
}
@@ -625,7 +659,9 @@ 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 Extension<MessageType, Type> extension) {
+ final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
return extensions.hasField(extension.getDescriptor());
}
@@ -633,7 +669,9 @@ 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 Extension<MessageType, List<Type>> extension) {
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
final FieldDescriptor descriptor = extension.getDescriptor();
return extensions.getRepeatedFieldCount(descriptor);
@@ -643,7 +681,9 @@ 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 Extension<MessageType, Type> extension) {
+ final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
final Object value = extensions.getField(descriptor);
@@ -666,8 +706,10 @@ 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 Extension<MessageType, List<Type>> extension,
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
return (Type) extension.singularFromReflectionType(
@@ -914,11 +956,10 @@ public abstract class GeneratedMessage extends AbstractMessage
// This is implemented here only to work around an apparent bug in the
// Java compiler and/or build system. See bug #1898463. The mere presence
- // of this dummy clone() implementation makes it go away.
+ // of this clone() implementation makes it go away.
@Override
public BuilderType clone() {
- throw new UnsupportedOperationException(
- "This is supposed to be overridden by subclasses.");
+ return super.clone();
}
private void ensureExtensionsIsMutable() {
@@ -943,7 +984,9 @@ 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 Extension<MessageType, Type> extension) {
+ final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
return extensions.hasField(extension.getDescriptor());
}
@@ -951,7 +994,9 @@ 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 Extension<MessageType, List<Type>> extension) {
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
final FieldDescriptor descriptor = extension.getDescriptor();
return extensions.getRepeatedFieldCount(descriptor);
@@ -960,7 +1005,9 @@ 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 Extension<MessageType, Type> extension) {
+ final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
final Object value = extensions.getField(descriptor);
@@ -982,8 +1029,10 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Get one element of a repeated extension. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> Type getExtension(
- final Extension<MessageType, List<Type>> extension,
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
return (Type) extension.singularFromReflectionType(
@@ -992,8 +1041,10 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Set the value of an extension. */
public final <Type> BuilderType setExtension(
- final Extension<MessageType, Type> extension,
+ final ExtensionLite<MessageType, Type> extensionLite,
final Type value) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
final FieldDescriptor descriptor = extension.getDescriptor();
@@ -1004,8 +1055,10 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Set the value of one element of a repeated extension. */
public final <Type> BuilderType setExtension(
- final Extension<MessageType, List<Type>> extension,
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
final int index, final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
final FieldDescriptor descriptor = extension.getDescriptor();
@@ -1018,8 +1071,10 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Append a value to a repeated extension. */
public final <Type> BuilderType addExtension(
- final Extension<MessageType, List<Type>> extension,
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
final FieldDescriptor descriptor = extension.getDescriptor();
@@ -1031,7 +1086,9 @@ public abstract class GeneratedMessage extends AbstractMessage
/** Clear an extension. */
public final <Type> BuilderType clearExtension(
- final Extension<MessageType, ?> extension) {
+ final ExtensionLite<MessageType, ?> extensionLite) {
+ Extension<MessageType, ?> extension = checkNotLite(extensionLite);
+
verifyExtensionContainingType(extension);
ensureExtensionsIsMutable();
extensions.clearField(extension.getDescriptor());
@@ -1594,6 +1651,25 @@ public abstract class GeneratedMessage extends AbstractMessage
}
}
}
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"rawtypes", "unused"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
/**
* Users should ignore this class. This class provides the implementation
@@ -1633,6 +1709,11 @@ public abstract class GeneratedMessage extends AbstractMessage
oneofs = new OneofAccessor[descriptor.getOneofs().size()];
initialized = false;
}
+
+ private boolean isMapFieldEnabled(FieldDescriptor field) {
+ boolean result = true;
+ return result;
+ }
/**
* Ensures the field accessors are initialized. This method is thread-safe.
@@ -1657,8 +1738,13 @@ public abstract class GeneratedMessage extends AbstractMessage
}
if (field.isRepeated()) {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
- fields[i] = new RepeatedMessageFieldAccessor(
- field, camelCaseNames[i], messageClass, builderClass);
+ if (field.isMapField() && isMapFieldEnabled(field)) {
+ fields[i] = new MapFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
} else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
fields[i] = new RepeatedEnumFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass);
@@ -1744,6 +1830,8 @@ public abstract class GeneratedMessage extends AbstractMessage
void clear(Builder builder);
Message.Builder newBuilder();
Message.Builder getBuilder(GeneratedMessage.Builder builder);
+ Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
+ int index);
}
/** OneofAccessor provides access to a single oneof. */
@@ -1799,9 +1887,9 @@ public abstract class GeneratedMessage extends AbstractMessage
invokeOrDie(clearMethod, builder);
}
}
-
+
private static boolean supportFieldPresence(FileDescriptor file) {
- return true;
+ return file.getSyntax() == FileDescriptor.Syntax.PROTO2;
}
// ---------------------------------------------------------------
@@ -1919,6 +2007,11 @@ public abstract class GeneratedMessage extends AbstractMessage
throw new UnsupportedOperationException(
"getFieldBuilder() called on a non-Message type.");
}
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
+ int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
}
private static class RepeatedFieldAccessor implements FieldAccessor {
@@ -2014,6 +2107,113 @@ public abstract class GeneratedMessage extends AbstractMessage
throw new UnsupportedOperationException(
"getFieldBuilder() called on a non-Message type.");
}
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
+ int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
+ }
+
+ private static class MapFieldAccessor implements FieldAccessor {
+ MapFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ field = descriptor;
+ Method getDefaultInstanceMethod =
+ getMethodOrDie(messageClass, "getDefaultInstance");
+ MapField defaultMapField = getMapField(
+ (GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null));
+ mapEntryMessageDefaultInstance =
+ defaultMapField.getMapEntryMessageDefaultInstance();
+ }
+
+ private final FieldDescriptor field;
+ private final Message mapEntryMessageDefaultInstance;
+
+ private MapField<?, ?> getMapField(GeneratedMessage message) {
+ return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
+ }
+
+ private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
+ }
+
+ public Object get(GeneratedMessage message) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(message); i++) {
+ result.add(getRepeated(message, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ public Object get(Builder builder) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(builder); i++) {
+ result.add(getRepeated(builder, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ public void set(Builder builder, Object value) {
+ clear(builder);
+ for (Object entry : (List) value) {
+ addRepeated(builder, entry);
+ }
+ }
+
+ public Object getRepeated(GeneratedMessage message, int index) {
+ return getMapField(message).getList().get(index);
+ }
+
+ public Object getRepeated(Builder builder, int index) {
+ return getMapField(builder).getList().get(index);
+ }
+
+ public void setRepeated(Builder builder, int index, Object value) {
+ getMapField(builder).getMutableList().set(index, (Message) value);
+ }
+
+ public void addRepeated(Builder builder, Object value) {
+ getMapField(builder).getMutableList().add((Message) value);
+ }
+
+ public boolean has(GeneratedMessage message) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ public boolean has(Builder builder) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ public int getRepeatedCount(GeneratedMessage message) {
+ return getMapField(message).getList().size();
+ }
+
+ public int getRepeatedCount(Builder builder) {
+ return getMapField(builder).getList().size();
+ }
+
+ public void clear(Builder builder) {
+ getMapField(builder).getMutableList().clear();
+ }
+
+ public com.google.protobuf.Message.Builder newBuilder() {
+ return mapEntryMessageDefaultInstance.newBuilderForType();
+ }
+
+ public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
+
+ public com.google.protobuf.Message.Builder getRepeatedBuilder(
+ Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
}
// ---------------------------------------------------------------
@@ -2026,28 +2226,60 @@ public abstract class GeneratedMessage extends AbstractMessage
final Class<? extends Builder> builderClass,
final String containingOneofCamelCaseName) {
super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+
+ enumDescriptor = descriptor.getEnumType();
valueOfMethod = getMethodOrDie(type, "valueOf",
EnumValueDescriptor.class);
getValueDescriptorMethod =
getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
+ getValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
+ setValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
+ }
}
+
+ private EnumDescriptor enumDescriptor;
private Method valueOfMethod;
private Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getValueMethod;
+ private Method getValueMethodBuilder;
+ private Method setValueMethod;
@Override
public Object get(final GeneratedMessage message) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethod, message);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
return invokeOrDie(getValueDescriptorMethod, super.get(message));
}
@Override
public Object get(final GeneratedMessage.Builder builder) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethodBuilder, builder);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
return invokeOrDie(getValueDescriptorMethod, super.get(builder));
}
@Override
public void set(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
super.set(builder, invokeOrDie(valueOfMethod, null, value));
}
}
@@ -2059,22 +2291,44 @@ public abstract class GeneratedMessage extends AbstractMessage
final Class<? extends GeneratedMessage> messageClass,
final Class<? extends Builder> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass);
+
+ enumDescriptor = descriptor.getEnumType();
valueOfMethod = getMethodOrDie(type, "valueOf",
EnumValueDescriptor.class);
getValueDescriptorMethod =
getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getRepeatedValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value", int.class);
+ getRepeatedValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value", int.class);
+ setRepeatedValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class, int.class);
+ addRepeatedValueMethod =
+ getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
+ }
}
+ private EnumDescriptor enumDescriptor;
private final Method valueOfMethod;
private final Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getRepeatedValueMethod;
+ private Method getRepeatedValueMethodBuilder;
+ private Method setRepeatedValueMethod;
+ private Method addRepeatedValueMethod;
@Override
@SuppressWarnings("unchecked")
public Object get(final GeneratedMessage message) {
final List newList = new ArrayList();
- for (final Object element : (List) super.get(message)) {
- newList.add(invokeOrDie(getValueDescriptorMethod, element));
+ final int size = getRepeatedCount(message);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(message, i));
}
return Collections.unmodifiableList(newList);
}
@@ -2083,8 +2337,9 @@ public abstract class GeneratedMessage extends AbstractMessage
@SuppressWarnings("unchecked")
public Object get(final GeneratedMessage.Builder builder) {
final List newList = new ArrayList();
- for (final Object element : (List) super.get(builder)) {
- newList.add(invokeOrDie(getValueDescriptorMethod, element));
+ final int size = getRepeatedCount(builder);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(builder, i));
}
return Collections.unmodifiableList(newList);
}
@@ -2092,23 +2347,41 @@ public abstract class GeneratedMessage extends AbstractMessage
@Override
public Object getRepeated(final GeneratedMessage message,
final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
return invokeOrDie(getValueDescriptorMethod,
super.getRepeated(message, index));
}
@Override
public Object getRepeated(final GeneratedMessage.Builder builder,
final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
return invokeOrDie(getValueDescriptorMethod,
super.getRepeated(builder, index));
}
@Override
public void setRepeated(final Builder builder,
final int index, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setRepeatedValueMethod, builder, index,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
value));
}
@Override
public void addRepeated(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(addRepeatedValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
}
}
@@ -2168,9 +2441,12 @@ public abstract class GeneratedMessage extends AbstractMessage
super(descriptor, camelCaseName, messageClass, builderClass);
newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Builder", Integer.TYPE);
}
private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
private Object coerceType(final Object value) {
if (type.isInstance(value)) {
@@ -2198,6 +2474,12 @@ public abstract class GeneratedMessage extends AbstractMessage
public Message.Builder newBuilder() {
return (Message.Builder) invokeOrDie(newBuilderMethod, null);
}
+ @Override
+ public Message.Builder getRepeatedBuilder(
+ final GeneratedMessage.Builder builder, final int index) {
+ return (Message.Builder) invokeOrDie(
+ getBuilderMethodBuilder, builder, index);
+ }
}
}
@@ -2210,4 +2492,18 @@ public abstract class GeneratedMessage extends AbstractMessage
protected Object writeReplace() throws ObjectStreamException {
return new GeneratedMessageLite.SerializedForm(this);
}
+
+ /**
+ * Checks that the {@link Extension} is non-Lite and returns it as a
+ * {@link GeneratedExtension}.
+ */
+ private static <MessageType extends ExtendableMessage<MessageType>, T>
+ Extension<MessageType, T> checkNotLite(
+ ExtensionLite<MessageType, T> extension) {
+ if (extension.isLite()) {
+ throw new IllegalArgumentException("Expected non-lite extension.");
+ }
+
+ return (Extension<MessageType, T>) extension;
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 6c5136fd..8fe33bc6 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import com.google.protobuf.WireFormat.FieldType;
+
import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;
@@ -50,10 +52,15 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
implements Serializable {
private static final long serialVersionUID = 1L;
+ /** For use by generated code only. */
+ protected UnknownFieldSetLite unknownFields;
+
protected GeneratedMessageLite() {
+ unknownFields = UnknownFieldSetLite.getDefaultInstance();
}
protected GeneratedMessageLite(Builder builder) {
+ unknownFields = builder.unknownFields;
}
public Parser<? extends MessageLite> getParserForType() {
@@ -62,15 +69,16 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
}
/**
- * Called by subclasses to parse an unknown field.
+ * Called by subclasses to parse an unknown field. For use by generated code
+ * only.
* @return {@code true} unless the tag is an end-group tag.
*/
- protected boolean parseUnknownField(
+ protected static boolean parseUnknownField(
CodedInputStream input,
- CodedOutputStream unknownFieldsCodedOutput,
+ UnknownFieldSetLite.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
- return input.skipField(tag, unknownFieldsCodedOutput);
+ return unknownFields.mergeFieldFrom(tag, input);
}
/**
@@ -84,22 +92,28 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
public abstract static class Builder<MessageType extends GeneratedMessageLite,
BuilderType extends Builder>
extends AbstractMessageLite.Builder<BuilderType> {
+
+ private UnknownFieldSetLite unknownFields =
+ UnknownFieldSetLite.getDefaultInstance();
+
protected Builder() {}
//@Override (Java 1.6 override semantics, but we must support 1.5)
public BuilderType clear() {
- unknownFields = ByteString.EMPTY;
+ unknownFields = UnknownFieldSetLite.getDefaultInstance();
return (BuilderType) this;
}
- // This is implemented here only to work around an apparent bug in the
- // Java compiler and/or build system. See bug #1898463. The mere presence
- // of this dummy clone() implementation makes it go away.
- @Override
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
public BuilderType clone() {
- throw new UnsupportedOperationException(
- "This is supposed to be overridden by subclasses.");
+ BuilderType builder =
+ (BuilderType) getDefaultInstanceForType().newBuilderForType();
+ builder.mergeFrom(buildPartial());
+ return builder;
}
+
+ /** All subclasses implement this. */
+ public abstract MessageType buildPartial();
/** All subclasses implement this. */
public abstract BuilderType mergeFrom(MessageType message);
@@ -113,22 +127,43 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
*/
protected boolean parseUnknownField(
CodedInputStream input,
- CodedOutputStream unknownFieldsCodedOutput,
+ UnknownFieldSetLite.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
- return input.skipField(tag, unknownFieldsCodedOutput);
+ return unknownFields.mergeFieldFrom(tag, input);
}
- public final ByteString getUnknownFields() {
- return unknownFields;
+ /**
+ * Merge some unknown fields into the {@link UnknownFieldSetLite} for this
+ * message.
+ *
+ * <p>For use by generated code only.
+ */
+ protected final BuilderType mergeUnknownFields(
+ final UnknownFieldSetLite unknownFields) {
+ this.unknownFields = UnknownFieldSetLite.concat(this.unknownFields, unknownFields);
+ return (BuilderType) this;
}
-
- public final BuilderType setUnknownFields(final ByteString unknownFields) {
- this.unknownFields = unknownFields;
+
+ public BuilderType mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ MessageType parsedMessage = null;
+ try {
+ parsedMessage =
+ (MessageType) getDefaultInstanceForType().getParserForType().parsePartialFrom(
+ input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (MessageType) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
return (BuilderType) this;
}
-
- private ByteString unknownFields = ByteString.EMPTY;
}
@@ -143,18 +178,18 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
/** Check if a singular extension is present. */
<Type> boolean hasExtension(
- GeneratedExtension<MessageType, Type> extension);
+ ExtensionLite<MessageType, Type> extension);
/** Get the number of elements in a repeated extension. */
<Type> int getExtensionCount(
- GeneratedExtension<MessageType, List<Type>> extension);
+ ExtensionLite<MessageType, List<Type>> extension);
/** Get the value of an extension. */
- <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension);
+ <Type> Type getExtension(ExtensionLite<MessageType, Type> extension);
/** Get one element of a repeated extension. */
<Type> Type getExtension(
- GeneratedExtension<MessageType, List<Type>> extension,
+ ExtensionLite<MessageType, List<Type>> extension,
int index);
}
@@ -166,7 +201,11 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
extends GeneratedMessageLite
implements ExtendableMessageOrBuilder<MessageType> {
- private final FieldSet<ExtensionDescriptor> extensions;
+ /**
+ * Represents the set of extensions on this message. For use by generated
+ * code only.
+ */
+ protected final FieldSet<ExtensionDescriptor> extensions;
protected ExtendableMessage() {
this.extensions = FieldSet.newFieldSet();
@@ -190,30 +229,39 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
/** 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) {
- verifyExtensionContainingType(extension);
- return extensions.hasField(extension.descriptor);
+ final ExtensionLite<MessageType, Type> extension) {
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return extensions.hasField(extensionLite.descriptor);
}
/** 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) {
- verifyExtensionContainingType(extension);
- return extensions.getRepeatedFieldCount(extension.descriptor);
+ final ExtensionLite<MessageType, List<Type>> extension) {
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return extensions.getRepeatedFieldCount(extensionLite.descriptor);
}
/** Get the value of an extension. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- final GeneratedExtension<MessageType, Type> extension) {
- verifyExtensionContainingType(extension);
- final Object value = extensions.getField(extension.descriptor);
+ final ExtensionLite<MessageType, Type> extension) {
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ final Object value = extensions.getField(extensionLite.descriptor);
if (value == null) {
- return extension.defaultValue;
+ return extensionLite.defaultValue;
} else {
- return (Type) extension.fromFieldSetType(value);
+ return (Type) extensionLite.fromFieldSetType(value);
}
}
@@ -221,11 +269,14 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
//@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 ExtensionLite<MessageType, List<Type>> extension,
final int index) {
- verifyExtensionContainingType(extension);
- return (Type) extension.singularFromFieldSetType(
- extensions.getRepeatedField(extension.descriptor, index));
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return (Type) extensionLite.singularFromFieldSetType(
+ extensions.getRepeatedField(extensionLite.descriptor, index));
}
/** Called by subclasses to check if all extensions are initialized. */
@@ -233,25 +284,6 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
return extensions.isInitialized();
}
- /**
- * Called by subclasses to parse an unknown field or an extension.
- * @return {@code true} unless the tag is an end-group tag.
- */
- @Override
- protected boolean parseUnknownField(
- 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.
@@ -377,30 +409,39 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
/** 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) {
- verifyExtensionContainingType(extension);
- return extensions.hasField(extension.descriptor);
+ final ExtensionLite<MessageType, Type> extension) {
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return extensions.hasField(extensionLite.descriptor);
}
/** 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) {
- verifyExtensionContainingType(extension);
- return extensions.getRepeatedFieldCount(extension.descriptor);
+ final ExtensionLite<MessageType, List<Type>> extension) {
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return extensions.getRepeatedFieldCount(extensionLite.descriptor);
}
/** Get the value of an extension. */
//@Override (Java 1.6 override semantics, but we must support 1.5)
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- final GeneratedExtension<MessageType, Type> extension) {
- verifyExtensionContainingType(extension);
- final Object value = extensions.getField(extension.descriptor);
+ final ExtensionLite<MessageType, Type> extension) {
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ final Object value = extensions.getField(extensionLite.descriptor);
if (value == null) {
- return extension.defaultValue;
+ return extensionLite.defaultValue;
} else {
- return (Type) extension.fromFieldSetType(value);
+ return (Type) extensionLite.fromFieldSetType(value);
}
}
@@ -408,11 +449,14 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
@SuppressWarnings("unchecked")
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> Type getExtension(
- final GeneratedExtension<MessageType, List<Type>> extension,
+ final ExtensionLite<MessageType, List<Type>> extension,
final int index) {
- verifyExtensionContainingType(extension);
- return (Type) extension.singularFromFieldSetType(
- extensions.getRepeatedField(extension.descriptor, index));
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return (Type) extensionLite.singularFromFieldSetType(
+ extensions.getRepeatedField(extensionLite.descriptor, index));
}
// This is implemented here only to work around an apparent bug in the
@@ -423,46 +467,57 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
throw new UnsupportedOperationException(
"This is supposed to be overridden by subclasses.");
}
-
+
/** Set the value of an extension. */
public final <Type> BuilderType setExtension(
- final GeneratedExtension<MessageType, Type> extension,
+ final ExtensionLite<MessageType, Type> extension,
final Type value) {
- verifyExtensionContainingType(extension);
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
ensureExtensionsIsMutable();
- extensions.setField(extension.descriptor,
- extension.toFieldSetType(value));
+ extensions.setField(extensionLite.descriptor,
+ extensionLite.toFieldSetType(value));
return (BuilderType) this;
}
/** Set the value of one element of a repeated extension. */
public final <Type> BuilderType setExtension(
- final GeneratedExtension<MessageType, List<Type>> extension,
+ final ExtensionLite<MessageType, List<Type>> extension,
final int index, final Type value) {
- verifyExtensionContainingType(extension);
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
ensureExtensionsIsMutable();
- extensions.setRepeatedField(extension.descriptor, index,
- extension.singularToFieldSetType(value));
+ extensions.setRepeatedField(extensionLite.descriptor, index,
+ extensionLite.singularToFieldSetType(value));
return (BuilderType) this;
}
/** Append a value to a repeated extension. */
public final <Type> BuilderType addExtension(
- final GeneratedExtension<MessageType, List<Type>> extension,
+ final ExtensionLite<MessageType, List<Type>> extension,
final Type value) {
- verifyExtensionContainingType(extension);
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
ensureExtensionsIsMutable();
- extensions.addRepeatedField(extension.descriptor,
- extension.singularToFieldSetType(value));
+ extensions.addRepeatedField(extensionLite.descriptor,
+ extensionLite.singularToFieldSetType(value));
return (BuilderType) this;
}
/** Clear an extension. */
public final <Type> BuilderType clearExtension(
- final GeneratedExtension<MessageType, ?> extension) {
- verifyExtensionContainingType(extension);
+ final ExtensionLite<MessageType, ?> extension) {
+ GeneratedExtension<MessageType, ?> extensionLite = checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
ensureExtensionsIsMutable();
- extensions.clearField(extension.descriptor);
+ extensions.clearField(extensionLite.descriptor);
return (BuilderType) this;
}
@@ -471,44 +526,24 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
return extensions.isInitialized();
}
- /**
- * Called by subclasses to parse an unknown field or an extension.
- * @return {@code true} unless the tag is an end-group tag.
- */
- @Override
- protected boolean parseUnknownField(
- CodedInputStream input,
- CodedOutputStream unknownFieldsCodedOutput,
- ExtensionRegistryLite extensionRegistry,
- int tag) throws IOException {
- ensureExtensionsIsMutable();
- return GeneratedMessageLite.parseUnknownField(
- extensions,
- getDefaultInstanceForType(),
- input,
- unknownFieldsCodedOutput,
- extensionRegistry,
- tag);
- }
-
protected final void mergeExtensionFields(final MessageType other) {
ensureExtensionsIsMutable();
extensions.mergeFrom(((ExtendableMessage) other).extensions);
}
}
- // -----------------------------------------------------------------
+ //-----------------------------------------------------------------
/**
- * Parse an unknown field or an extension.
+ * Parse an unknown field or an extension. For use by generated code only.
* @return {@code true} unless the tag is an end-group tag.
*/
- private static <MessageType extends MessageLite>
+ protected static <MessageType extends MessageLite>
boolean parseUnknownField(
FieldSet<ExtensionDescriptor> extensions,
MessageType defaultInstance,
CodedInputStream input,
- CodedOutputStream unknownFieldsCodedOutput,
+ UnknownFieldSetLite.Builder unknownFields,
ExtensionRegistryLite extensionRegistry,
int tag) throws IOException {
int wireType = WireFormat.getTagWireType(tag);
@@ -537,7 +572,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
}
if (unknown) { // Unknown field or wrong wire type. Skip.
- return input.skipField(tag, unknownFieldsCodedOutput);
+ return unknownFields.mergeFieldFrom(tag, input);
}
if (packed) {
@@ -599,8 +634,7 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
// If the number isn't recognized as a valid value for this enum,
// write it to unknown fields object.
if (value == null) {
- unknownFieldsCodedOutput.writeRawVarint32(tag);
- unknownFieldsCodedOutput.writeUInt32NoTag(rawValue);
+ unknownFields.mergeVarintField(fieldNumber, rawValue);
return true;
}
break;
@@ -768,7 +802,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
* this type as parameters to extension accessors and ExtensionRegistry.add().
*/
public static class GeneratedExtension<
- ContainingType extends MessageLite, Type> {
+ ContainingType extends MessageLite, Type>
+ extends ExtensionLite<ContainingType, Type> {
/**
* Create a new isntance with the given parameters.
@@ -888,6 +923,18 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
return value;
}
}
+
+ public FieldType getLiteType() {
+ return descriptor.getLiteType();
+ }
+
+ public boolean isRepeated() {
+ return descriptor.isRepeated;
+ }
+
+ public Type getDefaultValue() {
+ return defaultValue;
+ }
}
/**
@@ -897,8 +944,8 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
static final class SerializedForm implements Serializable {
private static final long serialVersionUID = 0L;
- private String messageClassName;
- private byte[] asBytes;
+ private final String messageClassName;
+ private final byte[] asBytes;
/**
* Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}.
@@ -918,19 +965,17 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
protected Object readResolve() throws ObjectStreamException {
try {
Class messageClass = Class.forName(messageClassName);
- Method newBuilder = messageClass.getMethod("newBuilder");
- MessageLite.Builder builder =
- (MessageLite.Builder) newBuilder.invoke(null);
- builder.mergeFrom(asBytes);
- return builder.buildPartial();
+ Parser<?> parser =
+ (Parser<?>) messageClass.getField("PARSER").get(null);
+ return parser.parsePartialFrom(asBytes);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unable to find proto buffer class", e);
- } catch (NoSuchMethodException e) {
- throw new RuntimeException("Unable to find newBuilder method", e);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Unable to find PARSER", e);
+ } catch (SecurityException e) {
+ throw new RuntimeException("Unable to call PARSER", e);
} catch (IllegalAccessException e) {
- throw new RuntimeException("Unable to call newBuilder method", e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException("Error calling newBuilder", e.getCause());
+ throw new RuntimeException("Unable to call parseFrom method", e);
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException("Unable to understand proto buffer", e);
}
@@ -946,4 +991,18 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
protected Object writeReplace() throws ObjectStreamException {
return new SerializedForm(this);
}
+
+ /**
+ * Checks that the {@link Extension} is Lite and returns it as a
+ * {@link GeneratedExtension}.
+ */
+ private static <MessageType extends ExtendableMessage<MessageType>, T>
+ GeneratedExtension<MessageType, T> checkIsLite(
+ ExtensionLite<MessageType, T> extension) {
+ if (!extension.isLite()) {
+ throw new IllegalArgumentException("Expected a lite extension.");
+ }
+
+ return (GeneratedExtension<MessageType, T>) extension;
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
index 48d29e69..ba0f526b 100644
--- a/java/src/main/java/com/google/protobuf/Internal.java
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -33,8 +33,14 @@ package com.google.protobuf;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
+import java.util.AbstractList;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
/**
* The classes contained within are used internally by the Protocol Buffer
@@ -388,4 +394,164 @@ public class Internal {
public static final ByteBuffer EMPTY_BYTE_BUFFER =
ByteBuffer.wrap(EMPTY_BYTE_ARRAY);
+
+ /**
+ * Provides an immutable view of List<T> around a List<F>.
+ *
+ * Protobuf internal. Used in protobuf generated code only.
+ */
+ public static class ListAdapter<F, T> extends AbstractList<T> {
+ /**
+ * Convert individual elements of the List from F to T.
+ */
+ public interface Converter<F, T> {
+ T convert(F from);
+ }
+
+ private final List<F> fromList;
+ private final Converter<F, T> converter;
+
+ public ListAdapter(List<F> fromList, Converter<F, T> converter) {
+ this.fromList = fromList;
+ this.converter = converter;
+ }
+
+ @Override
+ public T get(int index) {
+ return converter.convert(fromList.get(index));
+ }
+
+ @Override
+ public int size() {
+ return fromList.size();
+ }
+ }
+
+ /**
+ * Wrap around a Map<K, RealValue> and provide a Map<K, V> interface.
+ */
+ public static class MapAdapter<K, V, RealValue> extends AbstractMap<K, V> {
+ /**
+ * An interface used to convert between two types.
+ */
+ public interface Converter<A, B> {
+ B doForward(A object);
+ A doBackward(B object);
+ }
+
+ public static <T extends EnumLite> Converter<Integer, T> newEnumConverter(
+ final EnumLiteMap<T> enumMap, final T unrecognizedValue) {
+ return new Converter<Integer, T>() {
+ public T doForward(Integer value) {
+ T result = enumMap.findValueByNumber(value);
+ return result == null ? unrecognizedValue : result;
+ }
+ public Integer doBackward(T value) {
+ return value.getNumber();
+ }
+ };
+ }
+
+ private final Map<K, RealValue> realMap;
+ private final Converter<RealValue, V> valueConverter;
+
+ public MapAdapter(Map<K, RealValue> realMap,
+ Converter<RealValue, V> valueConverter) {
+ this.realMap = realMap;
+ this.valueConverter = valueConverter;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(Object key) {
+ RealValue result = realMap.get(key);
+ if (result == null) {
+ return null;
+ }
+ return valueConverter.doForward(result);
+ }
+
+ @Override
+ public V put(K key, V value) {
+ RealValue oldValue = realMap.put(key, valueConverter.doBackward(value));
+ if (oldValue == null) {
+ return null;
+ }
+ return valueConverter.doForward(oldValue);
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<K, V>> entrySet() {
+ return new SetAdapter(realMap.entrySet());
+ }
+
+ private class SetAdapter extends AbstractSet<Map.Entry<K, V>> {
+ private final Set<Map.Entry<K, RealValue>> realSet;
+ public SetAdapter(Set<Map.Entry<K, RealValue>> realSet) {
+ this.realSet = realSet;
+ }
+
+ @Override
+ public Iterator<java.util.Map.Entry<K, V>> iterator() {
+ return new IteratorAdapter(realSet.iterator());
+ }
+
+ @Override
+ public int size() {
+ return realSet.size();
+ }
+ }
+
+ private class IteratorAdapter implements Iterator<Map.Entry<K, V>> {
+ private final Iterator<Map.Entry<K, RealValue>> realIterator;
+
+ public IteratorAdapter(
+ Iterator<Map.Entry<K, RealValue>> realIterator) {
+ this.realIterator = realIterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return realIterator.hasNext();
+ }
+
+ @Override
+ public java.util.Map.Entry<K, V> next() {
+ return new EntryAdapter(realIterator.next());
+ }
+
+ @Override
+ public void remove() {
+ realIterator.remove();
+ }
+ }
+
+ private class EntryAdapter implements Map.Entry<K, V> {
+ private final Map.Entry<K, RealValue> realEntry;
+
+ public EntryAdapter(Map.Entry<K, RealValue> realEntry) {
+ this.realEntry = realEntry;
+ }
+
+ @Override
+ public K getKey() {
+ return realEntry.getKey();
+ }
+
+ @Override
+ public V getValue() {
+ return valueConverter.doForward(realEntry.getValue());
+ }
+
+ @Override
+ public V setValue(V value) {
+ RealValue oldValue = realEntry.setValue(
+ valueConverter.doBackward(value));
+ if (oldValue == null) {
+ return null;
+ }
+ return valueConverter.doForward(oldValue);
+ }
+ }
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
index 61c7e1ea..2d40a51f 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -74,6 +74,10 @@ public class LazyStringArrayList extends AbstractList<String>
list = new ArrayList<Object>();
}
+ public LazyStringArrayList(int intialCapacity) {
+ list = new ArrayList<Object>(intialCapacity);
+ }
+
public LazyStringArrayList(LazyStringList from) {
list = new ArrayList<Object>(from.size());
addAll(from);
diff --git a/java/src/main/java/com/google/protobuf/LiteralByteString.java b/java/src/main/java/com/google/protobuf/LiteralByteString.java
index 83e71e93..127c574d 100644
--- a/java/src/main/java/com/google/protobuf/LiteralByteString.java
+++ b/java/src/main/java/com/google/protobuf/LiteralByteString.java
@@ -190,6 +190,15 @@ class LiteralByteString extends ByteString {
}
if (other instanceof LiteralByteString) {
+ LiteralByteString otherAsLiteral = (LiteralByteString) other;
+ // If we know the hash codes and they are not equal, we know the byte
+ // strings are not equal.
+ if (hash != 0
+ && otherAsLiteral.hash != 0
+ && hash != otherAsLiteral.hash) {
+ return false;
+ }
+
return equalsRange((LiteralByteString) other, 0, size());
} else if (other instanceof RopeByteString) {
return other.equals(this);
diff --git a/java/src/main/java/com/google/protobuf/MapEntry.java b/java/src/main/java/com/google/protobuf/MapEntry.java
new file mode 100644
index 00000000..8e3551b6
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MapEntry.java
@@ -0,0 +1,433 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Implements MapEntry messages.
+ *
+ * In reflection API, map fields will be treated as repeated message fields and
+ * each map entry is accessed as a message. This MapEntry class is used to
+ * represent these map entry messages in reflection API.
+ *
+ * Protobuf internal. Users shouldn't use this class.
+ */
+public final class MapEntry<K, V> extends AbstractMessage {
+ private static class Metadata<K, V> {
+ public final Descriptor descriptor;
+ public final MapEntry<K, V> defaultInstance;
+ public final AbstractParser<MapEntry<K, V>> parser;
+
+ public Metadata(
+ final Descriptor descriptor, final MapEntry<K, V> defaultInstance) {
+ this.descriptor = descriptor;
+ this.defaultInstance = defaultInstance;
+ final Metadata<K, V> thisMetadata = this;
+ this.parser = new AbstractParser<MapEntry<K, V>>() {
+ private final Parser<MapEntryLite<K, V>> dataParser =
+ defaultInstance.data.getParserForType();
+ @Override
+ public MapEntry<K, V> parsePartialFrom(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ MapEntryLite<K, V> data =
+ dataParser.parsePartialFrom(input, extensionRegistry);
+ return new MapEntry<K, V>(thisMetadata, data);
+ }
+
+ };
+ }
+ }
+
+ private final Metadata<K, V> metadata;
+ private final MapEntryLite<K, V> data;
+
+ /** Create a default MapEntry instance. */
+ private MapEntry(Descriptor descriptor,
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ this.data = MapEntryLite.newDefaultInstance(
+ keyType, defaultKey, valueType, defaultValue);
+ this.metadata = new Metadata<K, V>(descriptor, this);
+ }
+
+ /** Create a new MapEntry message. */
+ private MapEntry(Metadata<K, V> metadata, MapEntryLite<K, V> data) {
+ this.metadata = metadata;
+ this.data = data;
+ }
+
+ /**
+ * Create a default MapEntry instance. A default MapEntry instance should be
+ * created only once for each map entry message type. Generated code should
+ * store the created default instance and use it later to create new MapEntry
+ * messages of the same type.
+ */
+ public static <K, V> MapEntry<K, V> newDefaultInstance(
+ Descriptor descriptor,
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ return new MapEntry<K, V>(
+ descriptor, keyType, defaultKey, valueType, defaultValue);
+ }
+
+ public K getKey() {
+ return data.getKey();
+ }
+
+ public V getValue() {
+ return data.getValue();
+ }
+
+ @Override
+ public int getSerializedSize() {
+ return data.getSerializedSize();
+ }
+
+ @Override
+ public void writeTo(CodedOutputStream output) throws IOException {
+ data.writeTo(output);
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return data.isInitialized();
+ }
+
+ @Override
+ public Parser<MapEntry<K, V>> getParserForType() {
+ return metadata.parser;
+ }
+
+ @Override
+ public Builder<K, V> newBuilderForType() {
+ return new Builder<K, V>(metadata);
+ }
+
+ @Override
+ public Builder<K, V> toBuilder() {
+ return new Builder<K, V>(metadata, data);
+ }
+
+ @Override
+ public MapEntry<K, V> getDefaultInstanceForType() {
+ return metadata.defaultInstance;
+ }
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return metadata.descriptor;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ for (final FieldDescriptor field : metadata.descriptor.getFields()) {
+ if (hasField(field)) {
+ result.put(field, getField(field));
+ }
+ }
+ return Collections.unmodifiableMap(result);
+ }
+
+ private void checkFieldDescriptor(FieldDescriptor field) {
+ if (field.getContainingType() != metadata.descriptor) {
+ throw new RuntimeException(
+ "Wrong FieldDescriptor \"" + field.getFullName()
+ + "\" used in message \"" + metadata.descriptor.getFullName());
+ }
+ }
+
+ @Override
+ public boolean hasField(FieldDescriptor field) {
+ checkFieldDescriptor(field);;
+ // A MapEntry always contains two fields.
+ return true;
+ }
+
+ @Override
+ public Object getField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ Object result = field.getNumber() == 1 ? getKey() : getValue();
+ // Convert enums to EnumValueDescriptor.
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ result = field.getEnumType().findValueByNumberCreatingIfUnknown(
+ (java.lang.Integer) result);
+ }
+ return result;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(FieldDescriptor field) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Object getRepeatedField(FieldDescriptor field, int index) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return UnknownFieldSet.getDefaultInstance();
+ }
+
+ /**
+ * Builder to create {@link MapEntry} messages.
+ */
+ public static class Builder<K, V>
+ extends AbstractMessage.Builder<Builder<K, V>> {
+ private final Metadata<K, V> metadata;
+ private MapEntryLite<K, V> data;
+ private MapEntryLite.Builder<K, V> dataBuilder;
+
+ private Builder(Metadata<K, V> metadata) {
+ this.metadata = metadata;
+ this.data = metadata.defaultInstance.data;
+ this.dataBuilder = null;
+ }
+
+ private Builder(Metadata<K, V> metadata, MapEntryLite<K, V> data) {
+ this.metadata = metadata;
+ this.data = data;
+ this.dataBuilder = null;
+ }
+
+ public K getKey() {
+ return dataBuilder == null ? data.getKey() : dataBuilder.getKey();
+ }
+
+ public V getValue() {
+ return dataBuilder == null ? data.getValue() : dataBuilder.getValue();
+ }
+
+ private void ensureMutable() {
+ if (dataBuilder == null) {
+ dataBuilder = data.toBuilder();
+ }
+ }
+
+ public Builder<K, V> setKey(K key) {
+ ensureMutable();
+ dataBuilder.setKey(key);
+ return this;
+ }
+
+ public Builder<K, V> clearKey() {
+ ensureMutable();
+ dataBuilder.clearKey();
+ return this;
+ }
+
+ public Builder<K, V> setValue(V value) {
+ ensureMutable();
+ dataBuilder.setValue(value);
+ return this;
+ }
+
+ public Builder<K, V> clearValue() {
+ ensureMutable();
+ dataBuilder.clearValue();
+ return this;
+ }
+
+ @Override
+ public MapEntry<K, V> build() {
+ MapEntry<K, V> result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @Override
+ public MapEntry<K, V> buildPartial() {
+ if (dataBuilder != null) {
+ data = dataBuilder.build();
+ dataBuilder = null;
+ }
+ return new MapEntry<K, V>(metadata, data);
+ }
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return metadata.descriptor;
+ }
+
+ private void checkFieldDescriptor(FieldDescriptor field) {
+ if (field.getContainingType() != metadata.descriptor) {
+ throw new RuntimeException(
+ "Wrong FieldDescriptor \"" + field.getFullName()
+ + "\" used in message \"" + metadata.descriptor.getFullName());
+ }
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder newBuilderForField(
+ FieldDescriptor field) {
+ checkFieldDescriptor(field);;
+ // This method should be called for message fields and in a MapEntry
+ // message only the value field can possibly be a message field.
+ if (field.getNumber() != 2
+ || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+ throw new RuntimeException(
+ "\"" + field.getFullName() + "\" is not a message value field.");
+ }
+ return ((Message) data.getValue()).newBuilderForType();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Builder<K, V> setField(FieldDescriptor field, Object value) {
+ checkFieldDescriptor(field);
+ if (field.getNumber() == 1) {
+ setKey((K) value);
+ } else {
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ value = ((EnumValueDescriptor) value).getNumber();
+ }
+ setValue((V) value);
+ }
+ return this;
+ }
+
+ @Override
+ public Builder<K, V> clearField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ if (field.getNumber() == 1) {
+ clearKey();
+ } else {
+ clearValue();
+ }
+ return this;
+ }
+
+ @Override
+ public Builder<K, V> setRepeatedField(FieldDescriptor field, int index,
+ Object value) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Builder<K, V> addRepeatedField(FieldDescriptor field, Object value) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Builder<K, V> setUnknownFields(UnknownFieldSet unknownFields) {
+ // Unknown fields are discarded for MapEntry message.
+ return this;
+ }
+
+ @Override
+ public MapEntry<K, V> getDefaultInstanceForType() {
+ return metadata.defaultInstance;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ if (dataBuilder != null) {
+ return dataBuilder.isInitialized();
+ } else {
+ return data.isInitialized();
+ }
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ for (final FieldDescriptor field : metadata.descriptor.getFields()) {
+ if (hasField(field)) {
+ result.put(field, getField(field));
+ }
+ }
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public boolean hasField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ return true;
+ }
+
+ @Override
+ public Object getField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ Object result = field.getNumber() == 1 ? getKey() : getValue();
+ // Convert enums to EnumValueDescriptor.
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ result = field.getEnumType().findValueByNumberCreatingIfUnknown(
+ (java.lang.Integer) result);
+ }
+ return result;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(FieldDescriptor field) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Object getRepeatedField(FieldDescriptor field, int index) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return UnknownFieldSet.getDefaultInstance();
+ }
+
+ @Override
+ public Builder<K, V> clone() {
+ if (dataBuilder == null) {
+ return new Builder<K, V>(metadata, data);
+ } else {
+ return new Builder<K, V>(metadata, dataBuilder.build());
+ }
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/MapEntryLite.java b/java/src/main/java/com/google/protobuf/MapEntryLite.java
new file mode 100644
index 00000000..bcffa946
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MapEntryLite.java
@@ -0,0 +1,331 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+
+/**
+ * Implements the lite version of map entry messages.
+ *
+ * This class serves as an utility class to help do serialization/parsing of
+ * map entries. It's used in generated code and also in the full version
+ * MapEntry message.
+ *
+ * Protobuf internal. Users shouldn't use.
+ */
+public class MapEntryLite<K, V> extends AbstractMessageLite {
+ private static class Metadata<K, V> {
+ public final MapEntryLite<K, V> defaultInstance;
+ public final WireFormat.FieldType keyType;
+ public final WireFormat.FieldType valueType;
+ public final Parser<MapEntryLite<K, V>> parser;
+ public Metadata(
+ MapEntryLite<K, V> defaultInstance,
+ WireFormat.FieldType keyType,
+ WireFormat.FieldType valueType) {
+ this.defaultInstance = defaultInstance;
+ this.keyType = keyType;
+ this.valueType = valueType;
+ final Metadata<K, V> finalThis = this;
+ this.parser = new AbstractParser<MapEntryLite<K, V>>() {
+ @Override
+ public MapEntryLite<K, V> parsePartialFrom(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return new MapEntryLite<K, V>(finalThis, input, extensionRegistry);
+ }
+ };
+ }
+ }
+
+ private static final int KEY_FIELD_NUMBER = 1;
+ private static final int VALUE_FIELD_NUMBER = 2;
+
+ private final Metadata<K, V> metadata;
+ private final K key;
+ private final V value;
+
+ /** Creates a default MapEntryLite message instance. */
+ private MapEntryLite(
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ this.metadata = new Metadata<K, V>(this, keyType, valueType);
+ this.key = defaultKey;
+ this.value = defaultValue;
+ }
+
+ /** Creates a new MapEntryLite message. */
+ private MapEntryLite(Metadata<K, V> metadata, K key, V value) {
+ this.metadata = metadata;
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ /**
+ * Creates a default MapEntryLite message instance.
+ *
+ * This method is used by generated code to create the default instance for
+ * a map entry message. The created default instance should be used to create
+ * new map entry messages of the same type. For each map entry message, only
+ * one default instance should be created.
+ */
+ public static <K, V> MapEntryLite<K, V> newDefaultInstance(
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ return new MapEntryLite<K, V>(
+ keyType, defaultKey, valueType, defaultValue);
+ }
+
+ @Override
+ public void writeTo(CodedOutputStream output) throws IOException {
+ writeField(KEY_FIELD_NUMBER, metadata.keyType, key, output);
+ writeField(VALUE_FIELD_NUMBER, metadata.valueType, value, output);
+ }
+
+ private void writeField(
+ int number, WireFormat.FieldType type, Object value,
+ CodedOutputStream output) throws IOException {
+ output.writeTag(number, type.getWireType());
+ FieldSet.writeElementNoTag(output, type, value);
+ }
+
+ private volatile int cachedSerializedSize = -1;
+ @Override
+ public int getSerializedSize() {
+ if (cachedSerializedSize != -1) {
+ return cachedSerializedSize;
+ }
+ int size = 0;
+ size += getFieldSize(KEY_FIELD_NUMBER, metadata.keyType, key);
+ size += getFieldSize(VALUE_FIELD_NUMBER, metadata.valueType, value);
+ cachedSerializedSize = size;
+ return size;
+ }
+
+ private int getFieldSize(
+ int number, WireFormat.FieldType type, Object value) {
+ return CodedOutputStream.computeTagSize(number)
+ + FieldSet.computeElementSizeNoTag(type, value);
+ }
+
+ /** Parsing constructor. */
+ private MapEntryLite(
+ Metadata<K, V> metadata,
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ K key = metadata.defaultInstance.key;
+ V value = metadata.defaultInstance.value;
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+ if (tag == WireFormat.makeTag(
+ KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
+ key = mergeField(
+ input, extensionRegistry, metadata.keyType, key);
+ } else if (tag == WireFormat.makeTag(
+ VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) {
+ value = mergeField(
+ input, extensionRegistry, metadata.valueType, value);
+ } else {
+ if (!input.skipField(tag)) {
+ break;
+ }
+ }
+ }
+ this.metadata = metadata;
+ this.key = key;
+ this.value = value;
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e.getMessage())
+ .setUnfinishedMessage(this);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> T mergeField(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry,
+ WireFormat.FieldType type, T value) throws IOException {
+ switch (type) {
+ case MESSAGE:
+ MessageLite.Builder subBuilder = ((MessageLite) value).toBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ return (T) subBuilder.buildPartial();
+ case ENUM:
+ return (T) (java.lang.Integer) input.readEnum();
+ case GROUP:
+ throw new RuntimeException("Groups are not allowed in maps.");
+ default:
+ return (T) FieldSet.readPrimitiveField(input, type, true);
+ }
+ }
+
+ @Override
+ public Parser<MapEntryLite<K, V>> getParserForType() {
+ return metadata.parser;
+ }
+
+ @Override
+ public Builder<K, V> newBuilderForType() {
+ return new Builder<K, V>(metadata);
+ }
+
+ @Override
+ public Builder<K, V> toBuilder() {
+ return new Builder<K, V>(metadata, key, value);
+ }
+
+ @Override
+ public MapEntryLite<K, V> getDefaultInstanceForType() {
+ return metadata.defaultInstance;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
+ return ((MessageLite) value).isInitialized();
+ }
+ return true;
+ }
+
+ /**
+ * Builder used to create {@link MapEntryLite} messages.
+ */
+ public static class Builder<K, V>
+ extends AbstractMessageLite.Builder<Builder<K, V>> {
+ private final Metadata<K, V> metadata;
+ private K key;
+ private V value;
+
+ private Builder(Metadata<K, V> metadata) {
+ this.metadata = metadata;
+ this.key = metadata.defaultInstance.key;
+ this.value = metadata.defaultInstance.value;
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public Builder<K, V> setKey(K key) {
+ this.key = key;
+ return this;
+ }
+
+ public Builder<K, V> setValue(V value) {
+ this.value = value;
+ return this;
+ }
+
+ public Builder<K, V> clearKey() {
+ this.key = metadata.defaultInstance.key;
+ return this;
+ }
+
+ public Builder<K, V> clearValue() {
+ this.value = metadata.defaultInstance.value;
+ return this;
+ }
+
+ @Override
+ public Builder<K, V> clear() {
+ this.key = metadata.defaultInstance.key;
+ this.value = metadata.defaultInstance.value;
+ return this;
+ }
+
+ @Override
+ public MapEntryLite<K, V> build() {
+ MapEntryLite<K, V> result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @Override
+ public MapEntryLite<K, V> buildPartial() {
+ return new MapEntryLite<K, V>(metadata, key, value);
+ }
+
+ @Override
+ public MessageLite getDefaultInstanceForType() {
+ return metadata.defaultInstance;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
+ return ((MessageLite) value).isInitialized();
+ }
+ return true;
+ }
+
+ private Builder(Metadata<K, V> metadata, K key, V value) {
+ this.metadata = metadata;
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public Builder<K, V> clone() {
+ return new Builder<K, V>(metadata, key, value);
+ }
+
+ @Override
+ public Builder<K, V> mergeFrom(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ MapEntryLite<K, V> entry =
+ new MapEntryLite<K, V>(metadata, input, extensionRegistry);
+ this.key = entry.key;
+ this.value = entry.value;
+ return this;
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/MapField.java b/java/src/main/java/com/google/protobuf/MapField.java
new file mode 100644
index 00000000..5bd70dbb
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MapField.java
@@ -0,0 +1,259 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Internal representation of map fields in generated messages.
+ *
+ * This class supports accessing the map field as a {@link Map} to be used in
+ * generated API and also supports accessing the field as a {@link List} to be
+ * used in reflection API. It keeps track of where the data is currently stored
+ * and do necessary conversions between map and list.
+ *
+ * This class is a protobuf implementation detail. Users shouldn't use this
+ * class directly.
+ *
+ * THREAD-SAFETY NOTE: Read-only access is thread-safe. Users can call getMap()
+ * and getList() concurrently in multiple threads. If write-access is needed,
+ * all access must be synchronized.
+ */
+public class MapField<K, V> {
+ /**
+ * Indicates where the data of this map field is currently stored.
+ *
+ * MAP: Data is stored in mapData.
+ * LIST: Data is stored in listData.
+ * BOTH: mapData and listData have the same data.
+ *
+ * When the map field is accessed (through generated API or reflection API),
+ * it will shift between these 3 modes:
+ *
+ * getMap() getList() getMutableMap() getMutableList()
+ * MAP MAP BOTH MAP LIST
+ * LIST BOTH LIST MAP LIST
+ * BOTH BOTH BOTH MAP LIST
+ *
+ * As the map field changes its mode, the list/map reference returned in a
+ * previous method call may be invalidated.
+ */
+ private enum StorageMode {MAP, LIST, BOTH}
+
+ private volatile StorageMode mode;
+ private Map<K, V> mapData;
+ private List<Message> listData;
+
+ // Convert between a map entry Message and a key-value pair.
+ private static interface Converter<K, V> {
+ Message convertKeyAndValueToMessage(K key, V value);
+ void convertMessageToKeyAndValue(Message message, Map<K, V> map);
+
+ Message getMessageDefaultInstance();
+ }
+
+ private static class ImmutableMessageConverter<K, V> implements Converter<K, V> {
+ private final MapEntry<K, V> defaultEntry;
+ public ImmutableMessageConverter(MapEntry<K, V> defaultEntry) {
+ this.defaultEntry = defaultEntry;
+ }
+
+ public Message convertKeyAndValueToMessage(K key, V value) {
+ return defaultEntry.newBuilderForType().setKey(key).setValue(value).build();
+ }
+
+ public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
+ MapEntry<K, V> entry = (MapEntry<K, V>) message;
+ map.put(entry.getKey(), entry.getValue());
+ }
+
+ public Message getMessageDefaultInstance() {
+ return defaultEntry;
+ }
+ }
+
+
+ private final Converter<K, V> converter;
+
+ private MapField(
+ Converter<K, V> converter,
+ StorageMode mode,
+ Map<K, V> mapData,
+ List<Message> listData) {
+ this.converter = converter;
+ this.mode = mode;
+ this.mapData = mapData;
+ this.listData = listData;
+ }
+
+ private MapField(
+ MapEntry<K, V> defaultEntry,
+ StorageMode mode,
+ Map<K, V> mapData,
+ List<Message> listData) {
+ this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData, listData);
+ }
+
+
+ /** Returns an immutable empty MapField. */
+ public static <K, V> MapField<K, V> emptyMapField(
+ MapEntry<K, V> defaultEntry) {
+ return new MapField<K, V>(
+ defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap(), null);
+ }
+
+
+ /** Creates a new mutable empty MapField. */
+ public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry) {
+ return new MapField<K, V>(
+ defaultEntry, StorageMode.MAP, new HashMap<K, V>(), null);
+ }
+
+
+ private Message convertKeyAndValueToMessage(K key, V value) {
+ return converter.convertKeyAndValueToMessage(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
+ converter.convertMessageToKeyAndValue(message, map);
+ }
+
+ private List<Message> convertMapToList(Map<K, V> mapData) {
+ List<Message> listData = new ArrayList<Message>();
+ for (Map.Entry<K, V> entry : mapData.entrySet()) {
+ listData.add(
+ convertKeyAndValueToMessage(
+ entry.getKey(), entry.getValue()));
+ }
+ return listData;
+ }
+
+ private Map<K, V> convertListToMap(List<Message> listData) {
+ Map<K, V> mapData = new HashMap<K, V>();
+ for (Message item : listData) {
+ convertMessageToKeyAndValue(item, mapData);
+ }
+ return mapData;
+ }
+
+ /** Returns the content of this MapField as a read-only Map. */
+ public Map<K, V> getMap() {
+ if (mode == StorageMode.LIST) {
+ synchronized (this) {
+ if (mode == StorageMode.LIST) {
+ mapData = convertListToMap(listData);
+ mode = StorageMode.BOTH;
+ }
+ }
+ }
+ return Collections.unmodifiableMap(mapData);
+ }
+
+ /** Gets a mutable Map view of this MapField. */
+ public Map<K, V> getMutableMap() {
+ if (mode != StorageMode.MAP) {
+ if (mode == StorageMode.LIST) {
+ mapData = convertListToMap(listData);
+ }
+ listData = null;
+ mode = StorageMode.MAP;
+ }
+ return mapData;
+ }
+
+ public void mergeFrom(MapField<K, V> other) {
+ getMutableMap().putAll(MapFieldLite.copy(other.getMap()));
+ }
+
+ public void clear() {
+ mapData = new HashMap<K, V>();
+ mode = StorageMode.MAP;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof MapField)) {
+ return false;
+ }
+ MapField<K, V> other = (MapField<K, V>) object;
+ return MapFieldLite.<K, V>equals(getMap(), other.getMap());
+ }
+
+ @Override
+ public int hashCode() {
+ return MapFieldLite.<K, V>calculateHashCodeForMap(getMap());
+ }
+
+ /** Returns a deep copy of this MapField. */
+ public MapField<K, V> copy() {
+ return new MapField<K, V>(
+ converter, StorageMode.MAP, MapFieldLite.copy(getMap()), null);
+ }
+
+ /** Gets the content of this MapField as a read-only List. */
+ List<Message> getList() {
+ if (mode == StorageMode.MAP) {
+ synchronized (this) {
+ if (mode == StorageMode.MAP) {
+ listData = convertMapToList(mapData);
+ mode = StorageMode.BOTH;
+ }
+ }
+ }
+ return Collections.unmodifiableList(listData);
+ }
+
+ /** Gets a mutable List view of this MapField. */
+ List<Message> getMutableList() {
+ if (mode != StorageMode.LIST) {
+ if (mode == StorageMode.MAP) {
+ listData = convertMapToList(mapData);
+ }
+ mapData = null;
+ mode = StorageMode.LIST;
+ }
+ return listData;
+ }
+
+ /**
+ * Gets the default instance of the message stored in the list view of this
+ * map field.
+ */
+ Message getMapEntryMessageDefaultInstance() {
+ return converter.getMessageDefaultInstance();
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/MapFieldLite.java b/java/src/main/java/com/google/protobuf/MapFieldLite.java
new file mode 100644
index 00000000..eea36d9e
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MapFieldLite.java
@@ -0,0 +1,182 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Internal representation of map fields in generated lite-runtime messages.
+ *
+ * This class is a protobuf implementation detail. Users shouldn't use this
+ * class directly.
+ */
+public class MapFieldLite<K, V> {
+ private Map<K, V> mapData;
+
+ private MapFieldLite(Map<K, V> mapData) {
+ this.mapData = mapData;
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static final MapFieldLite EMPTY_MAP_FIELD =
+ new MapFieldLite(Collections.emptyMap());
+
+ /** Returns an singleton immutable empty MapFieldLite instance. */
+ @SuppressWarnings({"unchecked", "cast"})
+ public static <K, V> MapFieldLite<K, V> emptyMapField() {
+ return (MapFieldLite<K, V>) EMPTY_MAP_FIELD;
+ }
+
+ /** Creates a new MapFieldLite instance. */
+ public static <K, V> MapFieldLite<K, V> newMapField() {
+ return new MapFieldLite<K, V>(new HashMap<K, V>());
+ }
+
+ /** Gets the content of this MapField as a read-only Map. */
+ public Map<K, V> getMap() {
+ return Collections.unmodifiableMap(mapData);
+ }
+
+ /** Gets a mutable Map view of this MapField. */
+ public Map<K, V> getMutableMap() {
+ return mapData;
+ }
+
+ public void mergeFrom(MapFieldLite<K, V> other) {
+ mapData.putAll(copy(other.mapData));
+ }
+
+ public void clear() {
+ mapData.clear();
+ }
+
+ private static boolean equals(Object a, Object b) {
+ if (a instanceof byte[] && b instanceof byte[]) {
+ return Arrays.equals((byte[]) a, (byte[]) b);
+ }
+ return a.equals(b);
+ }
+
+ /**
+ * Checks whether two {@link Map}s are equal. We don't use the default equals
+ * method of {@link Map} because it compares by identity not by content for
+ * byte arrays.
+ */
+ static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) {
+ if (a == b) {
+ return true;
+ }
+ if (a.size() != a.size()) {
+ return false;
+ }
+ for (Map.Entry<K, V> entry : a.entrySet()) {
+ if (!b.containsKey(entry.getKey())) {
+ return false;
+ }
+ if (!equals(entry.getValue(), b.get(entry.getKey()))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether two map fields are equal.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof MapFieldLite)) {
+ return false;
+ }
+ MapFieldLite<K, V> other = (MapFieldLite<K, V>) object;
+ return equals(mapData, other.mapData);
+ }
+
+ private static int calculateHashCodeForObject(Object a) {
+ if (a instanceof byte[]) {
+ return LiteralByteString.hashCode((byte[]) a);
+ }
+ if (a instanceof Internal.EnumLite) {
+ return Internal.hashEnum((Internal.EnumLite) a);
+ }
+ return a.hashCode();
+ }
+
+ /**
+ * Calculates the hash code for a {@link Map}. We don't use the default hash
+ * code method of {@link Map} because for byte arrays and protobuf enums it
+ * use {@link Object#hashCode()}.
+ */
+ static <K, V> int calculateHashCodeForMap(Map<K, V> a) {
+ int result = 0;
+ for (Map.Entry<K, V> entry : a.entrySet()) {
+ result += calculateHashCodeForObject(entry.getKey())
+ ^ calculateHashCodeForObject(entry.getValue());
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return calculateHashCodeForMap(mapData);
+ }
+
+ private static Object copy(Object object) {
+ if (object instanceof byte[]) {
+ byte[] data = (byte[]) object;
+ return Arrays.copyOf(data, data.length);
+ }
+ return object;
+ }
+
+ /**
+ * Makes a deep copy of a {@link Map}. Immutable objects in the map will be
+ * shared (e.g., integers, strings, immutable messages) and mutable ones will
+ * have a copy (e.g., byte arrays, mutable messages).
+ */
+ @SuppressWarnings("unchecked")
+ static <K, V> Map<K, V> copy(Map<K, V> map) {
+ Map<K, V> result = new HashMap<K, V>();
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ result.put(entry.getKey(), (V) copy(entry.getValue()));
+ }
+ return result;
+ }
+
+ /** Returns a deep copy of this map field. */
+ public MapFieldLite<K, V> copy() {
+ return new MapFieldLite<K, V>(copy(mapData));
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index 5673d3bb..5c75b58b 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -168,6 +168,25 @@ public interface Message extends MessageLite, MessageOrBuilder {
Builder getFieldBuilder(Descriptors.FieldDescriptor field);
/**
+ * Get a nested builder instance for the given repeated field instance.
+ * <p>
+ * Normally, we hold a reference to the immutable message object for the
+ * message type field. Some implementations(the generated message builders),
+ * however, can also hold a reference to the builder object (a nested
+ * builder) for the field.
+ * <p>
+ * If the field is already backed up by a nested builder, the nested builder
+ * will be returned. Otherwise, a new field builder will be created and
+ * returned. The original message field (if exist) will be merged into the
+ * field builder, which will then be nested into its parent builder.
+ * <p>
+ * NOTE: implementations that do not support nested builders will throw
+ * <code>UnsupportedException</code>.
+ */
+ Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field,
+ int index);
+
+ /**
* 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.
diff --git a/java/src/main/java/com/google/protobuf/MessageReflection.java b/java/src/main/java/com/google/protobuf/MessageReflection.java
index edb5b5c2..06e3c99b 100644
--- a/java/src/main/java/com/google/protobuf/MessageReflection.java
+++ b/java/src/main/java/com/google/protobuf/MessageReflection.java
@@ -752,13 +752,18 @@ class MessageReflection {
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;
+ if (field.getFile().supportsUnknownEnumValue()) {
+ target.addRepeatedField(field,
+ field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue));
+ } else {
+ 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);
}
- target.addRepeatedField(field, value);
}
} else {
while (input.getBytesUntilLimit() > 0) {
@@ -783,12 +788,16 @@ class MessageReflection {
}
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;
+ if (field.getFile().supportsUnknownEnumValue()) {
+ value = field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue);
+ } else {
+ 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:
diff --git a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index 22760d3a..63535ac8 100644
--- a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -367,22 +367,28 @@ public class RepeatedFieldBuilder
throw new NullPointerException();
}
}
+
+ // If we can inspect the size, we can more efficiently add messages.
+ int size = -1;
if (values instanceof Collection) {
@SuppressWarnings("unchecked") final
Collection<MType> collection = (Collection<MType>) values;
if (collection.size() == 0) {
return this;
}
- ensureMutableMessageList();
- for (MType value : values) {
- addMessage(value);
- }
- } else {
- ensureMutableMessageList();
- for (MType value : values) {
- addMessage(value);
- }
+ size = collection.size();
+ }
+ ensureMutableMessageList();
+
+ if (size >= 0 && messages instanceof ArrayList) {
+ ((ArrayList<MType>) messages)
+ .ensureCapacity(messages.size() + size);
}
+
+ for (MType value : values) {
+ addMessage(value);
+ }
+
onChanged();
incrementModCounts();
return this;
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 57d0ca68..44674811 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -1211,6 +1211,7 @@ public final class TextFormat {
private SingularOverwritePolicy singularOverwritePolicy =
SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES;
+
/**
* Sets parser behavior when a non-repeated field appears more than once.
*/
@@ -1418,6 +1419,12 @@ public final class TextFormat {
} else {
consumeFieldValue(tokenizer, extensionRegistry, target, field, extension);
}
+
+ // For historical reasons, fields may optionally be separated by commas or
+ // semicolons.
+ if (!tokenizer.tryConsume(";")) {
+ tokenizer.tryConsume(",");
+ }
}
/**
@@ -1656,10 +1663,9 @@ public final class TextFormat {
case '\'': builder.append("\\\'"); break;
case '"' : builder.append("\\\""); break;
default:
- // Note: Bytes with the high-order bit set should be escaped. Since
- // bytes are signed, such bytes will compare less than 0x20, hence
- // the following line is correct.
- if (b >= 0x20) {
+ // Only ASCII characters between 0x20 (space) and 0x7e (tilde) are
+ // printable. Other byte values must be escaped.
+ if (b >= 0x20 && b <= 0x7e) {
builder.append((char) b);
} else {
builder.append('\\');
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 99de3732..7cd2250e 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -431,6 +431,21 @@ public final class UnknownFieldSet implements MessageLite {
return this;
}
+
+ /**
+ * Convenience method for merging a length-delimited field.
+ *
+ * <p>For use by generated code only.
+ */
+ public Builder mergeLengthDelimitedField(
+ final int number, final ByteString value) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ getFieldBuilder(number).addLengthDelimited(value);
+ return this;
+ }
+
/** Check if the given field number is present in the set. */
public boolean hasField(final int number) {
if (number == 0) {
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
new file mode 100644
index 00000000..7ea84022
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
@@ -0,0 +1,297 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+
+/**
+ * {@code UnknownFieldSetLite} is used to keep track of fields which were seen
+ * when parsing a protocol message but whose field numbers or types are
+ * unrecognized. This most frequently occurs when new fields are added to a
+ * message type and then messages containing those fields are read by old
+ * software that was compiled before the new types were added.
+ *
+ * <p>For use by generated code only.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public final class UnknownFieldSetLite {
+
+ private static final UnknownFieldSetLite DEFAULT_INSTANCE =
+ new UnknownFieldSetLite(ByteString.EMPTY);
+
+ /**
+ * Get an empty {@code UnknownFieldSetLite}.
+ *
+ * <p>For use by generated code only.
+ */
+ public static UnknownFieldSetLite getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ /**
+ * Create a new {@link Builder}.
+ *
+ * <p>For use by generated code only.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns an {@code UnknownFieldSetLite} that is the composite of {@code first} and
+ * {@code second}.
+ */
+ static UnknownFieldSetLite concat(UnknownFieldSetLite first, UnknownFieldSetLite second) {
+ return new UnknownFieldSetLite(first.byteString.concat(second.byteString));
+ }
+
+ /**
+ * The internal representation of the unknown fields.
+ */
+ private final ByteString byteString;
+
+ /**
+ * Constructs the {@code UnknownFieldSetLite} as a thin wrapper around {@link ByteString}.
+ */
+ private UnknownFieldSetLite(ByteString byteString) {
+ this.byteString = byteString;
+ }
+
+ /**
+ * Serializes the set and writes it to {@code output}.
+ *
+ * <p>For use by generated code only.
+ */
+ public void writeTo(CodedOutputStream output) throws IOException {
+ output.writeRawBytes(byteString);
+ }
+
+
+ /**
+ * Get the number of bytes required to encode this set.
+ *
+ * <p>For use by generated code only.
+ */
+ public int getSerializedSize() {
+ return byteString.size();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof UnknownFieldSetLite) {
+ return byteString.equals(((UnknownFieldSetLite) obj).byteString);
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return byteString.hashCode();
+ }
+
+ /**
+ * Builder for {@link UnknownFieldSetLite}s.
+ *
+ * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
+ *
+ * <p>For use by generated code only.
+ */
+ public static final class Builder {
+
+ private ByteString.Output byteStringOutput;
+ private CodedOutputStream output;
+ private boolean built;
+
+ /**
+ * Constructs a {@code Builder}. Lazily initialized by
+ * {@link #ensureInitializedButNotBuilt()}.
+ */
+ private Builder() {}
+
+ /**
+ * Ensures internal state is initialized for use.
+ */
+ private void ensureInitializedButNotBuilt() {
+ if (built) {
+ throw new IllegalStateException("Do not reuse UnknownFieldSetLite Builders.");
+ }
+
+ if (output == null && byteStringOutput == null) {
+ byteStringOutput = ByteString.newOutput(100 /* initialCapacity */);
+ output = CodedOutputStream.newInstance(byteStringOutput);
+ }
+ }
+
+ /**
+ * Parse a single field from {@code input} and merge it into this set.
+ *
+ * <p>For use by generated code only.
+ *
+ * @param tag The field's tag number, which was already parsed.
+ * @return {@code false} if the tag is an end group tag.
+ */
+ public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
+ throws IOException {
+ ensureInitializedButNotBuilt();
+
+ final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ output.writeUInt64(fieldNumber, input.readInt64());
+ return true;
+ case WireFormat.WIRETYPE_FIXED32:
+ output.writeFixed32(fieldNumber, input.readFixed32());
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ output.writeFixed64(fieldNumber, input.readFixed64());
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ output.writeBytes(fieldNumber, input.readBytes());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ final Builder subBuilder = newBuilder();
+ subBuilder.mergeFrom(input);
+ input.checkLastTagWas(
+ WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+ subBuilder.build().writeTo(output);
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ /**
+ * Convenience method for merging a new field containing a single varint
+ * value. This is used in particular when an unknown enum value is
+ * encountered.
+ *
+ * <p>For use by generated code only.
+ */
+ public Builder mergeVarintField(int fieldNumber, int value) {
+ if (fieldNumber == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ ensureInitializedButNotBuilt();
+ try {
+ output.writeUInt64(fieldNumber, value);
+ } catch (IOException e) {
+ // Should never happen.
+ }
+ return this;
+ }
+
+ /**
+ * Convenience method for merging a length-delimited field.
+ *
+ * <p>For use by generated code only.
+ */
+ public Builder mergeLengthDelimitedField(
+ final int fieldNumber, final ByteString value) {
+ if (fieldNumber == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ ensureInitializedButNotBuilt();
+ try {
+ output.writeBytes(fieldNumber, value);
+ } catch (IOException e) {
+ // Should never happen.
+ }
+ return this;
+ }
+
+ /**
+ * Build the {@link UnknownFieldSetLite} and return it.
+ *
+ * <p>Once {@code build()} has been called, the {@code Builder} will no
+ * longer be usable. Calling any method after {@code build()} will result
+ * in undefined behavior and can cause a {@code IllegalStateException} to be
+ * thrown.
+ *
+ * <p>For use by generated code only.
+ */
+ public UnknownFieldSetLite build() {
+ if (built) {
+ throw new IllegalStateException("Do not reuse UnknownFieldSetLite Builders.");
+ }
+
+ built = true;
+
+ final UnknownFieldSetLite result;
+ // If we were never initialized, no data was written.
+ if (output == null) {
+ result = getDefaultInstance();
+ } else {
+ try {
+ output.flush();
+ } catch (IOException e) {
+ // Should never happen.
+ }
+ ByteString byteString = byteStringOutput.toByteString();
+ if (byteString.isEmpty()) {
+ result = getDefaultInstance();
+ } else {
+ result = new UnknownFieldSetLite(byteString);
+ }
+ }
+
+ // Allow for garbage collection.
+ output = null;
+ byteStringOutput = null;
+ return result;
+ }
+
+ /**
+ * Parse an entire message from {@code input} and merge its fields into
+ * this set.
+ */
+ private Builder mergeFrom(final CodedInputStream input) throws IOException {
+ // Ensures initialization in mergeFieldFrom.
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0 || !mergeFieldFrom(tag, input)) {
+ break;
+ }
+ }
+ return this;
+ }
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index 3f656e25..18d8142c 100644
--- a/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -455,19 +455,19 @@ public class CodedInputStreamTest extends TestCase {
}
public void testMaliciousRecursion() throws Exception {
- ByteString data64 = makeRecursiveMessage(64).toByteString();
- ByteString data65 = makeRecursiveMessage(65).toByteString();
+ ByteString data100 = makeRecursiveMessage(100).toByteString();
+ ByteString data101 = makeRecursiveMessage(101).toByteString();
- assertMessageDepth(TestRecursiveMessage.parseFrom(data64), 64);
+ assertMessageDepth(TestRecursiveMessage.parseFrom(data100), 100);
try {
- TestRecursiveMessage.parseFrom(data65);
+ TestRecursiveMessage.parseFrom(data101);
fail("Should have thrown an exception!");
} catch (InvalidProtocolBufferException e) {
// success.
}
- CodedInputStream input = data64.newCodedInput();
+ CodedInputStream input = data100.newCodedInput();
input.setRecursionLimit(8);
try {
TestRecursiveMessage.parseFrom(input);
diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index 0092771b..05832a12 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -706,6 +706,12 @@ public class DescriptorsTest extends TestCase {
assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143));
}
+ public void testToString() {
+ assertEquals("protobuf_unittest.TestAllTypes.optional_uint64",
+ UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber(
+ UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER).toString());
+ }
+
public void testPackedEnumField() throws Exception {
FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
.setName("foo.proto")
diff --git a/java/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
new file mode 100644
index 00000000..acf2b023
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -0,0 +1,363 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly;
+import com.google.protobuf.FieldPresenceTestProto.TestRepeatedFieldsOnly;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that doesn't support field presence test for optional
+ * non-message fields.
+ */
+public class FieldPresenceTest extends TestCase {
+ private static boolean hasMethod(Class clazz, String name) {
+ try {
+ if (clazz.getMethod(name, new Class[]{}) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ private static boolean isHasMethodRemoved(
+ Class classWithFieldPresence,
+ Class classWithoutFieldPresence,
+ String camelName) {
+ return hasMethod(classWithFieldPresence, "get" + camelName)
+ && hasMethod(classWithFieldPresence, "has" + camelName)
+ && hasMethod(classWithoutFieldPresence, "get" + camelName)
+ && !hasMethod(classWithoutFieldPresence, "has" + camelName);
+ }
+
+ public void testHasMethod() {
+ // Optional non-message fields don't have a hasFoo() method generated.
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalInt32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalNestedEnum"));
+
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalInt32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalNestedEnum"));
+
+ // message fields still have the hasFoo() method generated.
+ assertFalse(TestAllTypes.newBuilder().build().hasOptionalNestedMessage());
+ assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
+
+ // oneof fields don't have hasFoo() methods (even for message types).
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofUint32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofNestedMessage"));
+
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofUint32"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofString"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofBytes"));
+ assertTrue(isHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofNestedMessage"));
+ }
+
+ public void testFieldPresence() {
+ // Optional non-message fields set to their default value are treated the
+ // same way as not set.
+
+ // Serialization will ignore such fields.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(0);
+ builder.setOptionalString("");
+ builder.setOptionalBytes(ByteString.EMPTY);
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+ TestAllTypes message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+
+ // mergeFrom() will ignore such fields.
+ TestAllTypes.Builder a = TestAllTypes.newBuilder();
+ a.setOptionalInt32(1);
+ a.setOptionalString("x");
+ a.setOptionalBytes(ByteString.copyFromUtf8("y"));
+ a.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+ TestAllTypes.Builder b = TestAllTypes.newBuilder();
+ b.setOptionalInt32(0);
+ b.setOptionalString("");
+ b.setOptionalBytes(ByteString.EMPTY);
+ b.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+ a.mergeFrom(b.build());
+ message = a.build();
+ assertEquals(1, message.getOptionalInt32());
+ assertEquals("x", message.getOptionalString());
+ assertEquals(ByteString.copyFromUtf8("y"), message.getOptionalBytes());
+ assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum());
+
+ // equals()/hashCode() should produce the same results.
+ TestAllTypes empty = TestAllTypes.newBuilder().build();
+ message = builder.build();
+ assertTrue(empty.equals(message));
+ assertTrue(message.equals(empty));
+ assertEquals(empty.hashCode(), message.hashCode());
+ }
+
+ public void testFieldPresenceByReflection() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalInt32Field = descriptor.findFieldByName("optional_int32");
+ FieldDescriptor optionalStringField = descriptor.findFieldByName("optional_string");
+ FieldDescriptor optionalBytesField = descriptor.findFieldByName("optional_bytes");
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+
+ // Field not present.
+ TestAllTypes message = TestAllTypes.newBuilder().build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to default value is seen as not present.
+ message = TestAllTypes.newBuilder()
+ .setOptionalInt32(0)
+ .setOptionalString("")
+ .setOptionalBytes(ByteString.EMPTY)
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO)
+ .build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to non-default value is seen as present.
+ message = TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("x")
+ .setOptionalBytes(ByteString.copyFromUtf8("y"))
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR)
+ .build();
+ assertTrue(message.hasField(optionalInt32Field));
+ assertTrue(message.hasField(optionalStringField));
+ assertTrue(message.hasField(optionalBytesField));
+ assertTrue(message.hasField(optionalNestedEnumField));
+ assertEquals(4, message.getAllFields().size());
+ }
+
+ public void testMessageField() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ assertFalse(builder.hasOptionalNestedMessage());
+ assertFalse(builder.build().hasOptionalNestedMessage());
+
+ TestAllTypes.NestedMessage.Builder nestedBuilder =
+ builder.getOptionalNestedMessageBuilder();
+ assertTrue(builder.hasOptionalNestedMessage());
+ assertTrue(builder.build().hasOptionalNestedMessage());
+
+ nestedBuilder.setValue(1);
+ assertEquals(1, builder.build().getOptionalNestedMessage().getValue());
+
+ builder.clearOptionalNestedMessage();
+ assertFalse(builder.hasOptionalNestedMessage());
+ assertFalse(builder.build().hasOptionalNestedMessage());
+
+ // Unlike non-message fields, if we set a message field to its default value (i.e.,
+ // default instance), the field should be seen as present.
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ assertTrue(builder.hasOptionalNestedMessage());
+ assertTrue(builder.build().hasOptionalNestedMessage());
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.setOptionalString("hello");
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ // Set an oneof field to its default value and expect it to be serialized (i.e.,
+ // an oneof field set to the default value should be treated as present).
+ builder.setOneofInt32(0);
+ ByteString data = builder.build().toByteString();
+
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(1234, message.getOptionalInt32());
+ assertEquals("hello", message.getOptionalString());
+ // Fields not set will have the default value.
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum());
+ // The message field is set despite that it's set with a default instance.
+ assertTrue(message.hasOptionalNestedMessage());
+ assertEquals(0, message.getOptionalNestedMessage().getValue());
+ // The oneof field set to its default value is also present.
+ assertEquals(
+ TestAllTypes.OneofFieldCase.ONEOF_INT32, message.getOneofFieldCase());
+ }
+
+ // Regression test for b/16173397
+ // Make sure we haven't screwed up the code generation for repeated fields.
+ public void testRepeatedFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.setOptionalString("hello");
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ builder.addRepeatedInt32(4321);
+ builder.addRepeatedString("world");
+ builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ ByteString data = builder.build().toByteString();
+
+ TestOptionalFieldsOnly optionalOnlyMessage = TestOptionalFieldsOnly.parseFrom(data);
+ assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+ assertEquals("hello", optionalOnlyMessage.getOptionalString());
+ assertTrue(optionalOnlyMessage.hasOptionalNestedMessage());
+ assertEquals(0, optionalOnlyMessage.getOptionalNestedMessage().getValue());
+
+ TestRepeatedFieldsOnly repeatedOnlyMessage = TestRepeatedFieldsOnly.parseFrom(data);
+ assertEquals(1, repeatedOnlyMessage.getRepeatedInt32Count());
+ assertEquals(4321, repeatedOnlyMessage.getRepeatedInt32(0));
+ assertEquals(1, repeatedOnlyMessage.getRepeatedStringCount());
+ assertEquals("world", repeatedOnlyMessage.getRepeatedString(0));
+ assertEquals(1, repeatedOnlyMessage.getRepeatedNestedMessageCount());
+ assertEquals(0, repeatedOnlyMessage.getRepeatedNestedMessage(0).getValue());
+ }
+
+ public void testIsInitialized() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ // Test optional proto2 message fields.
+ UnittestProto.TestRequired.Builder proto2Builder =
+ builder.getOptionalProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+
+ // Test oneof proto2 message fields.
+ proto2Builder = builder.getOneofProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+
+ // Test repeated proto2 message fields.
+ proto2Builder = builder.addRepeatedProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+ }
+
+
+ // Test that unknown fields are dropped.
+ public void testUnknownFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.addRepeatedInt32(5678);
+ TestAllTypes message = builder.build();
+ ByteString data = message.toByteString();
+
+ TestOptionalFieldsOnly optionalOnlyMessage =
+ TestOptionalFieldsOnly.parseFrom(data);
+ // UnknownFieldSet should be empty.
+ assertEquals(
+ 0, optionalOnlyMessage.getUnknownFields().toByteString().size());
+ assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+ message = TestAllTypes.parseFrom(optionalOnlyMessage.toByteString());
+ assertEquals(1234, message.getOptionalInt32());
+ // The repeated field is discarded because it's unknown to the optional-only
+ // message.
+ assertEquals(0, message.getRepeatedInt32Count());
+
+ DynamicMessage dynamicOptionalOnlyMessage =
+ DynamicMessage.getDefaultInstance(
+ TestOptionalFieldsOnly.getDescriptor())
+ .getParserForType().parseFrom(data);
+ assertEquals(
+ 0, dynamicOptionalOnlyMessage.getUnknownFields().toByteString().size());
+ assertEquals(optionalOnlyMessage.toByteString(),
+ dynamicOptionalOnlyMessage.toByteString());
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 0b3482c3..41ed7bd0 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -157,15 +157,12 @@ public class GeneratedMessageTest extends TestCase {
public void testProtosShareRepeatedArraysIfDidntChange() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
builder.addRepeatedInt32(100);
- builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
TestAllTypes value1 = builder.build();
TestAllTypes value2 = value1.toBuilder().build();
assertSame(value1.getRepeatedInt32List(), value2.getRepeatedInt32List());
- assertSame(value1.getRepeatedImportEnumList(),
- value2.getRepeatedImportEnumList());
assertSame(value1.getRepeatedForeignMessageList(),
value2.getRepeatedForeignMessageList());
}
@@ -1512,4 +1509,142 @@ public class GeneratedMessageTest extends TestCase {
assertEquals(message2.getFooMessage().getQuxInt(), 234);
}
}
+
+ public void testGetRepeatedFieldBuilder() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("repeated_nested_message");
+ FieldDescriptor foreignFieldDescriptor =
+ descriptor.findFieldByName("repeated_foreign_message");
+ FieldDescriptor importFieldDescriptor =
+ descriptor.findFieldByName("repeated_import_message");
+
+ // Mutate the message with new field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder1 = builder1.newBuilderForField(
+ fieldDescriptor);
+ FieldDescriptor subFieldDescriptor1 =
+ fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder1.setField(subFieldDescriptor1, 1);
+ builder1.addRepeatedField(fieldDescriptor, fieldBuilder1.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+ foreignFieldDescriptor);
+ FieldDescriptor subForeignFieldDescriptor1 =
+ foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+ builder1.addRepeatedField(foreignFieldDescriptor,
+ foreignFieldBuilder1.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+ importFieldDescriptor);
+ FieldDescriptor subImportFieldDescriptor1 =
+ importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+ builder1.addRepeatedField(importFieldDescriptor,
+ importFieldBuilder1.build());
+
+ Message newMessage1 = builder1.build();
+
+ // Mutate the message with existing field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+ builder2.addRepeatedNestedMessageBuilder();
+ Message.Builder fieldBuilder2 = builder2.getRepeatedFieldBuilder(
+ fieldDescriptor, 0);
+ FieldDescriptor subFieldDescriptor2 =
+ fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder2.setField(subFieldDescriptor2, 1);
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+ foreignFieldDescriptor);
+ FieldDescriptor subForeignFieldDescriptor2 =
+ foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+ builder2.addRepeatedField(foreignFieldDescriptor,
+ foreignFieldBuilder2.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+ importFieldDescriptor);
+ FieldDescriptor subImportFieldDescriptor2 =
+ importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+ builder2.addRepeatedField(importFieldDescriptor,
+ importFieldBuilder2.build());
+
+ Message newMessage2 = builder2.build();
+
+ // These two messages should be equal.
+ assertEquals(newMessage1, newMessage2);
+ }
+
+ public void testGetRepeatedFieldBuilderWithInitializedValue() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("repeated_nested_message");
+
+ // Before setting field, builder is initialized by default value.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedNestedMessageBuilder();
+ NestedMessage.Builder fieldBuilder =
+ (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+ assertEquals(0, fieldBuilder.getBb());
+
+ // Setting field value with new field builder instance.
+ builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder newFieldBuilder =
+ builder.addRepeatedNestedMessageBuilder();
+ newFieldBuilder.setBb(2);
+ // Then get the field builder instance by getRepeatedFieldBuilder().
+ fieldBuilder =
+ (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+ // It should contain new value.
+ assertEquals(2, fieldBuilder.getBb());
+ // These two builder should be equal.
+ assertSame(fieldBuilder, newFieldBuilder);
+ }
+
+ public void testGetRepeatedFieldBuilderNotSupportedException() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_int32"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_enum"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_int32"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("optional_nested_enum"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("optional_nested_message"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
index 00e3a843..9de794fe 100644
--- a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
@@ -36,8 +36,6 @@ import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite;
import junit.framework.TestCase;
-import org.easymock.classextension.EasyMock;
-
import java.util.ArrayList;
/**
@@ -52,14 +50,10 @@ public class LazyMessageLiteTest extends TestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
-
- originalLazyInnerMessageLiteParser = LazyInnerMessageLite.PARSER;
}
@Override
protected void tearDown() throws Exception {
- LazyInnerMessageLite.PARSER = originalLazyInnerMessageLiteParser;
-
super.tearDown();
}
@@ -291,29 +285,4 @@ public class LazyMessageLiteTest extends TestCase {
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/LiteEqualsAndHashTest.java b/java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
index 94f4fcf5..035917c8 100644
--- a/java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
@@ -82,4 +82,27 @@ public class LiteEqualsAndHashTest extends TestCase {
BarPrime barPrime = BarPrime.newBuilder().setName("bar").build();
assertFalse(bar.equals(barPrime));
}
+
+ public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException {
+ Foo fooWithOnlyValue = Foo.newBuilder()
+ .setValue(1)
+ .build();
+
+ Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .build();
+
+ Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray());
+
+ assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields);
+ assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields);
+ }
+
+ private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
+ assertFalse(o1.equals(o2));
+ assertFalse(o1.hashCode() == o2.hashCode());
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
new file mode 100644
index 00000000..22dbeb76
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -0,0 +1,277 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import map_lite_test.MapForProto2TestProto.TestMap;
+import map_lite_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_lite_test.MapForProto2TestProto.TestUnknownEnumValue;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for map fields.
+ */
+public class MapForProto2LiteTest extends TestCase {
+ private void setMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMap message) {
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToStringField().size());
+ assertEquals(0, message.getInt32ToBytesField().size());
+ assertEquals(0, message.getInt32ToEnumField().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+ assertEquals(0, message.getStringToInt32Field().size());
+ }
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValues(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder();
+ b1.getMutableInt32ToInt32Field().put(1, 2);
+ b1.getMutableInt32ToInt32Field().put(3, 4);
+ b1.getMutableInt32ToInt32Field().put(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder();
+ b2.getMutableInt32ToInt32Field().put(5, 6);
+ b2.getMutableInt32ToInt32Field().put(1, 2);
+ b2.getMutableInt32ToInt32Field().put(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.getMutableInt32ToInt32Field().put(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestUnknownEnumValue.Builder builder =
+ TestUnknownEnumValue.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 1);
+ builder.getMutableInt32ToInt32Field().put(2, 54321);
+ ByteString data = builder.build().toByteString();
+
+ TestMap message = TestMap.parseFrom(data);
+ // Entries with unknown enum values will be stored into UnknownFieldSet so
+ // there is only one entry in the map.
+ assertEquals(1, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ // Serializing and parsing should preserve the unknown entry.
+ data = message.toByteString();
+ TestUnknownEnumValue messageWithUnknownEnums =
+ TestUnknownEnumValue.parseFrom(data);
+ assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+ assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+ }
+
+}
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
new file mode 100644
index 00000000..d78c0d94
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -0,0 +1,488 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapForProto2TestProto.TestMap;
+import map_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_test.MapForProto2TestProto.TestUnknownEnumValue;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields in proto2 protos.
+ */
+public class MapForProto2Test extends TestCase {
+ private void setMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMap message) {
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToStringField().size());
+ assertEquals(0, message.getInt32ToBytesField().size());
+ assertEquals(0, message.getInt32ToEnumField().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+ assertEquals(0, message.getStringToInt32Field().size());
+ }
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValues(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder();
+ b1.getMutableInt32ToInt32Field().put(1, 2);
+ b1.getMutableInt32ToInt32Field().put(3, 4);
+ b1.getMutableInt32ToInt32Field().put(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder();
+ b2.getMutableInt32ToInt32Field().put(5, 6);
+ b2.getMutableInt32ToInt32Field().put(1, 2);
+ b2.getMutableInt32ToInt32Field().put(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.getMutableInt32ToInt32Field().put(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+
+ // The following methods are used to test reflection API.
+
+ private static FieldDescriptor f(String name) {
+ return TestMap.getDescriptor().findFieldByName(name);
+ }
+
+ private static Object getFieldValue(Message mapEntry, String name) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ return mapEntry.getField(field);
+ }
+
+ private static Message.Builder setFieldValue(
+ Message.Builder mapEntry, String name, Object value) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ mapEntry.setField(field, value);
+ return mapEntry;
+ }
+
+ private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+ FieldDescriptor field = f(name);
+ for (Object entry : (List<?>) message.getField(field)) {
+ Message mapEntry = (Message) entry;
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ assertEquals(values.size(), message.getRepeatedFieldCount(field));
+ for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) message.getRepeatedField(field, i);
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ }
+
+ private static <KeyType, ValueType>
+ Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+ FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ return entryBuilder.build();
+ }
+
+ private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+ List<Message> entryList = new ArrayList<Message>();
+ for (Map.Entry<?, ?> entry : values.entrySet()) {
+ entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+ }
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ builder.setField(field, entryList);
+ }
+
+ private static <KeyType, ValueType>
+ Map<KeyType, ValueType> mapForValues(
+ KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+ Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testReflectionApi() throws Exception {
+ // In reflection API, map fields are just repeated message fields.
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 2);
+ builder.getMutableInt32ToInt32Field().put(3, 4);
+ builder.getMutableInt32ToMessageField().put(
+ 11, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 33, MessageValue.newBuilder().setValue(44).build());
+ TestMap message = builder.build();
+
+ // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+ assertHasMapValues(message, "int32_to_int32_field",
+ mapForValues(1, 2, 3, 4));
+ assertHasMapValues(message, "int32_to_message_field",
+ mapForValues(
+ 11, MessageValue.newBuilder().setValue(22).build(),
+ 33, MessageValue.newBuilder().setValue(44).build()));
+
+ // Test clearField()
+ builder.clearField(f("int32_to_int32_field"));
+ builder.clearField(f("int32_to_message_field"));
+ message = builder.build();
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+
+ // Test setField()
+ setMapValues(builder, "int32_to_int32_field",
+ mapForValues(11, 22, 33, 44));
+ setMapValues(builder, "int32_to_message_field",
+ mapForValues(
+ 111, MessageValue.newBuilder().setValue(222).build(),
+ 333, MessageValue.newBuilder().setValue(444).build()));
+ message = builder.build();
+ assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+ assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+ assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+
+ // Test addRepeatedField
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 66));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(666).build()));
+ message = builder.build();
+ assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test addRepeatedField (overriding existing values)
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 55));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(555).build()));
+ message = builder.build();
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test setRepeatedField
+ for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+ int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+ // Swap key with value for each entry.
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ setFieldValue(mapEntryBuilder, "key", oldValue);
+ setFieldValue(mapEntryBuilder, "value", oldKey);
+ builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+ }
+ message = builder.build();
+ assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ }
+
+ public void testTextFormat() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ String textData = TextFormat.printToString(message);
+
+ builder = TestMap.newBuilder();
+ TextFormat.merge(textData, builder);
+ message = builder.build();
+
+ assertMapValuesSet(message);
+ }
+
+ public void testDynamicMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ Message dynamicMessage = dynamicDefaultInstance
+ .newBuilderForType().mergeFrom(message.toByteString()).build();
+
+ assertEquals(message, dynamicMessage);
+ assertEquals(message.hashCode(), dynamicMessage.hashCode());
+ }
+
+ public void testReflectionEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We use DynamicMessage to test reflection based equals()/hashCode().
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ FieldDescriptor field = f("int32_to_int32_field");
+
+ Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+ Message m1 = b1.build();
+
+ Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+ Message m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestUnknownEnumValue.Builder builder =
+ TestUnknownEnumValue.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 1);
+ builder.getMutableInt32ToInt32Field().put(2, 54321);
+ ByteString data = builder.build().toByteString();
+
+ TestMap message = TestMap.parseFrom(data);
+ // Entries with unknown enum values will be stored into UnknownFieldSet so
+ // there is only one entry in the map.
+ assertEquals(1, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ // UnknownFieldSet should not be empty.
+ assertFalse(message.getUnknownFields().asMap().isEmpty());
+ // Serializing and parsing should preserve the unknown entry.
+ data = message.toByteString();
+ TestUnknownEnumValue messageWithUnknownEnums =
+ TestUnknownEnumValue.parseFrom(data);
+ assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+ assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+ }
+
+}
diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java
new file mode 100644
index 00000000..542a20e7
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/MapTest.java
@@ -0,0 +1,569 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapTestProto.TestMap;
+import map_test.MapTestProto.TestMap.MessageValue;
+import map_test.MapTestProto.TestOnChangeEventPropagation;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Unit tests for map fields.
+ */
+public class MapTest extends TestCase {
+ private void setMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValues(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMap message) {
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToStringField().size());
+ assertEquals(0, message.getInt32ToBytesField().size());
+ assertEquals(0, message.getInt32ToEnumField().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+ assertEquals(0, message.getStringToInt32Field().size());
+ }
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValues(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.PARSER.parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder();
+ b1.getMutableInt32ToInt32Field().put(1, 2);
+ b1.getMutableInt32ToInt32Field().put(3, 4);
+ b1.getMutableInt32ToInt32Field().put(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder();
+ b2.getMutableInt32ToInt32Field().put(5, 6);
+ b2.getMutableInt32ToInt32Field().put(1, 2);
+ b2.getMutableInt32ToInt32Field().put(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.getMutableInt32ToInt32Field().put(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+
+ public void testNestedBuilderOnChangeEventPropagation() {
+ TestOnChangeEventPropagation.Builder parent =
+ TestOnChangeEventPropagation.newBuilder();
+ parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2);
+ TestOnChangeEventPropagation message = parent.build();
+ assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make a change using nested builder.
+ parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3);
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make another change using mergeFrom()
+ TestMap.Builder other = TestMap.newBuilder();
+ other.getMutableInt32ToInt32Field().put(1, 4);
+ parent.getOptionalMessageBuilder().mergeFrom(other.build());
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make yet another change by clearing the nested builder.
+ parent.getOptionalMessageBuilder().clear();
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+ }
+
+ // The following methods are used to test reflection API.
+
+ private static FieldDescriptor f(String name) {
+ return TestMap.getDescriptor().findFieldByName(name);
+ }
+
+ private static Object getFieldValue(Message mapEntry, String name) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ return mapEntry.getField(field);
+ }
+
+ private static Message.Builder setFieldValue(
+ Message.Builder mapEntry, String name, Object value) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ mapEntry.setField(field, value);
+ return mapEntry;
+ }
+
+ private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+ FieldDescriptor field = f(name);
+ for (Object entry : (List<?>) message.getField(field)) {
+ Message mapEntry = (Message) entry;
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ assertEquals(values.size(), message.getRepeatedFieldCount(field));
+ for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) message.getRepeatedField(field, i);
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ }
+
+ private static <KeyType, ValueType>
+ Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+ FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ return entryBuilder.build();
+ }
+
+ private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+ List<Message> entryList = new ArrayList<Message>();
+ for (Map.Entry<?, ?> entry : values.entrySet()) {
+ entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+ }
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ builder.setField(field, entryList);
+ }
+
+ private static <KeyType, ValueType>
+ Map<KeyType, ValueType> mapForValues(
+ KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+ Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testReflectionApi() throws Exception {
+ // In reflection API, map fields are just repeated message fields.
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableInt32ToInt32Field().put(1, 2);
+ builder.getMutableInt32ToInt32Field().put(3, 4);
+ builder.getMutableInt32ToMessageField().put(
+ 11, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 33, MessageValue.newBuilder().setValue(44).build());
+ TestMap message = builder.build();
+
+ // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+ assertHasMapValues(message, "int32_to_int32_field",
+ mapForValues(1, 2, 3, 4));
+ assertHasMapValues(message, "int32_to_message_field",
+ mapForValues(
+ 11, MessageValue.newBuilder().setValue(22).build(),
+ 33, MessageValue.newBuilder().setValue(44).build()));
+
+ // Test clearField()
+ builder.clearField(f("int32_to_int32_field"));
+ builder.clearField(f("int32_to_message_field"));
+ message = builder.build();
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+
+ // Test setField()
+ setMapValues(builder, "int32_to_int32_field",
+ mapForValues(11, 22, 33, 44));
+ setMapValues(builder, "int32_to_message_field",
+ mapForValues(
+ 111, MessageValue.newBuilder().setValue(222).build(),
+ 333, MessageValue.newBuilder().setValue(444).build()));
+ message = builder.build();
+ assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+ assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+ assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+
+ // Test addRepeatedField
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 66));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(666).build()));
+ message = builder.build();
+ assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test addRepeatedField (overriding existing values)
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 55));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(555).build()));
+ message = builder.build();
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test setRepeatedField
+ for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+ int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+ // Swap key with value for each entry.
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ setFieldValue(mapEntryBuilder, "key", oldValue);
+ setFieldValue(mapEntryBuilder, "value", oldKey);
+ builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+ }
+ message = builder.build();
+ assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ }
+
+ public void testTextFormat() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ String textData = TextFormat.printToString(message);
+
+ builder = TestMap.newBuilder();
+ TextFormat.merge(textData, builder);
+ message = builder.build();
+
+ assertMapValuesSet(message);
+ }
+
+ public void testDynamicMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ Message dynamicMessage = dynamicDefaultInstance
+ .newBuilderForType().mergeFrom(message.toByteString()).build();
+
+ assertEquals(message, dynamicMessage);
+ assertEquals(message.hashCode(), dynamicMessage.hashCode());
+ }
+
+ public void testReflectionEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We use DynamicMessage to test reflection based equals()/hashCode().
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ FieldDescriptor field = f("int32_to_int32_field");
+
+ Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+ Message m1 = b1.build();
+
+ Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+ Message m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.getMutableInt32ToEnumFieldValue().put(0, 0);
+ builder.getMutableInt32ToEnumFieldValue().put(1, 1);
+ builder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value.
+ TestMap message = builder.build();
+
+ assertEquals(TestMap.EnumValue.FOO,
+ message.getInt32ToEnumField().get(0));
+ assertEquals(TestMap.EnumValue.BAR,
+ message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.UNRECOGNIZED,
+ message.getInt32ToEnumField().get(2));
+ assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+
+ // Unknown enum values should be preserved after:
+ // 1. Serialization and parsing.
+ // 2. toBuild().
+ // 3. mergeFrom().
+ message = TestMap.parseFrom(message.toByteString());
+ assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+ builder = message.toBuilder();
+ assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+ builder = TestMap.newBuilder().mergeFrom(message);
+ assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+
+ // hashCode()/equals() should take unknown enum values into account.
+ builder.getMutableInt32ToEnumFieldValue().put(2, 1001);
+ TestMap message2 = builder.build();
+ assertFalse(message.hashCode() == message2.hashCode());
+ assertFalse(message.equals(message2));
+ // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
+ // should be the same.
+ assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField()));
+ }
+
+ public void testUnknownEnumValuesInReflectionApi() throws Exception {
+ Descriptor descriptor = TestMap.getDescriptor();
+ EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
+ FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
+
+ Map<Integer, Integer> data = new HashMap<Integer, Integer>();
+ data.put(0, 0);
+ data.put(1, 1);
+ data.put(2, 1000); // unknown value.
+
+ TestMap.Builder builder = TestMap.newBuilder();
+ for (Map.Entry<Integer, Integer> entry : data.entrySet()) {
+ builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue());
+ }
+
+ // Try to read unknown enum values using reflection API.
+ for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(field, i);
+ int key = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int value = ((EnumValueDescriptor) getFieldValue(mapEntry, "value")).getNumber();
+ assertEquals(data.get(key).intValue(), value);
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ // Increase the value by 1.
+ setFieldValue(mapEntryBuilder, "value",
+ enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1));
+ builder.setRepeatedField(field, i, mapEntryBuilder.build());
+ }
+
+ // Verify that enum values have been successfully updated.
+ TestMap message = builder.build();
+ for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValue().entrySet()) {
+ assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
+ }
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
index 614ac7fe..2c60fe0e 100644
--- a/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/java/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -72,7 +72,7 @@ public class TestBadIdentifiers extends TestCase {
assertEquals(0, message.getMessageField5Count());
assertEquals(0, message.getInt32FieldCount11());
- assertEquals(1, message.getEnumFieldCount12().getNumber());
+ assertEquals(0, message.getEnumFieldCount12().getNumber());
assertEquals("", message.getStringFieldCount13());
assertEquals(ByteString.EMPTY, message.getBytesFieldCount14());
assertEquals(0, message.getMessageFieldCount15().getSerializedSize());
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 152bdadc..82f9582f 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -73,7 +73,7 @@ public class TextFormatTest extends TestCase {
private static String exoticText =
"repeated_int32: -1\n" +
"repeated_int32: -2147483648\n" +
- "repeated_int64: -1\n" +
+ "repeated_int64: -1,\n" +
"repeated_int64: -9223372036854775808\n" +
"repeated_uint32: 4294967295\n" +
"repeated_uint32: 2147483648\n" +
@@ -101,7 +101,7 @@ public class TextFormatTest extends TestCase {
private static String canonicalExoticText =
exoticText.replace(": .", ": 0.").replace(": -.", ": -0.") // short-form double
- .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16");
+ .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16").replace(",", "");
private String messageSetText =
"[protobuf_unittest.TestMessageSetExtension1] {\n" +
@@ -119,6 +119,7 @@ public class TextFormatTest extends TestCase {
" i: 456\n" +
"}\n";
+
private final TextFormat.Parser parserWithOverwriteForbidden =
TextFormat.Parser.newBuilder()
.setSingularOverwritePolicy(
@@ -460,6 +461,7 @@ public class TextFormatTest extends TestCase {
}
}
+
private void assertParseErrorWithOverwriteForbidden(String error,
String text) {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -553,10 +555,10 @@ public class TextFormatTest extends TestCase {
public void testEscape() throws Exception {
// Escape sequences.
- assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
- TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"")));
- assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"",
- TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\""));
+ assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+ TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\177")));
+ assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+ TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\"\177"));
assertEquals(bytes("\0\001\007\b\f\n\r\t\013\\\'\""),
TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"",
@@ -900,6 +902,7 @@ public class TextFormatTest extends TestCase {
.build()));
}
+
public void testParseNonRepeatedFields() throws Exception {
assertParseSuccessWithOverwriteForbidden(
"repeated_int32: 1\n" +
diff --git a/java/src/test/java/com/google/protobuf/UnknownEnumValueTest.java b/java/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
new file mode 100644
index 00000000..8f45976f
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
@@ -0,0 +1,255 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.TextFormat.ParseException;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that keep unknown enum values rather than discard
+ * them as unknown fields.
+ */
+public class UnknownEnumValueTest extends TestCase {
+ public void testUnknownEnumValues() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalNestedEnumValue(4321);
+ builder.addRepeatedNestedEnumValue(5432);
+ builder.addPackedNestedEnumValue(6543);
+ TestAllTypes message = builder.build();
+ assertEquals(4321, message.getOptionalNestedEnumValue());
+ assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, message.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+
+ // Test serialization and parsing.
+ ByteString data = message.toByteString();
+ message = TestAllTypes.parseFrom(data);
+ assertEquals(4321, message.getOptionalNestedEnumValue());
+ assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, message.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+
+ // Test toBuilder().
+ builder = message.toBuilder();
+ assertEquals(4321, builder.getOptionalNestedEnumValue());
+ assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, builder.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+
+ // Test mergeFrom().
+ builder = TestAllTypes.newBuilder().mergeFrom(message);
+ assertEquals(4321, builder.getOptionalNestedEnumValue());
+ assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, builder.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+
+ // Test equals() and hashCode()
+ TestAllTypes sameMessage = builder.build();
+ assertEquals(message, sameMessage);
+ assertEquals(message.hashCode(), sameMessage.hashCode());
+
+ // Getting the numeric value of UNRECOGNIZED will throw an exception.
+ try {
+ TestAllTypes.NestedEnum.UNRECOGNIZED.getNumber();
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ // Setting an enum field to an UNRECOGNIZED value will throw an exception.
+ try {
+ builder.setOptionalNestedEnum(builder.getOptionalNestedEnum());
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ try {
+ builder.addRepeatedNestedEnum(builder.getOptionalNestedEnum());
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ public void testUnknownEnumValueInReflectionApi() throws Exception {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+ FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ TestAllTypes message = builder.build();
+
+ // Getters will return unknown enum values as EnumValueDescriptor.
+ EnumValueDescriptor unknown4321 =
+ (EnumValueDescriptor) message.getField(optionalNestedEnumField);
+ EnumValueDescriptor unknown5432 =
+ (EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0);
+ EnumValueDescriptor unknown6543 =
+ (EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0);
+ assertEquals(4321, unknown4321.getNumber());
+ assertEquals(5432, unknown5432.getNumber());
+ assertEquals(6543, unknown6543.getNumber());
+
+ // Unknown EnumValueDescriptor will map to UNRECOGNIZED.
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown4321),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown5432),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown6543),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+
+ // Setters also accept unknown EnumValueDescriptor.
+ builder.setField(optionalNestedEnumField, unknown6543);
+ builder.setRepeatedField(repeatedNestedEnumField, 0, unknown4321);
+ builder.setRepeatedField(packedNestedEnumField, 0, unknown5432);
+ message = builder.build();
+ // Like other descriptors, unknown EnumValueDescriptor can be compared by
+ // object identity.
+ assertTrue(unknown6543 == message.getField(optionalNestedEnumField));
+ assertTrue(unknown4321 == message.getRepeatedField(repeatedNestedEnumField, 0));
+ assertTrue(unknown5432 == message.getRepeatedField(packedNestedEnumField, 0));
+ }
+
+ public void testUnknownEnumValueWithDynamicMessage() throws Exception {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+ FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+
+ Message dynamicMessageDefaultInstance = DynamicMessage.getDefaultInstance(descriptor);
+
+ Message.Builder builder = dynamicMessageDefaultInstance.newBuilderForType();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ Message message = builder.build();
+ assertEquals(4321,
+ ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+ assertEquals(5432,
+ ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+ assertEquals(6543,
+ ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+
+ // Test reflection based serialization/parsing implementation.
+ ByteString data = message.toByteString();
+ message = dynamicMessageDefaultInstance
+ .newBuilderForType()
+ .mergeFrom(data)
+ .build();
+ assertEquals(4321,
+ ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+ assertEquals(5432,
+ ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+ assertEquals(6543,
+ ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+
+ // Test reflection based equals()/hashCode().
+ builder = dynamicMessageDefaultInstance.newBuilderForType();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ Message sameMessage = builder.build();
+ assertEquals(message, sameMessage);
+ assertEquals(message.hashCode(), sameMessage.hashCode());
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(0));
+ Message differentMessage = builder.build();
+ assertFalse(message.equals(differentMessage));
+ }
+
+ public void testUnknownEnumValuesInTextFormat() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalNestedEnumValue(4321);
+ builder.addRepeatedNestedEnumValue(5432);
+ builder.addPackedNestedEnumValue(6543);
+ TestAllTypes message = builder.build();
+
+ // We can print a message with unknown enum values.
+ String textData = TextFormat.printToString(message);
+ assertEquals(
+ "optional_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_4321\n"
+ + "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n"
+ + "packed_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_6543\n", textData);
+
+ // Parsing unknown enum values will fail just like parsing other kinds of
+ // unknown fields.
+ try {
+ TextFormat.merge(textData, builder);
+ fail();
+ } catch (ParseException e) {
+ // expected.
+ }
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
new file mode 100644
index 00000000..6372b7a7
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
@@ -0,0 +1,317 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package com.google.protobuf;
+
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Tests for {@link UnknownFieldSetLite}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class UnknownFieldSetLiteTest extends TestCase {
+
+ public void testNoDataIsDefaultInstance() {
+ assertSame(
+ UnknownFieldSetLite.getDefaultInstance(),
+ UnknownFieldSetLite.newBuilder()
+ .build());
+ }
+
+ public void testDefaultInstance() {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
+
+ assertEquals(0, unknownFields.getSerializedSize());
+ assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+ }
+
+ public void testMergeFieldFrom() throws IOException {
+ Foo foo = Foo.newBuilder()
+ .setValue(2)
+ .build();
+
+ CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.mergeFieldFrom(input.readTag(), input);
+
+ assertEquals(foo.toByteString(), toByteString(builder.build()));
+ }
+
+ public void testSerializedSize() throws IOException {
+ Foo foo = Foo.newBuilder()
+ .setValue(2)
+ .build();
+
+ CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.mergeFieldFrom(input.readTag(), input);
+
+ assertEquals(foo.toByteString().size(), builder.build().getSerializedSize());
+ }
+
+ public void testMergeVarintField() throws IOException {
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.mergeVarintField(10, 2);
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(builder.build()).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testMergeVarintField_negative() throws IOException {
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.mergeVarintField(10, -6);
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(builder.build()).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(-6, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testEqualsAndHashCode() {
+ UnknownFieldSetLite.Builder builder1 = UnknownFieldSetLite.newBuilder();
+ builder1.mergeVarintField(10, 2);
+ UnknownFieldSetLite unknownFields1 = builder1.build();
+
+ UnknownFieldSetLite.Builder builder2 = UnknownFieldSetLite.newBuilder();
+ builder2.mergeVarintField(10, 2);
+ UnknownFieldSetLite unknownFields2 = builder2.build();
+
+ assertEquals(unknownFields1, unknownFields2);
+ assertEquals(unknownFields1.hashCode(), unknownFields2.hashCode());
+ assertFalse(unknownFields1.equals(UnknownFieldSetLite.getDefaultInstance()));
+ assertFalse(unknownFields1.hashCode() == UnknownFieldSetLite.getDefaultInstance().hashCode());
+ }
+
+ public void testConcat() throws IOException {
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.mergeVarintField(10, 2);
+ UnknownFieldSetLite unknownFields = builder.build();
+
+ unknownFields = UnknownFieldSetLite.concat(unknownFields, unknownFields);
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertFalse(input.isAtEnd());
+ input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testConcat_empty() {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.concat(
+ UnknownFieldSetLite.getDefaultInstance(), UnknownFieldSetLite.getDefaultInstance());
+
+ assertEquals(0, unknownFields.getSerializedSize());
+ assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+ }
+
+ public void testBuilderReuse() throws IOException {
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.mergeVarintField(10, 2);
+ builder.build();
+
+ try {
+ builder.build();
+ fail();
+ } catch (IllegalStateException e) {
+ // Expected.
+ }
+
+ try {
+ builder.mergeFieldFrom(0, CodedInputStream.newInstance(new byte[0]));
+ fail();
+ } catch (IllegalStateException e) {
+ // Expected.
+ }
+
+ try {
+ builder.mergeVarintField(5, 1);
+ fail();
+ } catch (IllegalStateException e) {
+ // Expected.
+ }
+ }
+
+ public void testBuilderReuse_empty() {
+ UnknownFieldSetLite.Builder builder = UnknownFieldSetLite.newBuilder();
+ builder.build();
+
+ try {
+ builder.build();
+ fail();
+ } catch (IllegalStateException e) {
+ // Expected.
+ }
+ }
+
+ public void testRoundTrips() throws InvalidProtocolBufferException {
+ Foo foo = Foo.newBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .setExtension(LiteEqualsAndHash.varint, 22)
+ .setExtension(LiteEqualsAndHash.fixed32, 44)
+ .setExtension(LiteEqualsAndHash.fixed64, 66L)
+ .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+ .setGroupValue("value")
+ .build())
+ .build();
+
+ Foo copy = Foo.parseFrom(foo.toByteArray());
+
+ assertEquals(foo.getSerializedSize(), copy.getSerializedSize());
+ assertFalse(foo.equals(copy));
+
+ Foo secondCopy = Foo.parseFrom(foo.toByteArray());
+ assertEquals(copy, secondCopy);
+
+ ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
+ LiteEqualsAndHash.registerAllExtensions(extensionRegistry);
+ Foo copyOfCopy = Foo.parseFrom(copy.toByteArray(), extensionRegistry);
+
+ assertEquals(foo, copyOfCopy);
+ }
+
+ public void testMalformedBytes() {
+ try {
+ Foo.parseFrom("this is a malformed protocol buffer".getBytes(StandardCharsets.UTF_8));
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMissingStartGroupTag() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.writeTag(100, WireFormat.WIRETYPE_END_GROUP);
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMissingEndGroupTag() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMismatchingGroupTags() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.writeTag(101, WireFormat.WIRETYPE_END_GROUP);
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testTruncatedInput() {
+ Foo foo = Foo.newBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .setExtension(LiteEqualsAndHash.varint, 22)
+ .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+ .setGroupValue("value")
+ .build())
+ .build();
+
+ try {
+ Foo.parseFrom(foo.toByteString().substring(0, foo.toByteString().size() - 10));
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ private ByteString toByteString(UnknownFieldSetLite unknownFields) {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+ try {
+ unknownFields.writeTo(output);
+ output.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return ByteString.copyFrom(byteArrayOutputStream.toByteArray());
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/field_presence_test.proto b/java/src/test/java/com/google/protobuf/field_presence_test.proto
new file mode 100644
index 00000000..8d8ea8ef
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/field_presence_test.proto
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package field_presence_test;
+
+import "google/protobuf/unittest.proto";
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "FieldPresenceTestProto";
+option java_generate_equals_and_hash = true;
+
+message TestAllTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+ message NestedMessage {
+ optional int32 value = 1;
+ }
+
+ optional int32 optional_int32 = 1;
+ optional string optional_string = 2;
+ optional bytes optional_bytes = 3;
+ optional NestedEnum optional_nested_enum = 4;
+ optional NestedMessage optional_nested_message = 5;
+ optional protobuf_unittest.TestRequired optional_proto2_message = 6;
+
+ oneof oneof_field {
+ int32 oneof_int32 = 11;
+ uint32 oneof_uint32 = 12;
+ string oneof_string = 13;
+ bytes oneof_bytes = 14;
+ NestedEnum oneof_nested_enum = 15;
+ NestedMessage oneof_nested_message = 16;
+ protobuf_unittest.TestRequired oneof_proto2_message = 17;
+ }
+
+ repeated int32 repeated_int32 = 21;
+ repeated string repeated_string = 22;
+ repeated bytes repeated_bytes = 23;
+ repeated NestedEnum repeated_nested_enum = 24;
+ repeated NestedMessage repeated_nested_message = 25;
+ repeated protobuf_unittest.TestRequired repeated_proto2_message = 26;
+ repeated NestedEnum packed_nested_enum = 27 [packed = true];
+}
+
+message TestOptionalFieldsOnly {
+ optional int32 optional_int32 = 1;
+ optional string optional_string = 2;
+ optional bytes optional_bytes = 3;
+ optional TestAllTypes.NestedEnum optional_nested_enum = 4;
+ optional TestAllTypes.NestedMessage optional_nested_message = 5;
+ optional protobuf_unittest.TestRequired optional_proto2_message = 6;
+}
+
+message TestRepeatedFieldsOnly {
+ repeated int32 repeated_int32 = 21;
+ repeated string repeated_string = 22;
+ repeated bytes repeated_bytes = 23;
+ repeated TestAllTypes.NestedEnum repeated_nested_enum = 24;
+ repeated TestAllTypes.NestedMessage repeated_nested_message = 25;
+ repeated protobuf_unittest.TestRequired repeated_proto2_message = 26;
+}
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
index baed4e10..015dc267 100644
--- a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
+++ b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
@@ -32,6 +32,7 @@
//
// A proto file with lazy fields
+syntax = "proto2";
package protobuf_unittest;
diff --git a/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto b/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto
index 68615672..86837250 100644
--- a/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto
+++ b/java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto
@@ -30,6 +30,7 @@
// Author: pbogle@google.com (Phil Bogle)
+syntax = "proto2";
package protobuf_unittest.lite_equals_and_hash;
@@ -41,9 +42,15 @@ option optimize_for = LITE_RUNTIME;
message Foo {
optional int32 value = 1;
repeated Bar bar = 2;
+
+ extensions 100 to max;
}
message Bar {
+ extend Foo {
+ optional Bar foo_ext = 100;
+ }
+
optional string name = 1;
}
@@ -53,3 +60,13 @@ message BarPrime {
message Empty {
}
+
+extend Foo {
+ optional int32 varint = 101;
+ optional fixed32 fixed32 = 102;
+ optional fixed64 fixed64 = 103;
+ optional group MyGroup = 104 {
+ optional string group_value = 1;
+ }
+}
+
diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
new file mode 100644
index 00000000..4f23a4a8
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+
+option java_outer_classname = "MapForProto2TestProto";
+option java_generate_equals_and_hash = true;
+
+message TestMap {
+ message MessageValue {
+ optional int32 value = 1;
+ }
+ enum EnumValue {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+
+ map<int32, int32> int32_to_int32_field = 1;
+ map<int32, string> int32_to_string_field = 2;
+ map<int32, bytes> int32_to_bytes_field = 3;
+ map<int32, EnumValue> int32_to_enum_field = 4;
+ map<int32, MessageValue> int32_to_message_field = 5;
+ map<string, int32> string_to_int32_field = 6;
+}
+
+message TestUnknownEnumValue {
+ // Wire-compatible with TestMap.int32_to_enum_field so we can test the
+ // parsing behavior of TestMap regarding unknown enum values.
+ map<int32, int32> int32_to_int32_field = 4;
+}
+package map_for_proto2_lite_test;
+option java_package = "map_lite_test";
+option optimize_for = LITE_RUNTIME;
diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
new file mode 100644
index 00000000..36dfbd10
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
@@ -0,0 +1,62 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package map_for_proto2_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapForProto2TestProto";
+option java_generate_equals_and_hash = true;
+
+message TestMap {
+ message MessageValue {
+ optional int32 value = 1;
+ }
+ enum EnumValue {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+
+ map<int32, int32> int32_to_int32_field = 1;
+ map<int32, string> int32_to_string_field = 2;
+ map<int32, bytes> int32_to_bytes_field = 3;
+ map<int32, EnumValue> int32_to_enum_field = 4;
+ map<int32, MessageValue> int32_to_message_field = 5;
+ map<string, int32> string_to_int32_field = 6;
+}
+
+message TestUnknownEnumValue {
+ // Wire-compatible with TestMap.int32_to_enum_field so we can test the
+ // parsing behavior of TestMap regarding unknown enum values.
+ map<int32, int32> int32_to_int32_field = 4;
+}
diff --git a/java/src/test/java/com/google/protobuf/map_test.proto b/java/src/test/java/com/google/protobuf/map_test.proto
new file mode 100644
index 00000000..105ee3f8
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/map_test.proto
@@ -0,0 +1,63 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package map_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapTestProto";
+option java_generate_equals_and_hash = true;
+
+message TestMap {
+ message MessageValue {
+ optional int32 value = 1;
+ }
+ enum EnumValue {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+
+ map<int32, int32> int32_to_int32_field = 1;
+ map<int32, string> int32_to_string_field = 2;
+ map<int32, bytes> int32_to_bytes_field = 3;
+ map<int32, EnumValue> int32_to_enum_field = 4;
+ map<int32, MessageValue> int32_to_message_field = 5;
+ map<string, int32> string_to_int32_field = 6;
+}
+
+// Used to test that a nested bulider containing map fields will properly
+// propagate the onChange event and mark its parent dirty when a change
+// is made to a map field.
+message TestOnChangeEventPropagation {
+ optional TestMap optional_message = 1;
+}
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 7ec89a05..92790506 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
@@ -32,6 +32,7 @@
//
// A proto file which tests the java_multiple_files option.
+syntax = "proto2";
// Some generic_services option(s) added automatically.
// See: http://go/proto2-generic-services-default
diff --git a/java/src/test/java/com/google/protobuf/nested_builders_test.proto b/java/src/test/java/com/google/protobuf/nested_builders_test.proto
index 8ab4a433..a5dd66d8 100644
--- a/java/src/test/java/com/google/protobuf/nested_builders_test.proto
+++ b/java/src/test/java/com/google/protobuf/nested_builders_test.proto
@@ -30,6 +30,7 @@
// Author: jonp@google.com (Jon Perlow)
//
+syntax = "proto2";
package protobuf_unittest;
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 86492867..704e649e 100644
--- a/java/src/test/java/com/google/protobuf/nested_extension.proto
+++ b/java/src/test/java/com/google/protobuf/nested_extension.proto
@@ -33,6 +33,7 @@
// A proto file with nested extensions. Note that this must be defined in
// a separate file to properly test the initialization of the outer class.
+syntax = "proto2";
import "com/google/protobuf/non_nested_extension.proto";
diff --git a/java/src/test/java/com/google/protobuf/nested_extension_lite.proto b/java/src/test/java/com/google/protobuf/nested_extension_lite.proto
index 9c686829..a95c38b2 100644
--- a/java/src/test/java/com/google/protobuf/nested_extension_lite.proto
+++ b/java/src/test/java/com/google/protobuf/nested_extension_lite.proto
@@ -34,6 +34,7 @@
// this must be defined in a separate file to properly test the initialization
// of the outer class.
+syntax = "proto2";
package protobuf_unittest;
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 cb2f8b00..31fac552 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
@@ -32,6 +32,7 @@
//
// A proto file with extensions.
+syntax = "proto2";
package protobuf_unittest;
diff --git a/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto b/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto
index c1f744b8..37c369ed 100644
--- a/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto
+++ b/java/src/test/java/com/google/protobuf/non_nested_extension_lite.proto
@@ -32,6 +32,7 @@
//
// A proto file with extensions for a MessageLite messages.
+syntax = "proto2";
package protobuf_unittest;
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
index c5114f89..42083681 100644
--- 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
@@ -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.
+syntax = "proto2";
+
package protobuf_unittest;
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
index 741cd281..3e5956b0 100644
--- 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
@@ -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.
+syntax = "proto2";
+
package protobuf_unittest;
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
index 5d5d4ac9..74a8ba3c 100644
--- 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
@@ -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.
+syntax = "proto2";
+
package protobuf_unittest;
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 202e8c91..67035fd5 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
@@ -33,6 +33,7 @@
// This file tests that various identifiers work as field and type names even
// though the same identifiers are used internally by the java code generator.
+syntax = "proto2";
// Some generic_services option(s) added automatically.
// See: http://go/proto2-generic-services-default
@@ -59,12 +60,14 @@ message Descriptor {
}
optional NestedDescriptor nested_descriptor = 2;
enum NestedEnum {
+ UNKNOWN = 0;
FOO = 1;
}
}
message Parser {
enum ParserEnum {
+ UNKNOWN = 0;
PARSER = 1;
}
optional ParserEnum parser = 1;
@@ -72,6 +75,7 @@ message Parser {
message Deprecated {
enum TestEnum {
+ UNKNOWN = 0;
FOO = 1;
// Test if @Deprecated annotation conflicts with Deprecated message name.
@@ -118,6 +122,7 @@ service TestConflictingMethodNames {
message TestConflictingFieldNames {
enum TestEnum {
+ UNKNOWN = 0;
FOO = 1;
}
message TestMessage {
@@ -142,16 +147,23 @@ message TestConflictingFieldNames {
// This field conflicts with "int32_field" as they both generate
// the method getInt32FieldList().
- required int32 int32_field_list = 31;
+ required int32 int32_field_list = 31; // NO_PROTO3
- extensions 1000 to max;
+ extensions 1000 to max; // NO_PROTO3
repeated int64 int64_field = 41;
- extend TestConflictingFieldNames {
+ extend TestConflictingFieldNames { // NO_PROTO3
// 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;
- }
+ optional int64 int64_field_count = 1001; // NO_PROTO3
+ optional int64 int64_field_list = 1002; // NO_PROTO3
+ } // NO_PROTO3
}
+message TestMapField {
+ message MapField {}
+ message Pair {}
+ message Message {}
+
+ map<int32, int32> map_field = 1;
+}
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
index 206946d8..119c1dcb 100644
--- a/java/src/test/java/com/google/protobuf/test_check_utf8.proto
+++ b/java/src/test/java/com/google/protobuf/test_check_utf8.proto
@@ -31,6 +31,7 @@
// Author: Jacob Butcher (jbaum@google.com)
//
// Test file option java_string_check_utf8.
+syntax = "proto2";
package proto2_test_check_utf8;
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
index fa057a88..f06d76d6 100644
--- 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
@@ -31,6 +31,7 @@
// Author: Jacob Butcher (jbaum@google.com)
//
// Test file option java_string_check_utf8.
+syntax = "proto2";
package proto2_test_check_utf8_size;
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
index f6a5ecd4..f8efd455 100644
--- a/java/src/test/java/com/google/protobuf/test_custom_options.proto
+++ b/java/src/test/java/com/google/protobuf/test_custom_options.proto
@@ -32,6 +32,7 @@
//
// Test that custom options defined in a proto file's dependencies are properly
// initialized.
+syntax = "proto2";
package protobuf_unittest;
diff --git a/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto b/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto
index 72e05a36..645f57b4 100644
--- a/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto
+++ b/java/src/test/java/com/google/protobuf/test_extra_interfaces.proto
@@ -29,6 +29,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: Darick Tong (darick@google.com)
+syntax = "proto2";
package protobuf_unittest;
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index 6da8bb0b..af571b7c 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -841,9 +841,10 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True):
field_proto.number, field_proto.type,
FieldDescriptor.ProtoTypeToCppProtoType(field_proto.type),
field_proto.label, None, nested_desc, enum_desc, None, False, None,
- has_default_value=False)
+ options=field_proto.options, has_default_value=False)
fields.append(field)
desc_name = '.'.join(full_message_name)
return Descriptor(desc_proto.name, desc_name, None, None, fields,
- nested_types.values(), enum_types.values(), [])
+ nested_types.values(), enum_types.values(), [],
+ options=desc_proto.options)
diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py
index 55fb8c70..b10021e9 100644
--- a/python/google/protobuf/descriptor_database.py
+++ b/python/google/protobuf/descriptor_database.py
@@ -133,5 +133,5 @@ def _ExtractSymbols(desc_proto, package):
for nested_type in desc_proto.nested_type:
for symbol in _ExtractSymbols(nested_type, message_name):
yield symbol
- for enum_type in desc_proto.enum_type:
- yield '.'.join((message_name, enum_type.name))
+ for enum_type in desc_proto.enum_type:
+ yield '.'.join((message_name, enum_type.name))
diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py
index cf234cfa..bcac513a 100644
--- a/python/google/protobuf/descriptor_pool.py
+++ b/python/google/protobuf/descriptor_pool.py
@@ -554,7 +554,7 @@ class DescriptorPool(object):
field_desc.default_value = field_proto.default_value.lower() == 'true'
elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
field_desc.default_value = field_desc.enum_type.values_by_name[
- field_proto.default_value].index
+ field_proto.default_value].number
elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
field_desc.default_value = text_encoding.CUnescape(
field_proto.default_value)
diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py
index fc65b69a..8970f5c2 100644
--- a/python/google/protobuf/internal/descriptor_database_test.py
+++ b/python/google/protobuf/internal/descriptor_database_test.py
@@ -58,6 +58,8 @@ class DescriptorDatabaseTest(basetest.TestCase):
'google.protobuf.python.internal.Factory2Enum'))
self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
'google.protobuf.python.internal.Factory2Message.NestedFactory2Enum'))
+ self.assertEquals(file_desc_proto, db.FindFileContainingSymbol(
+ 'google.protobuf.python.internal.MessageWithNestedEnumOnly.NestedEnum'))
if __name__ == '__main__':
basetest.main()
diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py
index d2f85579..11ef61c5 100644
--- a/python/google/protobuf/internal/descriptor_pool_test.py
+++ b/python/google/protobuf/internal/descriptor_pool_test.py
@@ -48,6 +48,7 @@ from google.protobuf.internal import factory_test2_pb2
from google.protobuf import descriptor
from google.protobuf import descriptor_database
from google.protobuf import descriptor_pool
+from google.protobuf import symbol_database
class DescriptorPoolTest(basetest.TestCase):
@@ -237,6 +238,32 @@ class DescriptorPoolTest(basetest.TestCase):
TEST2_FILE.CheckFile(self, self.pool)
+ def testEnumDefaultValue(self):
+ """Test the default value of enums which don't start at zero."""
+ def _CheckDefaultValue(file_descriptor):
+ default_value = (file_descriptor
+ .message_types_by_name['DescriptorPoolTest1']
+ .fields_by_name['nested_enum']
+ .default_value)
+ self.assertEqual(default_value,
+ descriptor_pool_test1_pb2.DescriptorPoolTest1.BETA)
+ # First check what the generated descriptor contains.
+ _CheckDefaultValue(descriptor_pool_test1_pb2.DESCRIPTOR)
+ # Then check the generated pool. Normally this is the same descriptor.
+ file_descriptor = symbol_database.Default().pool.FindFileByName(
+ 'google/protobuf/internal/descriptor_pool_test1.proto')
+ self.assertIs(file_descriptor, descriptor_pool_test1_pb2.DESCRIPTOR)
+ _CheckDefaultValue(file_descriptor)
+
+ # Then check the dynamic pool and its internal DescriptorDatabase.
+ descriptor_proto = descriptor_pb2.FileDescriptorProto.FromString(
+ descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb)
+ self.pool.Add(descriptor_proto)
+ # And do the same check as above
+ file_descriptor = self.pool.FindFileByName(
+ 'google/protobuf/internal/descriptor_pool_test1.proto')
+ _CheckDefaultValue(file_descriptor)
+
class ProtoFile(object):
@@ -328,7 +355,7 @@ class EnumField(object):
test.assertEqual(descriptor.FieldDescriptor.CPPTYPE_ENUM,
field_desc.cpp_type)
test.assertTrue(field_desc.has_default_value)
- test.assertEqual(enum_desc.values_by_name[self.default_value].index,
+ test.assertEqual(enum_desc.values_by_name[self.default_value].number,
field_desc.default_value)
test.assertEqual(msg_desc, field_desc.containing_type)
test.assertEqual(enum_desc, field_desc.enum_type)
diff --git a/python/google/protobuf/internal/descriptor_pool_test1.proto b/python/google/protobuf/internal/descriptor_pool_test1.proto
index 6dfe4ef3..00816b78 100644
--- a/python/google/protobuf/internal/descriptor_pool_test1.proto
+++ b/python/google/protobuf/internal/descriptor_pool_test1.proto
@@ -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.
+syntax = "proto2";
+
package google.protobuf.python.internal;
diff --git a/python/google/protobuf/internal/descriptor_pool_test2.proto b/python/google/protobuf/internal/descriptor_pool_test2.proto
index fbc84382..e3fa660c 100644
--- a/python/google/protobuf/internal/descriptor_pool_test2.proto
+++ b/python/google/protobuf/internal/descriptor_pool_test2.proto
@@ -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.
+syntax = "proto2";
+
package google.protobuf.python.internal;
import "google/protobuf/internal/descriptor_pool_test1.proto";
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index b3777e39..3924f21a 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -665,5 +665,15 @@ class MakeDescriptorTest(basetest.TestCase):
descriptor.FieldDescriptor.CPPTYPE_UINT64)
+ def testMakeDescriptorWithOptions(self):
+ descriptor_proto = descriptor_pb2.DescriptorProto()
+ aggregate_message = unittest_custom_options_pb2.AggregateMessage
+ aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto)
+ reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto)
+
+ options = reformed_descriptor.GetOptions()
+ self.assertEquals(101,
+ options.Extensions[unittest_custom_options_pb2.msgopt].i)
+
if __name__ == '__main__':
basetest.main()
diff --git a/python/google/protobuf/internal/factory_test1.proto b/python/google/protobuf/internal/factory_test1.proto
index 9f5a3919..d2fbbeec 100644
--- a/python/google/protobuf/internal/factory_test1.proto
+++ b/python/google/protobuf/internal/factory_test1.proto
@@ -30,6 +30,7 @@
// Author: matthewtoia@google.com (Matt Toia)
+syntax = "proto2";
package google.protobuf.python.internal;
diff --git a/python/google/protobuf/internal/factory_test2.proto b/python/google/protobuf/internal/factory_test2.proto
index 27feb6ce..bb1b54ad 100644
--- a/python/google/protobuf/internal/factory_test2.proto
+++ b/python/google/protobuf/internal/factory_test2.proto
@@ -30,6 +30,7 @@
// Author: matthewtoia@google.com (Matt Toia)
+syntax = "proto2";
package google.protobuf.python.internal;
@@ -87,6 +88,12 @@ message LoopMessage {
optional Factory2Message loop = 1;
}
+message MessageWithNestedEnumOnly {
+ enum NestedEnum {
+ NESTED_MESSAGE_ENUM_0 = 0;
+ }
+}
+
extend Factory1Message {
optional string another_field = 1002;
}
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index 422fa9a6..14b05cca 100755
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -35,7 +35,7 @@
# indirect testing of the protocol compiler output.
"""Unittest that directly tests the output of the pure-Python protocol
-compiler. See //google/protobuf/reflection_test.py for a test which
+compiler. See //google/protobuf/internal/reflection_test.py for a test which
further ensures that we can use Python protocol message objects as we expect.
"""
@@ -281,6 +281,8 @@ class GeneratorTest(basetest.TestCase):
"baz")
self.assertEqual(message.Extensions[test_bad_identifiers_pb2.service],
"qux")
+ self.assertEqual(message.Extensions[test_bad_identifiers_pb2.class_],
+ "Foo")
def testOneof(self):
desc = unittest_pb2.TestAllTypes.DESCRIPTOR
diff --git a/python/google/protobuf/internal/import_test_package/BUILD b/python/google/protobuf/internal/import_test_package/BUILD
new file mode 100644
index 00000000..90e59505
--- /dev/null
+++ b/python/google/protobuf/internal/import_test_package/BUILD
@@ -0,0 +1,27 @@
+# Description:
+# An example package that contains nested protos that are imported from
+# __init__.py. See testPackageInitializationImport in reflection_test.py for
+# details.
+
+package(
+ default_visibility = ["//net/proto2/python/internal:__pkg__"],
+)
+
+proto_library(
+ name = "inner_proto",
+ srcs = ["inner.proto"],
+ py_api_version = 2,
+)
+
+proto_library(
+ name = "outer_proto",
+ srcs = ["outer.proto"],
+ py_api_version = 2,
+ deps = [":inner_proto"],
+)
+
+py_library(
+ name = "import_test_package",
+ srcs = ["__init__.py"],
+ deps = [":outer_proto"],
+)
diff --git a/python/google/protobuf/internal/import_test_package/__init__.py b/python/google/protobuf/internal/import_test_package/__init__.py
new file mode 100644
index 00000000..5121dd0e
--- /dev/null
+++ b/python/google/protobuf/internal/import_test_package/__init__.py
@@ -0,0 +1,33 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Sample module importing a nested proto from itself."""
+
+from google.protobuf.internal.import_test_package import outer_pb2 as myproto
diff --git a/python/google/protobuf/internal/import_test_package/inner.proto b/python/google/protobuf/internal/import_test_package/inner.proto
new file mode 100644
index 00000000..2887c123
--- /dev/null
+++ b/python/google/protobuf/internal/import_test_package/inner.proto
@@ -0,0 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal.import_test_package;
+
+message Inner {
+ optional int32 value = 1 [default = 57];
+}
diff --git a/python/google/protobuf/internal/import_test_package/outer.proto b/python/google/protobuf/internal/import_test_package/outer.proto
new file mode 100644
index 00000000..a27fb5c8
--- /dev/null
+++ b/python/google/protobuf/internal/import_test_package/outer.proto
@@ -0,0 +1,39 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package google.protobuf.python.internal.import_test_package;
+
+import "google/protobuf/internal/import_test_package/inner.proto";
+
+message Outer {
+ optional Inner inner = 1;
+}
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 48b7ffd4..42e2ad7e 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -337,6 +337,20 @@ class MessageTest(basetest.TestCase):
empty.ParseFromString(populated.SerializeToString())
self.assertEqual(str(empty), '')
+ def testRepeatedNestedFieldIteration(self):
+ msg = unittest_pb2.TestAllTypes()
+ msg.repeated_nested_message.add(bb=1)
+ msg.repeated_nested_message.add(bb=2)
+ msg.repeated_nested_message.add(bb=3)
+ msg.repeated_nested_message.add(bb=4)
+
+ self.assertEquals([1, 2, 3, 4],
+ [m.bb for m in msg.repeated_nested_message])
+ self.assertEquals([4, 3, 2, 1],
+ [m.bb for m in reversed(msg.repeated_nested_message)])
+ self.assertEquals([4, 3, 2, 1],
+ [m.bb for m in msg.repeated_nested_message[::-1]])
+
def testSortingRepeatedScalarFieldsDefaultComparator(self):
"""Check some different types with the default comparator."""
message = unittest_pb2.TestAllTypes()
@@ -641,6 +655,32 @@ class MessageTest(basetest.TestCase):
m2.ParseFromString(m.SerializeToString())
self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+ def testOneofCopyFrom(self):
+ m = unittest_pb2.TestAllTypes()
+ m.oneof_uint32 = 11
+ m2 = unittest_pb2.TestAllTypes()
+ m2.CopyFrom(m)
+ self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+ def testOneofNestedMergeFrom(self):
+ m = unittest_pb2.NestedTestAllTypes()
+ m.payload.oneof_uint32 = 11
+ m2 = unittest_pb2.NestedTestAllTypes()
+ m2.payload.oneof_bytes = b'bb'
+ m2.child.payload.oneof_bytes = b'bb'
+ m2.MergeFrom(m)
+ self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field'))
+ self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field'))
+
+ def testOneofClear(self):
+ m = unittest_pb2.TestAllTypes()
+ m.oneof_uint32 = 11
+ m.Clear()
+ self.assertIsNone(m.WhichOneof('oneof_field'))
+ m.oneof_bytes = b'bb'
+ self.assertTrue(m.HasField('oneof_field'))
+
+
def testSortEmptyRepeatedCompositeContainer(self):
"""Exercise a scenario that has led to segfaults in the past.
"""
diff --git a/python/google/protobuf/internal/missing_enum_values.proto b/python/google/protobuf/internal/missing_enum_values.proto
index e90f0cd3..161fc5e1 100644
--- a/python/google/protobuf/internal/missing_enum_values.proto
+++ b/python/google/protobuf/internal/missing_enum_values.proto
@@ -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.
+syntax = "proto2";
+
package google.protobuf.python.internal;
message TestEnumValues {
diff --git a/python/google/protobuf/internal/more_extensions.proto b/python/google/protobuf/internal/more_extensions.proto
index c04e597f..78f14673 100644
--- a/python/google/protobuf/internal/more_extensions.proto
+++ b/python/google/protobuf/internal/more_extensions.proto
@@ -30,6 +30,7 @@
// Author: robinson@google.com (Will Robinson)
+syntax = "proto2";
package google.protobuf.internal;
diff --git a/python/google/protobuf/internal/more_extensions_dynamic.proto b/python/google/protobuf/internal/more_extensions_dynamic.proto
index 88bd9c1b..11f85ef6 100644
--- a/python/google/protobuf/internal/more_extensions_dynamic.proto
+++ b/python/google/protobuf/internal/more_extensions_dynamic.proto
@@ -34,6 +34,7 @@
// generated C++ type is available for the extendee, but the extension is
// defined in a file whose C++ type is not in the binary.
+syntax = "proto2";
import "google/protobuf/internal/more_extensions.proto";
diff --git a/python/google/protobuf/internal/more_messages.proto b/python/google/protobuf/internal/more_messages.proto
index 61db66c5..2c6ab9ef 100644
--- a/python/google/protobuf/internal/more_messages.proto
+++ b/python/google/protobuf/internal/more_messages.proto
@@ -30,6 +30,7 @@
// Author: robinson@google.com (Will Robinson)
+syntax = "proto2";
package google.protobuf.internal;
diff --git a/python/google/protobuf/internal/proto_builder_test.py b/python/google/protobuf/internal/proto_builder_test.py
new file mode 100644
index 00000000..c74db7e7
--- /dev/null
+++ b/python/google/protobuf/internal/proto_builder_test.py
@@ -0,0 +1,77 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Tests for google.protobuf.proto_builder."""
+
+from google.apputils import basetest
+
+from google.protobuf import descriptor_pb2
+from google.protobuf import descriptor_pool
+from google.protobuf import proto_builder
+from google.protobuf import text_format
+
+
+class ProtoBuilderTest(basetest.TestCase):
+
+ def setUp(self):
+ self._fields = {
+ 'foo': descriptor_pb2.FieldDescriptorProto.TYPE_INT64,
+ 'bar': descriptor_pb2.FieldDescriptorProto.TYPE_STRING,
+ }
+
+ def testMakeSimpleProtoClass(self):
+ """Test that we can create a proto class."""
+ proto_cls = proto_builder.MakeSimpleProtoClass(
+ self._fields,
+ full_name='net.proto2.python.public.proto_builder_test.Test')
+ proto = proto_cls()
+ proto.foo = 12345
+ proto.bar = 'asdf'
+ self.assertMultiLineEqual(
+ 'bar: "asdf"\nfoo: 12345\n', text_format.MessageToString(proto))
+
+ def testMakeSameProtoClassTwice(self):
+ """Test that the DescriptorPool is used."""
+ pool = descriptor_pool.DescriptorPool()
+ proto_cls1 = proto_builder.MakeSimpleProtoClass(
+ self._fields,
+ full_name='net.proto2.python.public.proto_builder_test.Test',
+ pool=pool)
+ proto_cls2 = proto_builder.MakeSimpleProtoClass(
+ self._fields,
+ full_name='net.proto2.python.public.proto_builder_test.Test',
+ pool=pool)
+ self.assertIs(proto_cls1.DESCRIPTOR, proto_cls2.DESCRIPTOR)
+
+
+if __name__ == '__main__':
+ basetest.main()
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index a5c26f45..6fda6ae0 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -306,6 +306,17 @@ def _DefaultValueConstructorForField(field):
return MakeScalarDefault
+def _ReraiseTypeErrorWithFieldName(message_name, field_name):
+ """Re-raise the currently-handled TypeError with the field name added."""
+ exc = sys.exc_info()[1]
+ if len(exc.args) == 1 and type(exc) is TypeError:
+ # simple TypeError; add field name to exception message
+ exc = TypeError('%s for field %s.%s' % (str(exc), message_name, field_name))
+
+ # re-raise possibly-amended exception with original traceback:
+ raise type(exc), exc, sys.exc_info()[2]
+
+
def _AddInitMethod(message_descriptor, cls):
"""Adds an __init__ method to cls."""
fields = message_descriptor.fields
@@ -338,10 +349,16 @@ def _AddInitMethod(message_descriptor, cls):
self._fields[field] = copy
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
copy = field._default_constructor(self)
- copy.MergeFrom(field_value)
+ try:
+ copy.MergeFrom(field_value)
+ except TypeError:
+ _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
self._fields[field] = copy
else:
- setattr(self, field_name, field_value)
+ try:
+ setattr(self, field_name, field_value)
+ except TypeError:
+ _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
init.__module__ = None
init.__doc__ = None
@@ -691,6 +708,7 @@ def _AddClearMethod(message_descriptor, cls):
# Clear fields.
self._fields = {}
self._unknown_fields = ()
+ self._oneofs = {}
self._Modified()
cls.Clear = Clear
@@ -993,6 +1011,8 @@ def _AddMergeFromMethod(cls):
field_value.MergeFrom(value)
else:
self._fields[field] = value
+ if field.containing_oneof:
+ self._UpdateOneofState(field)
if msg._unknown_fields:
if not self._unknown_fields:
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index d59815d0..6b24b092 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -35,8 +35,6 @@
pure-Python protocol compiler.
"""
-__author__ = 'robinson@google.com (Will Robinson)'
-
import copy
import gc
import operator
@@ -1252,15 +1250,18 @@ class ReflectionTest(basetest.TestCase):
# Try something that *is* an extension handle, just not for
# this message...
- unknown_handle = more_extensions_pb2.optional_int_extension
- self.assertRaises(KeyError, extendee_proto.HasExtension,
- unknown_handle)
- self.assertRaises(KeyError, extendee_proto.ClearExtension,
- unknown_handle)
- self.assertRaises(KeyError, extendee_proto.Extensions.__getitem__,
- unknown_handle)
- self.assertRaises(KeyError, extendee_proto.Extensions.__setitem__,
- unknown_handle, 5)
+ for unknown_handle in (more_extensions_pb2.optional_int_extension,
+ more_extensions_pb2.optional_message_extension,
+ more_extensions_pb2.repeated_int_extension,
+ more_extensions_pb2.repeated_message_extension):
+ self.assertRaises(KeyError, extendee_proto.HasExtension,
+ unknown_handle)
+ self.assertRaises(KeyError, extendee_proto.ClearExtension,
+ unknown_handle)
+ self.assertRaises(KeyError, extendee_proto.Extensions.__getitem__,
+ unknown_handle)
+ self.assertRaises(KeyError, extendee_proto.Extensions.__setitem__,
+ unknown_handle, 5)
# Try call HasExtension() with a valid handle, but for a
# *repeated* field. (Just as with non-extension repeated
@@ -1669,16 +1670,15 @@ class ReflectionTest(basetest.TestCase):
proto.optional_string = str('Testing')
self.assertEqual(proto.optional_string, unicode('Testing'))
- # Try to assign a 'str' value which contains bytes that aren't 7-bit ASCII.
+ # Try to assign a 'bytes' object which contains non-UTF-8.
self.assertRaises(ValueError,
setattr, proto, 'optional_string', b'a\x80a')
- if str is bytes: # PY2
- # Assign a 'str' object which contains a UTF-8 encoded string.
- self.assertRaises(ValueError,
- setattr, proto, 'optional_string', 'Тест')
- else:
- proto.optional_string = 'Тест'
- # No exception thrown.
+ # No exception: Assign already encoded UTF-8 bytes to a string field.
+ utf8_bytes = u'Тест'.encode('utf-8')
+ proto.optional_string = utf8_bytes
+ # No exception: Assign the a non-ascii unicode object.
+ proto.optional_string = u'Тест'
+ # No exception thrown (normal str assignment containing ASCII).
proto.optional_string = 'abc'
def testStringUTF8Serialization(self):
@@ -1774,6 +1774,24 @@ class ReflectionTest(basetest.TestCase):
proto.optionalgroup.SetInParent()
self.assertTrue(proto.HasField('optionalgroup'))
+ def testPackageInitializationImport(self):
+ """Test that we can import nested messages from their __init__.py.
+
+ Such setup is not trivial since at the time of processing of __init__.py one
+ can't refer to its submodules by name in code, so expressions like
+ google.protobuf.internal.import_test_package.inner_pb2
+ don't work. They do work in imports, so we have assign an alias at import
+ and then use that alias in generated code.
+ """
+ # We import here since it's the import that used to fail, and we want
+ # the failure to have the right context.
+ # pylint: disable=g-import-not-at-top
+ from google.protobuf.internal import import_test_package
+ # pylint: enable=g-import-not-at-top
+ msg = import_test_package.myproto.Outer()
+ # Just check the default value.
+ self.assertEqual(57, msg.inner.value)
+
# Since we had so many tests for protocol buffer equality, we broke these out
# into separate TestCase classes.
@@ -2802,6 +2820,9 @@ class OptionsTest(basetest.TestCase):
class ClassAPITest(basetest.TestCase):
+ @basetest.unittest.skipIf(
+ api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+ 'C++ implementation requires a call to MakeDescriptor()')
def testMakeClassWithNestedDescriptor(self):
leaf_desc = descriptor.Descriptor('leaf', 'package.parent.child.leaf', '',
containing_type=None, fields=[],
diff --git a/python/google/protobuf/internal/test_bad_identifiers.proto b/python/google/protobuf/internal/test_bad_identifiers.proto
index 9eb18cb0..29fa38a2 100644
--- a/python/google/protobuf/internal/test_bad_identifiers.proto
+++ b/python/google/protobuf/internal/test_bad_identifiers.proto
@@ -30,6 +30,7 @@
// Author: kenton@google.com (Kenton Varda)
+syntax = "proto2";
package protobuf_unittest;
@@ -39,13 +40,15 @@ message TestBadIdentifiers {
extensions 100 to max;
}
-// Make sure these reasonable extension names don't conflict with internal
-// variables.
extend TestBadIdentifiers {
+ // Make sure these reasonable extension names don't conflict with internal
+ // variables.
optional string message = 100 [default="foo"];
optional string descriptor = 101 [default="bar"];
optional string reflection = 102 [default="baz"];
optional string service = 103 [default="qux"];
+ // And Python keywords.
+ optional string class = 104 [default="Foo"];
}
message AnotherMessage {}
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index b0a3a5f7..55e3c2c8 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -69,13 +69,18 @@ class TextFormatTest(basetest.TestCase):
message.my_string = '115'
message.my_int = 101
message.my_float = 111
+ message.optional_nested_message.oo = 0
+ message.optional_nested_message.bb = 1
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_format.MessageToString(
message, use_index_order=True)),
- 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n')
+ 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n'
+ 'optional_nested_message {\n oo: 0\n bb: 1\n}\n')
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_format.MessageToString(
- message)), 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n')
+ message)),
+ 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n'
+ 'optional_nested_message {\n bb: 1\n oo: 0\n}\n')
def testPrintAllExtensions(self):
message = unittest_pb2.TestAllExtensions()
@@ -511,7 +516,7 @@ class TextFormatTest(basetest.TestCase):
message.repeated_string[4])
self.assertEqual(SLASH + 'x20', message.repeated_string[5])
- def testMergeRepeatedScalars(self):
+ def testMergeDuplicateScalars(self):
message = unittest_pb2.TestAllTypes()
text = ('optional_int32: 42 '
'optional_int32: 67')
@@ -519,7 +524,7 @@ class TextFormatTest(basetest.TestCase):
self.assertIs(r, message)
self.assertEqual(67, message.optional_int32)
- def testParseRepeatedScalars(self):
+ def testParseDuplicateScalars(self):
message = unittest_pb2.TestAllTypes()
text = ('optional_int32: 42 '
'optional_int32: 67')
@@ -529,7 +534,7 @@ class TextFormatTest(basetest.TestCase):
'have multiple "optional_int32" fields.'),
text_format.Parse, text, message)
- def testMergeRepeatedNestedMessageScalars(self):
+ def testMergeDuplicateNestedMessageScalars(self):
message = unittest_pb2.TestAllTypes()
text = ('optional_nested_message { bb: 1 } '
'optional_nested_message { bb: 2 }')
@@ -537,7 +542,7 @@ class TextFormatTest(basetest.TestCase):
self.assertTrue(r is message)
self.assertEqual(2, message.optional_nested_message.bb)
- def testParseRepeatedNestedMessageScalars(self):
+ def testParseDuplicateNestedMessageScalars(self):
message = unittest_pb2.TestAllTypes()
text = ('optional_nested_message { bb: 1 } '
'optional_nested_message { bb: 2 }')
@@ -547,7 +552,7 @@ class TextFormatTest(basetest.TestCase):
'should not have multiple "bb" fields.'),
text_format.Parse, text, message)
- def testMergeRepeatedExtensionScalars(self):
+ def testMergeDuplicateExtensionScalars(self):
message = unittest_pb2.TestAllExtensions()
text = ('[protobuf_unittest.optional_int32_extension]: 42 '
'[protobuf_unittest.optional_int32_extension]: 67')
@@ -556,7 +561,7 @@ class TextFormatTest(basetest.TestCase):
67,
message.Extensions[unittest_pb2.optional_int32_extension])
- def testParseRepeatedExtensionScalars(self):
+ def testParseDuplicateExtensionScalars(self):
message = unittest_pb2.TestAllExtensions()
text = ('[protobuf_unittest.optional_int32_extension]: 42 '
'[protobuf_unittest.optional_int32_extension]: 67')
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index 56d26460..118725da 100755
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -154,14 +154,13 @@ class UnicodeValueChecker(object):
(proposed_value, type(proposed_value), (bytes, unicode)))
raise TypeError(message)
- # If the value is of type 'bytes' make sure that it is in 7-bit ASCII
- # encoding.
+ # If the value is of type 'bytes' make sure that it is valid UTF-8 data.
if isinstance(proposed_value, bytes):
try:
- proposed_value = proposed_value.decode('ascii')
+ proposed_value = proposed_value.decode('utf-8')
except UnicodeDecodeError:
- raise ValueError('%.1024r has type bytes, but isn\'t in 7-bit ASCII '
- 'encoding. Non-ASCII strings must be converted to '
+ raise ValueError('%.1024r has type bytes, but isn\'t valid UTF-8 '
+ 'encoding. Non-UTF-8 strings must be converted to '
'unicode objects before being added.' %
(proposed_value))
return proposed_value
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index 71775609..a4dc1f7c 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -38,12 +38,16 @@ __author__ = 'bohdank@google.com (Bohdan Koval)'
from google.apputils import basetest
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
+from google.protobuf.internal import api_implementation
from google.protobuf.internal import encoder
from google.protobuf.internal import missing_enum_values_pb2
from google.protobuf.internal import test_util
from google.protobuf.internal import type_checkers
+@basetest.unittest.skipIf(
+ api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+ 'C++ implementation does not expose unknown fields to Python')
class UnknownFieldsTest(basetest.TestCase):
def setUp(self):
@@ -175,7 +179,10 @@ class UnknownFieldsTest(basetest.TestCase):
self.assertNotEqual(self.empty_message, message)
-class UnknownFieldsTest(basetest.TestCase):
+@basetest.unittest.skipIf(
+ api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+ 'C++ implementation does not expose unknown fields to Python')
+class UnknownEnumValuesTest(basetest.TestCase):
def setUp(self):
self.descriptor = missing_enum_values_pb2.TestEnumValues.DESCRIPTOR
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index c186452a..88ed9f4c 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -233,12 +233,21 @@ class Message(object):
raise NotImplementedError
def HasField(self, field_name):
- """Checks if a certain field is set for the message. Note if the
- field_name is not defined in the message descriptor, ValueError will be
- raised."""
+ """Checks if a certain field is set for the message, or if any field inside
+ a oneof group is set. Note that if the field_name is not defined in the
+ message descriptor, ValueError will be raised."""
raise NotImplementedError
def ClearField(self, field_name):
+ """Clears the contents of a given field, or the field set inside a oneof
+ group. If the name neither refers to a defined field or oneof group,
+ ValueError is raised."""
+ raise NotImplementedError
+
+ def WhichOneof(self, oneof_group):
+ """Returns the name of the field that is set inside a oneof group, or
+ None if no field is set. If no group with the given name exists, ValueError
+ will be raised."""
raise NotImplementedError
def HasExtension(self, extension_handle):
diff --git a/python/google/protobuf/proto_builder.py b/python/google/protobuf/proto_builder.py
new file mode 100644
index 00000000..1fa28f1a
--- /dev/null
+++ b/python/google/protobuf/proto_builder.py
@@ -0,0 +1,98 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Dynamic Protobuf class creator."""
+
+import hashlib
+import os
+
+from google.protobuf import descriptor_pb2
+from google.protobuf import message_factory
+
+
+def _GetMessageFromFactory(factory, full_name):
+ """Get a proto class from the MessageFactory by name.
+
+ Args:
+ factory: a MessageFactory instance.
+ full_name: str, the fully qualified name of the proto type.
+ Returns:
+ a class, for the type identified by full_name.
+ Raises:
+ KeyError, if the proto is not found in the factory's descriptor pool.
+ """
+ proto_descriptor = factory.pool.FindMessageTypeByName(full_name)
+ proto_cls = factory.GetPrototype(proto_descriptor)
+ return proto_cls
+
+
+def MakeSimpleProtoClass(fields, full_name, pool=None):
+ """Create a Protobuf class whose fields are basic types.
+
+ Note: this doesn't validate field names!
+
+ Args:
+ fields: dict of {name: field_type} mappings for each field in the proto.
+ full_name: str, the fully-qualified name of the proto type.
+ pool: optional DescriptorPool instance.
+ Returns:
+ a class, the new protobuf class with a FileDescriptor.
+ """
+ factory = message_factory.MessageFactory(pool=pool)
+ try:
+ proto_cls = _GetMessageFromFactory(factory, full_name)
+ return proto_cls
+ except KeyError:
+ # The factory's DescriptorPool doesn't know about this class yet.
+ pass
+
+ # Use a consistent file name that is unlikely to conflict with any imported
+ # proto files.
+ fields_hash = hashlib.sha1()
+ for f_name, f_type in sorted(fields.items()):
+ fields_hash.update(f_name.encode('utf8'))
+ fields_hash.update(str(f_type).encode('utf8'))
+ proto_file_name = fields_hash.hexdigest() + '.proto'
+
+ package, name = full_name.rsplit('.', 1)
+ file_proto = descriptor_pb2.FileDescriptorProto()
+ file_proto.name = os.path.join(package.replace('.', '/'), proto_file_name)
+ file_proto.package = package
+ desc_proto = file_proto.message_type.add()
+ desc_proto.name = name
+ for f_number, (f_name, f_type) in enumerate(sorted(fields.items()), 1):
+ field_proto = desc_proto.field.add()
+ field_proto.name = f_name
+ field_proto.number = f_number
+ field_proto.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
+ field_proto.type = f_type
+
+ factory.pool.Add(file_proto)
+ return _GetMessageFromFactory(factory, full_name)
diff --git a/python/google/protobuf/pyext/cpp_message.py b/python/google/protobuf/pyext/cpp_message.py
index dcf34a02..037bb72c 100644
--- a/python/google/protobuf/pyext/cpp_message.py
+++ b/python/google/protobuf/pyext/cpp_message.py
@@ -53,9 +53,5 @@ def NewMessage(bases, message_descriptor, dictionary):
def InitMessage(message_descriptor, cls):
- """Constructs a new message instance (called before instance's __init__)."""
-
- def SubInit(self, **kwargs):
- super(cls, self).__init__(message_descriptor, **kwargs)
- cls.__init__ = SubInit
+ """Finalizes the creation of a message class."""
cls.AddDescriptors(message_descriptor)
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 3f7be73c..55bb0b72 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#define C(str) const_cast<char*>(str)
@@ -46,7 +47,7 @@
#error "Python 3.0 - 3.2 are not supported."
#else
#define PyString_AsString(ob) \
- (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob))
+ (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
#endif
#endif
@@ -65,10 +66,80 @@ namespace python {
static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
+namespace cmessage_descriptor {
+
+static void Dealloc(CMessageDescriptor* self) {
+ Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyObject* GetFullName(CMessageDescriptor* self, void *closure) {
+ return PyString_FromStringAndSize(
+ self->descriptor->full_name().c_str(),
+ self->descriptor->full_name().size());
+}
+
+static PyObject* GetName(CMessageDescriptor *self, void *closure) {
+ return PyString_FromStringAndSize(
+ self->descriptor->name().c_str(),
+ self->descriptor->name().size());
+}
+
+static PyGetSetDef Getters[] = {
+ { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
+ { C("name"), (getter)GetName, NULL, "Unqualified name", NULL},
+ {NULL}
+};
+
+} // namespace cmessage_descriptor
+
+PyTypeObject CMessageDescriptor_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ C("google.protobuf.internal."
+ "_net_proto2___python."
+ "CMessageDescriptor"), // tp_name
+ sizeof(CMessageDescriptor), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)cmessage_descriptor::Dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ C("A Message 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
+ cmessage_descriptor::Getters, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ PyType_GenericAlloc, // tp_alloc
+ PyType_GenericNew, // tp_new
+ PyObject_Del, // tp_free
+};
+
+
namespace cfield_descriptor {
static void Dealloc(CFieldDescriptor* self) {
- Py_CLEAR(self->descriptor_field);
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
@@ -98,7 +169,7 @@ static PyObject* GetID(CFieldDescriptor *self, void *closure) {
static PyGetSetDef Getters[] = {
{ C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
- { C("name"), (getter)GetName, NULL, "last name", NULL},
+ { C("name"), (getter)GetName, NULL, "Unqualified name", NULL},
{ C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL},
{ C("label"), (getter)GetLabel, NULL, "Label", NULL},
{ C("id"), (getter)GetID, NULL, "ID", NULL},
@@ -151,13 +222,56 @@ PyTypeObject CFieldDescriptor_Type = {
PyObject_Del, // tp_free
};
+
namespace cdescriptor_pool {
-static void Dealloc(CDescriptorPool* self) {
+PyDescriptorPool* NewDescriptorPool() {
+ PyDescriptorPool* cdescriptor_pool = PyObject_New(
+ PyDescriptorPool, &PyDescriptorPool_Type);
+ if (cdescriptor_pool == NULL) {
+ return NULL;
+ }
+
+ // Build a DescriptorPool for messages only declared in Python libraries.
+ // generated_pool() contains all messages linked in C++ libraries, and is used
+ // as underlay.
+ cdescriptor_pool->pool = new google::protobuf::DescriptorPool(
+ google::protobuf::DescriptorPool::generated_pool());
+
+ // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
+ // storage.
+ cdescriptor_pool->classes_by_descriptor =
+ new PyDescriptorPool::ClassesByMessageMap();
+
+ return cdescriptor_pool;
+}
+
+static void Dealloc(PyDescriptorPool* self) {
+ for (auto it : (*self->classes_by_descriptor)) {
+ Py_DECREF(it.second);
+ }
+ delete self->classes_by_descriptor;
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
-static PyObject* NewCDescriptor(
+const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
+ const string& name) {
+ return self->pool->FindMessageTypeByName(name);
+}
+
+static PyObject* NewCMessageDescriptor(
+ const google::protobuf::Descriptor* message_descriptor) {
+ CMessageDescriptor* cmessage_descriptor = PyObject_New(
+ CMessageDescriptor, &CMessageDescriptor_Type);
+ if (cmessage_descriptor == NULL) {
+ return NULL;
+ }
+ cmessage_descriptor->descriptor = message_descriptor;
+
+ return reinterpret_cast<PyObject*>(cmessage_descriptor);
+}
+
+static PyObject* NewCFieldDescriptor(
const google::protobuf::FieldDescriptor* field_descriptor) {
CFieldDescriptor* cfield_descriptor = PyObject_New(
CFieldDescriptor, &CFieldDescriptor_Type);
@@ -165,12 +279,61 @@ static PyObject* NewCDescriptor(
return NULL;
}
cfield_descriptor->descriptor = field_descriptor;
- cfield_descriptor->descriptor_field = NULL;
return reinterpret_cast<PyObject*>(cfield_descriptor);
}
-PyObject* FindFieldByName(CDescriptorPool* self, PyObject* name) {
+// Add a message class to our database.
+const google::protobuf::Descriptor* RegisterMessageClass(
+ PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) {
+ ScopedPyObjectPtr full_message_name(
+ PyObject_GetAttrString(descriptor, "full_name"));
+ const char* full_name = PyString_AsString(full_message_name);
+ if (full_name == NULL) {
+ return NULL;
+ }
+ const Descriptor *message_descriptor =
+ self->pool->FindMessageTypeByName(full_name);
+ if (!message_descriptor) {
+ PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'",
+ full_name);
+ return NULL;
+ }
+ Py_INCREF(message_class);
+ auto ret = self->classes_by_descriptor->insert(
+ make_pair(message_descriptor, message_class));
+ if (!ret.second) {
+ // Update case: DECREF the previous value.
+ Py_DECREF(ret.first->second);
+ ret.first->second = message_class;
+ }
+
+ // Also add the C++ descriptor to the Python descriptor class.
+ ScopedPyObjectPtr cdescriptor(NewCMessageDescriptor(message_descriptor));
+ if (cdescriptor == NULL) {
+ return NULL;
+ }
+ if (PyObject_SetAttrString(
+ descriptor, "_cdescriptor", cdescriptor) < 0) {
+ return NULL;
+ }
+ return message_descriptor;
+}
+
+// Retrieve the message class added to our database.
+PyObject *GetMessageClass(PyDescriptorPool* self,
+ const Descriptor *message_descriptor) {
+ auto ret = self->classes_by_descriptor->find(message_descriptor);
+ if (ret == self->classes_by_descriptor->end()) {
+ PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
+ message_descriptor->full_name().c_str());
+ return NULL;
+ } else {
+ return ret->second;
+ }
+}
+
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name) {
const char* full_field_name = PyString_AsString(name);
if (full_field_name == NULL) {
return NULL;
@@ -186,10 +349,10 @@ PyObject* FindFieldByName(CDescriptorPool* self, PyObject* name) {
return NULL;
}
- return NewCDescriptor(field_descriptor);
+ return NewCFieldDescriptor(field_descriptor);
}
-PyObject* FindExtensionByName(CDescriptorPool* self, PyObject* arg) {
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
const char* full_field_name = PyString_AsString(arg);
if (full_field_name == NULL) {
return NULL;
@@ -203,7 +366,7 @@ PyObject* FindExtensionByName(CDescriptorPool* self, PyObject* arg) {
return NULL;
}
- return NewCDescriptor(field_descriptor);
+ return NewCFieldDescriptor(field_descriptor);
}
static PyMethodDef Methods[] = {
@@ -220,12 +383,12 @@ static PyMethodDef Methods[] = {
} // namespace cdescriptor_pool
-PyTypeObject CDescriptorPool_Type = {
+PyTypeObject PyDescriptorPool_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
C("google.protobuf.internal."
"_net_proto2___python."
"CFieldDescriptor"), // tp_name
- sizeof(CDescriptorPool), // tp_basicsize
+ sizeof(PyDescriptorPool), // tp_basicsize
0, // tp_itemsize
(destructor)cdescriptor_pool::Dealloc, // tp_dealloc
0, // tp_print
@@ -259,29 +422,11 @@ PyTypeObject CDescriptorPool_Type = {
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
- PyType_GenericAlloc, // tp_alloc
- PyType_GenericNew, // tp_new
+ 0, // tp_alloc
+ 0, // tp_new
PyObject_Del, // tp_free
};
-google::protobuf::DescriptorPool* GetDescriptorPool() {
- if (g_descriptor_pool == NULL) {
- g_descriptor_pool = new google::protobuf::DescriptorPool(
- google::protobuf::DescriptorPool::generated_pool());
- }
- return g_descriptor_pool;
-}
-
-PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args) {
- CDescriptorPool* cdescriptor_pool = PyObject_New(
- CDescriptorPool, &CDescriptorPool_Type);
- if (cdescriptor_pool == NULL) {
- return NULL;
- }
- cdescriptor_pool->pool = GetDescriptorPool();
- return reinterpret_cast<PyObject*>(cdescriptor_pool);
-}
-
// Collects errors that occur during proto file building to allow them to be
// propagated in the python exception instead of only living in ERROR logs.
@@ -321,6 +466,8 @@ PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
return NULL;
}
+ // If the file was already part of a C++ library, all its descriptors are in
+ // the underlying pool. No need to do anything else.
if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
file_proto.name()) != NULL) {
Py_RETURN_NONE;
@@ -328,8 +475,8 @@ PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
BuildFileErrorCollector error_collector;
const google::protobuf::FileDescriptor* descriptor =
- GetDescriptorPool()->BuildFileCollectingErrors(file_proto,
- &error_collector);
+ GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto,
+ &error_collector);
if (descriptor == NULL) {
PyErr_Format(PyExc_TypeError,
"Couldn't build proto file into descriptor pool!\n%s",
@@ -341,12 +488,13 @@ PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
}
bool InitDescriptor() {
- CFieldDescriptor_Type.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&CMessageDescriptor_Type) < 0)
+ return false;
if (PyType_Ready(&CFieldDescriptor_Type) < 0)
return false;
- CDescriptorPool_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&CDescriptorPool_Type) < 0)
+ PyDescriptorPool_Type.tp_new = PyType_GenericNew;
+ if (PyType_Ready(&PyDescriptorPool_Type) < 0)
return false;
return true;
diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h
index ae7a1b9c..9e5957b5 100644
--- a/python/google/protobuf/pyext/descriptor.h
+++ b/python/google/protobuf/pyext/descriptor.h
@@ -36,6 +36,8 @@
#include <Python.h>
#include <structmember.h>
+#include <google/protobuf/stubs/hash.h>
+
#include <google/protobuf/descriptor.h>
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
@@ -48,46 +50,90 @@ namespace google {
namespace protobuf {
namespace python {
+typedef struct CMessageDescriptor {
+ PyObject_HEAD
+
+ // The proto2 descriptor that this object represents.
+ const google::protobuf::Descriptor* descriptor;
+} CMessageDescriptor;
+
+
typedef struct CFieldDescriptor {
PyObject_HEAD
// The proto2 descriptor that this object represents.
const google::protobuf::FieldDescriptor* descriptor;
-
- // Reference to the original field object in the Python DESCRIPTOR.
- PyObject* descriptor_field;
} CFieldDescriptor;
-typedef struct {
+
+// Wraps operations to the global DescriptorPool which contains information
+// about all messages and fields.
+//
+// There is normally one pool per process. We make it a Python object only
+// because it contains many Python references.
+// TODO(amauryfa): See whether such objects can appear in reference cycles, and
+// consider adding support for the cyclic GC.
+//
+// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool
+// namespace.
+typedef struct PyDescriptorPool {
PyObject_HEAD
- const google::protobuf::DescriptorPool* pool;
-} CDescriptorPool;
+ google::protobuf::DescriptorPool* pool;
+ // Make our own mapping to retrieve Python classes from C++ descriptors.
+ //
+ // Descriptor pointers stored here are owned by the DescriptorPool above.
+ // Python references to classes are owned by this PyDescriptorPool.
+ typedef hash_map<const Descriptor *, PyObject *> ClassesByMessageMap;
+ ClassesByMessageMap *classes_by_descriptor;
+} PyDescriptorPool;
+
+
+extern PyTypeObject CMessageDescriptor_Type;
extern PyTypeObject CFieldDescriptor_Type;
-extern PyTypeObject CDescriptorPool_Type;
+extern PyTypeObject PyDescriptorPool_Type;
+
namespace cdescriptor_pool {
+// Builds a new DescriptorPool. Normally called only once per process.
+PyDescriptorPool* NewDescriptorPool();
+
+// Looks up a message by name.
+// Returns a message Descriptor, or NULL if not found.
+const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
+ const string& name);
+
+// Registers a new Python class for the given message descriptor.
+// Returns the message Descriptor.
+// On error, returns NULL with a Python exception set.
+const google::protobuf::Descriptor* RegisterMessageClass(
+ PyDescriptorPool* self, PyObject *message_class, PyObject *descriptor);
+
+// Retrieves the Python class registered with the given message descriptor.
+//
+// Returns a *borrowed* reference if found, otherwise returns NULL with an
+// exception set.
+PyObject *GetMessageClass(PyDescriptorPool* self,
+ const Descriptor *message_descriptor);
+
// Looks up a field by name. Returns a CDescriptor corresponding to
// the field on success, or NULL on failure.
//
// Returns a new reference.
-PyObject* FindFieldByName(CDescriptorPool* self, PyObject* name);
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name);
// Looks up an extension by name. Returns a CDescriptor corresponding
// to the field on success, or NULL on failure.
//
// Returns a new reference.
-PyObject* FindExtensionByName(CDescriptorPool* self, PyObject* arg);
-
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg);
} // namespace cdescriptor_pool
-PyObject* Python_NewCDescriptorPool(PyObject* ignored, PyObject* args);
PyObject* Python_BuildFile(PyObject* ignored, PyObject* args);
bool InitDescriptor();
-google::protobuf::DescriptorPool* GetDescriptorPool();
} // namespace python
} // namespace protobuf
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index 3861c794..d83b57d5 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -62,22 +62,6 @@ static google::protobuf::Message* GetMessage(ExtensionDict* self) {
}
}
-CFieldDescriptor* InternalGetCDescriptorFromExtension(PyObject* extension) {
- PyObject* cdescriptor = PyObject_GetAttrString(extension, "_cdescriptor");
- if (cdescriptor == NULL) {
- PyErr_SetString(PyExc_KeyError, "Unregistered extension.");
- return NULL;
- }
- if (!PyObject_TypeCheck(cdescriptor, &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Not a CFieldDescriptor");
- Py_DECREF(cdescriptor);
- return NULL;
- }
- CFieldDescriptor* descriptor =
- reinterpret_cast<CFieldDescriptor*>(cdescriptor);
- return descriptor;
-}
-
PyObject* len(ExtensionDict* self) {
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(PyDict_Size(self->values));
@@ -118,16 +102,15 @@ int ReleaseExtension(ExtensionDict* self,
}
PyObject* subscript(ExtensionDict* self, PyObject* key) {
- CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension(
- key);
- if (cdescriptor == NULL) {
+ const google::protobuf::FieldDescriptor* descriptor =
+ cmessage::GetExtensionDescriptor(key);
+ if (descriptor == NULL) {
return NULL;
}
- ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor));
- const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor;
- if (descriptor == NULL) {
+ if (!CheckFieldBelongsToMessage(descriptor, self->parent->message)) {
return NULL;
}
+
if (descriptor->label() != FieldDescriptor::LABEL_REPEATED &&
descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
return cmessage::InternalGetScalar(self->parent, descriptor);
@@ -142,7 +125,7 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
if (descriptor->label() != FieldDescriptor::LABEL_REPEATED &&
descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyObject* sub_message = cmessage::InternalGetSubMessage(
- self->parent, cdescriptor);
+ self->parent, descriptor);
if (sub_message == NULL) {
return NULL;
}
@@ -152,33 +135,21 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- // COPIED
- PyObject* py_container = PyObject_CallObject(
- reinterpret_cast<PyObject*>(&RepeatedCompositeContainer_Type),
- NULL);
+ PyObject *message_class = cdescriptor_pool::GetMessageClass(
+ GetDescriptorPool(), descriptor->message_type());
+ if (message_class == NULL) {
+ return NULL;
+ }
+ PyObject* py_container = repeated_composite_container::NewContainer(
+ self->parent, descriptor, message_class);
if (py_container == NULL) {
return NULL;
}
- RepeatedCompositeContainer* container =
- reinterpret_cast<RepeatedCompositeContainer*>(py_container);
- PyObject* field = cdescriptor->descriptor_field;
- PyObject* message_type = PyObject_GetAttrString(field, "message_type");
- PyObject* concrete_class = PyObject_GetAttrString(message_type,
- "_concrete_class");
- container->owner = self->owner;
- container->parent = self->parent;
- container->message = self->parent->message;
- container->parent_field = cdescriptor;
- container->subclass_init = concrete_class;
- Py_DECREF(message_type);
PyDict_SetItem(self->values, key, py_container);
return py_container;
} else {
- // COPIED
- ScopedPyObjectPtr init_args(PyTuple_Pack(2, self->parent, cdescriptor));
- PyObject* py_container = PyObject_CallObject(
- reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type),
- init_args);
+ PyObject* py_container = repeated_scalar_container::NewContainer(
+ self->parent, descriptor);
if (py_container == NULL) {
return NULL;
}
@@ -191,13 +162,15 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
}
int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
- CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension(
- key);
- if (cdescriptor == NULL) {
+ const google::protobuf::FieldDescriptor* descriptor =
+ cmessage::GetExtensionDescriptor(key);
+ if (descriptor == NULL) {
+ return -1;
+ }
+ if (!CheckFieldBelongsToMessage(descriptor, self->parent->message)) {
return -1;
}
- ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor));
- const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor;
+
if (descriptor->label() != FieldDescriptor::LABEL_OPTIONAL ||
descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyErr_SetString(PyExc_TypeError, "Extension is repeated and/or composite "
@@ -214,20 +187,18 @@ int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
}
PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
- CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension(
- extension);
- if (cdescriptor == NULL) {
+ const google::protobuf::FieldDescriptor* descriptor =
+ cmessage::GetExtensionDescriptor(extension);
+ if (descriptor == NULL) {
return NULL;
}
- ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor));
PyObject* value = PyDict_GetItem(self->values, extension);
if (value != NULL) {
- if (ReleaseExtension(self, value, cdescriptor->descriptor) < 0) {
+ if (ReleaseExtension(self, value, descriptor) < 0) {
return NULL;
}
}
- if (cmessage::ClearFieldByDescriptor(self->parent,
- cdescriptor->descriptor) == NULL) {
+ if (cmessage::ClearFieldByDescriptor(self->parent, descriptor) == NULL) {
return NULL;
}
if (PyDict_DelItem(self->values, extension) < 0) {
@@ -237,14 +208,12 @@ PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
}
PyObject* HasExtension(ExtensionDict* self, PyObject* extension) {
- CFieldDescriptor* cdescriptor = InternalGetCDescriptorFromExtension(
- extension);
- if (cdescriptor == NULL) {
+ const google::protobuf::FieldDescriptor* descriptor =
+ cmessage::GetExtensionDescriptor(extension);
+ if (descriptor == NULL) {
return NULL;
}
- ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor));
- PyObject* result = cmessage::HasFieldByDescriptor(
- self->parent, cdescriptor->descriptor);
+ PyObject* result = cmessage::HasFieldByDescriptor(self->parent, descriptor);
return result;
}
@@ -263,11 +232,18 @@ PyObject* _FindExtensionByName(ExtensionDict* self, PyObject* name) {
}
}
-int init(ExtensionDict* self, PyObject* args, PyObject* kwargs) {
- self->parent = NULL;
- self->message = NULL;
+ExtensionDict* NewExtensionDict(CMessage *parent) {
+ ExtensionDict* self = reinterpret_cast<ExtensionDict*>(
+ PyType_GenericAlloc(&ExtensionDict_Type, 0));
+ if (self == NULL) {
+ return NULL;
+ }
+
+ self->parent = parent; // Store a borrowed reference.
+ self->message = parent->message;
+ self->owner = parent->owner;
self->values = PyDict_New();
- return 0;
+ return self;
}
void dealloc(ExtensionDict* self) {
@@ -330,7 +306,7 @@ PyTypeObject ExtensionDict_Type = {
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
- (initproc)extension_dict::init, // tp_init
+ 0, // tp_init
};
} // namespace python
diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h
index 13c874a4..47625e23 100644
--- a/python/google/protobuf/pyext/extension_dict.h
+++ b/python/google/protobuf/pyext/extension_dict.h
@@ -53,13 +53,26 @@ using internal::shared_ptr;
namespace python {
struct CMessage;
-struct CFieldDescriptor;
typedef struct ExtensionDict {
PyObject_HEAD;
+
+ // This is the top-level C++ Message object that owns the whole
+ // proto tree. Every Python container class holds a
+ // reference to it in order to keep it alive as long as there's a
+ // Python object that references any part of the tree.
shared_ptr<Message> owner;
+
+ // Weak reference to parent message. Used to make sure
+ // the parent is writable when an extension field is modified.
CMessage* parent;
+
+ // Pointer to the C++ Message that this ExtensionDict extends.
+ // Not owned by us.
Message* message;
+
+ // A dict of child messages, indexed by Extension descriptors.
+ // Similar to CMessage::composite_fields.
PyObject* values;
} ExtensionDict;
@@ -67,11 +80,8 @@ extern PyTypeObject ExtensionDict_Type;
namespace extension_dict {
-// Gets the _cdescriptor reference to a CFieldDescriptor object given a
-// python descriptor object.
-//
-// Returns a new reference.
-CFieldDescriptor* InternalGetCDescriptorFromExtension(PyObject* extension);
+// Builds an Extensions dict for a specific message.
+ExtensionDict* NewExtensionDict(CMessage *parent);
// Gets the number of extension values in this ExtensionDict as a python object.
//
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 9fb7083f..cd956e0e 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -71,7 +71,7 @@
#error "Python 3.0 - 3.2 are not supported."
#else
#define PyString_AsString(ob) \
- (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob))
+ (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
#endif
#endif
@@ -81,7 +81,9 @@ namespace python {
// Forward declarations
namespace cmessage {
-static PyObject* GetDescriptor(CMessage* self, PyObject* name);
+static const google::protobuf::FieldDescriptor* GetFieldDescriptor(
+ CMessage* self, PyObject* name);
+static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls);
static string GetMessageName(CMessage* self);
int InternalReleaseFieldByDescriptor(
const google::protobuf::FieldDescriptor* field_descriptor,
@@ -147,12 +149,15 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
PyObject* key;
PyObject* field;
+ // Never use self->message in this function, it may be already freed.
+ const google::protobuf::Descriptor* message_descriptor =
+ cmessage::GetMessageDescriptor(Py_TYPE(self));
+
// Visit normal fields.
while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
- PyObject* cdescriptor = cmessage::GetDescriptor(self, key);
- if (cdescriptor != NULL) {
- const google::protobuf::FieldDescriptor* descriptor =
- reinterpret_cast<CFieldDescriptor*>(cdescriptor)->descriptor;
+ const google::protobuf::FieldDescriptor* descriptor =
+ message_descriptor->FindFieldByName(PyString_AsString(key));
+ if (descriptor != NULL) {
if (VisitCompositeField(descriptor, field, visitor) == -1)
return -1;
}
@@ -161,11 +166,11 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
// Visit extension fields.
if (self->extensions != NULL) {
while (PyDict_Next(self->extensions->values, &pos, &key, &field)) {
- CFieldDescriptor* cdescriptor =
- extension_dict::InternalGetCDescriptorFromExtension(key);
- if (cdescriptor == NULL)
+ const google::protobuf::FieldDescriptor* descriptor =
+ cmessage::GetExtensionDescriptor(key);
+ if (descriptor == NULL)
return -1;
- if (VisitCompositeField(cdescriptor->descriptor, field, visitor) == -1)
+ if (VisitCompositeField(descriptor, field, visitor) == -1)
return -1;
}
}
@@ -191,18 +196,19 @@ PyObject* PickleError_class;
// Constant PyString values used for GetAttr/GetItem.
static PyObject* kDESCRIPTOR;
-static PyObject* k__descriptors;
+static PyObject* k_cdescriptor;
static PyObject* kfull_name;
static PyObject* kname;
-static PyObject* kmessage_type;
-static PyObject* kis_extendable;
static PyObject* kextensions_by_name;
static PyObject* k_extensions_by_name;
static PyObject* k_extensions_by_number;
-static PyObject* k_concrete_class;
static PyObject* kfields_by_name;
-static CDescriptorPool* descriptor_pool;
+static PyDescriptorPool* descriptor_pool;
+
+PyDescriptorPool* GetDescriptorPool() {
+ return descriptor_pool;
+}
/* Is 64bit */
void FormatTypeError(PyObject* arg, char* expected_types) {
@@ -313,12 +319,12 @@ bool CheckAndSetString(
}
if (PyBytes_Check(arg)) {
- PyObject* unicode = PyUnicode_FromEncodedObject(arg, "ascii", NULL);
+ PyObject* unicode = PyUnicode_FromEncodedObject(arg, "utf-8", 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 "
+ "%s has type str, but isn't valid UTF-8 "
+ "encoding. Non-UTF-8 strings must be converted to "
"unicode objects before being added.",
PyString_AsString(repr));
Py_DECREF(repr);
@@ -335,12 +341,9 @@ bool CheckAndSetString(
PyObject* encoded_string = NULL;
if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
if (PyBytes_Check(arg)) {
-#if PY_MAJOR_VERSION < 3
- encoded_string = PyString_AsEncodedObject(arg, "utf-8", NULL);
-#else
+ // The bytes were already validated as correctly encoded UTF-8 above.
encoded_string = arg; // Already encoded.
Py_INCREF(encoded_string);
-#endif
} else {
encoded_string = PyUnicode_AsEncodedObject(arg, "utf-8", NULL);
}
@@ -391,6 +394,17 @@ PyObject* ToStringObject(
return result;
}
+bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor,
+ const google::protobuf::Message* message) {
+ if (message->GetDescriptor() == field_descriptor->containing_type()) {
+ return true;
+ }
+ PyErr_Format(PyExc_KeyError, "Field '%s' does not belong to message '%s'",
+ field_descriptor->full_name().c_str(),
+ message->GetDescriptor()->full_name().c_str());
+ return false;
+}
+
google::protobuf::DynamicMessageFactory* global_message_factory;
namespace cmessage {
@@ -489,7 +503,7 @@ int AssureWritable(CMessage* self) {
google::protobuf::Message* parent_message = self->parent->message;
google::protobuf::Message* mutable_message = GetMutableMessage(
self->parent,
- self->parent_field->descriptor);
+ self->parent_field_descriptor);
if (mutable_message == NULL) {
return -1;
}
@@ -512,26 +526,61 @@ int AssureWritable(CMessage* self) {
// --- Globals:
-static PyObject* GetDescriptor(CMessage* self, PyObject* name) {
- PyObject* descriptors =
- PyDict_GetItem(Py_TYPE(self)->tp_dict, k__descriptors);
- if (descriptors == NULL) {
- PyErr_SetString(PyExc_TypeError, "No __descriptors");
+// Retrieve the C++ Descriptor of a message class.
+// On error, returns NULL with an exception set.
+static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
+ ScopedPyObjectPtr descriptor(PyObject_GetAttr(
+ reinterpret_cast<PyObject*>(cls), kDESCRIPTOR));
+ if (descriptor == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
+ return NULL;
+ }
+ ScopedPyObjectPtr cdescriptor(PyObject_GetAttr(descriptor, k_cdescriptor));
+ if (cdescriptor == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Unregistered message.");
+ return NULL;
+ }
+ if (!PyObject_TypeCheck(cdescriptor, &CMessageDescriptor_Type)) {
+ PyErr_SetString(PyExc_TypeError, "Not a CMessageDescriptor");
return NULL;
}
+ return reinterpret_cast<CMessageDescriptor*>(cdescriptor.get())->descriptor;
+}
- return PyDict_GetItem(descriptors, name);
+// Retrieve a C++ FieldDescriptor for a message attribute.
+// The C++ message must be valid.
+// TODO(amauryfa): This function should stay internal, because exception
+// handling is not consistent.
+static const google::protobuf::FieldDescriptor* GetFieldDescriptor(
+ CMessage* self, PyObject* name) {
+ const google::protobuf::Descriptor *message_descriptor = self->message->GetDescriptor();
+ const char* field_name = PyString_AsString(name);
+ if (field_name == NULL) {
+ return NULL;
+ }
+ const google::protobuf::FieldDescriptor *field_descriptor =
+ message_descriptor->FindFieldByName(field_name);
+ if (field_descriptor == NULL) {
+ // Note: No exception is set!
+ return NULL;
+ }
+ return field_descriptor;
}
-static const google::protobuf::Message* CreateMessage(const char* message_type) {
- string message_name(message_type);
- const google::protobuf::Descriptor* descriptor =
- GetDescriptorPool()->FindMessageTypeByName(message_name);
- if (descriptor == NULL) {
- PyErr_SetString(PyExc_TypeError, message_type);
+// Retrieve a C++ FieldDescriptor for an extension handle.
+const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
+ ScopedPyObjectPtr cdescriptor(
+ PyObject_GetAttrString(extension, "_cdescriptor"));
+ if (cdescriptor == NULL) {
+ PyErr_SetString(PyExc_KeyError, "Unregistered extension.");
+ return NULL;
+ }
+ if (!PyObject_TypeCheck(cdescriptor, &CFieldDescriptor_Type)) {
+ PyErr_SetString(PyExc_TypeError, "Not a CFieldDescriptor");
+ Py_DECREF(cdescriptor);
return NULL;
}
- return global_message_factory->GetPrototype(descriptor);
+ return reinterpret_cast<CFieldDescriptor*>(cdescriptor.get())->descriptor;
}
// If cmessage_list is not NULL, this function releases values into the
@@ -627,39 +676,8 @@ int InternalDeleteRepeatedField(
return 0;
}
-int InitAttributes(CMessage* self, PyObject* arg, PyObject* kwargs) {
- ScopedPyObjectPtr descriptor;
- if (arg == NULL) {
- descriptor.reset(
- PyObject_GetAttr(reinterpret_cast<PyObject*>(self), kDESCRIPTOR));
- if (descriptor == NULL) {
- return NULL;
- }
- } else {
- descriptor.reset(arg);
- descriptor.inc();
- }
- ScopedPyObjectPtr is_extendable(PyObject_GetAttr(descriptor, kis_extendable));
- if (is_extendable == NULL) {
- return NULL;
- }
- int retcode = PyObject_IsTrue(is_extendable);
- if (retcode == -1) {
- return NULL;
- }
- if (retcode) {
- PyObject* py_extension_dict = PyObject_CallObject(
- reinterpret_cast<PyObject*>(&ExtensionDict_Type), NULL);
- if (py_extension_dict == NULL) {
- return NULL;
- }
- ExtensionDict* extension_dict = reinterpret_cast<ExtensionDict*>(
- py_extension_dict);
- extension_dict->parent = self;
- extension_dict->message = self->message;
- self->extensions = extension_dict;
- }
-
+// Initializes fields of a message. Used in constructors.
+int InitAttributes(CMessage* self, PyObject* kwargs) {
if (kwargs == NULL) {
return 0;
}
@@ -672,14 +690,12 @@ int InitAttributes(CMessage* self, PyObject* arg, PyObject* kwargs) {
PyErr_SetString(PyExc_ValueError, "Field name must be a string");
return -1;
}
- PyObject* py_cdescriptor = GetDescriptor(self, name);
- if (py_cdescriptor == NULL) {
+ const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
+ if (descriptor == NULL) {
PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.",
PyString_AsString(name));
return -1;
}
- const google::protobuf::FieldDescriptor* descriptor =
- reinterpret_cast<CFieldDescriptor*>(py_cdescriptor)->descriptor;
if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
ScopedPyObjectPtr container(GetAttr(self, name));
if (container == NULL) {
@@ -719,15 +735,19 @@ int InitAttributes(CMessage* self, PyObject* arg, PyObject* kwargs) {
return 0;
}
-static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
- CMessage* self = reinterpret_cast<CMessage*>(type->tp_alloc(type, 0));
+// Allocates an incomplete Python Message: the caller must fill self->message,
+// self->owner and eventually self->parent.
+CMessage* NewEmptyMessage(PyObject* type,
+ const google::protobuf::Descriptor *descriptor) {
+ CMessage* self = reinterpret_cast<CMessage*>(
+ PyType_GenericAlloc(reinterpret_cast<PyTypeObject*>(type), 0));
if (self == NULL) {
return NULL;
}
self->message = NULL;
self->parent = NULL;
- self->parent_field = NULL;
+ self->parent_field_descriptor = NULL;
self->read_only = false;
self->extensions = NULL;
@@ -735,43 +755,58 @@ static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
if (self->composite_fields == NULL) {
return NULL;
}
- return reinterpret_cast<PyObject*>(self);
-}
-
-PyObject* NewEmpty(PyObject* type) {
- return New(reinterpret_cast<PyTypeObject*>(type), NULL, NULL);
-}
-static int Init(CMessage* self, PyObject* args, PyObject* kwargs) {
- if (kwargs == NULL) {
- // TODO(anuraag): Set error
- return -1;
+ // If there are extension_ranges, the message is "extendable". Allocate a
+ // dictionary to store the extension fields.
+ if (descriptor->extension_range_count() > 0) {
+ // TODO(amauryfa): Delay the construction of this dict until extensions are
+ // really used on the object.
+ ExtensionDict* extension_dict = extension_dict::NewExtensionDict(self);
+ if (extension_dict == NULL) {
+ return NULL;
+ }
+ self->extensions = extension_dict;
}
- PyObject* descriptor = PyTuple_GetItem(args, 0);
- if (descriptor == NULL || PyTuple_Size(args) != 1) {
- PyErr_SetString(PyExc_ValueError, "args must contain one arg: descriptor");
- return -1;
- }
+ return self;
+}
- ScopedPyObjectPtr py_message_type(PyObject_GetAttr(descriptor, kfull_name));
- if (py_message_type == NULL) {
- return -1;
+// The __new__ method of Message classes.
+// Creates a new C++ message and takes ownership.
+static PyObject* New(PyTypeObject* type,
+ PyObject* unused_args, PyObject* unused_kwargs) {
+ // Retrieve the message descriptor and the default instance (=prototype).
+ const google::protobuf::Descriptor* message_descriptor = GetMessageDescriptor(type);
+ if (message_descriptor == NULL) {
+ return NULL;
}
-
- const char* message_type = PyString_AsString(py_message_type.get());
- const google::protobuf::Message* message = CreateMessage(message_type);
- if (message == NULL) {
- return -1;
+ const google::protobuf::Message* default_message =
+ global_message_factory->GetPrototype(message_descriptor);
+ if (default_message == NULL) {
+ PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
+ return NULL;
}
- self->message = message->New();
+ CMessage* self = NewEmptyMessage(reinterpret_cast<PyObject*>(type),
+ message_descriptor);
+ if (self == NULL) {
+ return NULL;
+ }
+ self->message = default_message->New();
self->owner.reset(self->message);
- if (InitAttributes(self, descriptor, kwargs) < 0) {
+ return reinterpret_cast<PyObject*>(self);
+}
+
+// The __init__ method of Message classes.
+// It initializes fields from keywords passed to the constructor.
+static int Init(CMessage* self, PyObject* args, PyObject* kwargs) {
+ if (PyTuple_Size(args) != 0) {
+ PyErr_SetString(PyExc_TypeError, "No positional arguments allowed");
return -1;
}
- return 0;
+
+ return InitAttributes(self, kwargs);
}
// ---------------------------------------------------------------------
@@ -853,9 +888,7 @@ PyObject* IsInitialized(CMessage* self, PyObject* args) {
PyObject* HasFieldByDescriptor(
CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) {
google::protobuf::Message* message = self->message;
- if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
- PyErr_SetString(PyExc_KeyError,
- "Field does not belong to message!");
+ if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
return NULL;
}
if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
@@ -1048,7 +1081,7 @@ int ReleaseSubMessage(google::protobuf::Message* message,
child_cmessage->message = released_message.get();
child_cmessage->owner.swap(released_message);
child_cmessage->parent = NULL;
- child_cmessage->parent_field = NULL;
+ child_cmessage->parent_field_descriptor = NULL;
child_cmessage->read_only = false;
return ForEachCompositeField(child_cmessage,
SetOwnerVisitor(child_cmessage->owner));
@@ -1090,10 +1123,8 @@ int InternalReleaseFieldByDescriptor(
int InternalReleaseField(CMessage* self, PyObject* composite_field,
PyObject* name) {
- PyObject* cdescriptor = GetDescriptor(self, name);
- if (cdescriptor != NULL) {
- const google::protobuf::FieldDescriptor* descriptor =
- reinterpret_cast<CFieldDescriptor*>(cdescriptor)->descriptor;
+ const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
+ if (descriptor != NULL) {
return InternalReleaseFieldByDescriptor(
descriptor, composite_field, self->message);
}
@@ -1104,9 +1135,7 @@ int InternalReleaseField(CMessage* self, PyObject* composite_field,
PyObject* ClearFieldByDescriptor(
CMessage* self,
const google::protobuf::FieldDescriptor* descriptor) {
- if (!FIELD_BELONGS_TO_MESSAGE(descriptor, self->message)) {
- PyErr_SetString(PyExc_KeyError,
- "Field does not belong to message!");
+ if (!CheckFieldBelongsToMessage(descriptor, self->message)) {
return NULL;
}
AssureWritable(self);
@@ -1177,15 +1206,10 @@ PyObject* Clear(CMessage* self) {
// fields have been released.
if (self->extensions != NULL) {
Py_CLEAR(self->extensions);
- PyObject* py_extension_dict = PyObject_CallObject(
- reinterpret_cast<PyObject*>(&ExtensionDict_Type), NULL);
- if (py_extension_dict == NULL) {
+ ExtensionDict* extension_dict = extension_dict::NewExtensionDict(self);
+ if (extension_dict == NULL) {
return NULL;
}
- ExtensionDict* extension_dict = reinterpret_cast<ExtensionDict*>(
- py_extension_dict);
- extension_dict->parent = self;
- extension_dict->message = self->message;
self->extensions = extension_dict;
}
PyDict_Clear(self->composite_fields);
@@ -1196,8 +1220,8 @@ PyObject* Clear(CMessage* self) {
// ---------------------------------------------------------------------
static string GetMessageName(CMessage* self) {
- if (self->parent_field != NULL) {
- return self->parent_field->descriptor->full_name();
+ if (self->parent_field_descriptor != NULL) {
+ return self->parent_field_descriptor->full_name();
} else {
return self->message->GetDescriptor()->full_name();
}
@@ -1219,7 +1243,7 @@ static PyObject* SerializeToString(CMessage* self, PyObject* args) {
return NULL;
}
PyErr_Format(EncodeError_class, "Message %s is missing required fields: %s",
- GetMessageName(self).c_str(), PyString_AsString(joined.get()));
+ GetMessageName(self).c_str(), PyString_AsString(joined));
return NULL;
}
int size = self->message->ByteSize();
@@ -1361,7 +1385,7 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
AssureWritable(self);
google::protobuf::io::CodedInputStream input(
reinterpret_cast<const uint8*>(data), data_length);
- input.SetExtensionRegistry(GetDescriptorPool(), global_message_factory);
+ input.SetExtensionRegistry(descriptor_pool->pool, global_message_factory);
bool success = self->message->MergePartialFromCodedStream(&input);
if (success) {
return PyInt_FromLong(input.CurrentPosition());
@@ -1421,15 +1445,11 @@ static PyObject* RegisterExtension(PyObject* cls,
return NULL;
}
- CFieldDescriptor* cdescriptor =
- extension_dict::InternalGetCDescriptorFromExtension(extension_handle);
- ScopedPyObjectPtr py_cdescriptor(reinterpret_cast<PyObject*>(cdescriptor));
- if (cdescriptor == NULL) {
+ const google::protobuf::FieldDescriptor* descriptor =
+ GetExtensionDescriptor(extension_handle);
+ if (descriptor == NULL) {
return NULL;
}
- Py_INCREF(extension_handle);
- cdescriptor->descriptor_field = extension_handle;
- const google::protobuf::FieldDescriptor* descriptor = cdescriptor->descriptor;
// Check if it's a message set
if (descriptor->is_extension() &&
descriptor->containing_type()->options().message_set_wire_format() &&
@@ -1608,8 +1628,14 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
}
if (opid == Py_EQ || opid == Py_NE) {
ScopedPyObjectPtr self_fields(ListFields(self));
+ if (!self_fields) {
+ return NULL;
+ }
ScopedPyObjectPtr other_fields(ListFields(
reinterpret_cast<CMessage*>(other)));
+ if (!other_fields) {
+ return NULL;
+ }
return PyObject_RichCompare(self_fields, other_fields, opid);
} else {
Py_INCREF(Py_NotImplemented);
@@ -1623,9 +1649,7 @@ PyObject* InternalGetScalar(
google::protobuf::Message* message = self->message;
const google::protobuf::Reflection* reflection = message->GetReflection();
- if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
- PyErr_SetString(
- PyExc_KeyError, "Field does not belong to message!");
+ if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
return NULL;
}
@@ -1701,43 +1725,31 @@ PyObject* InternalGetScalar(
return result;
}
-PyObject* InternalGetSubMessage(CMessage* self,
- CFieldDescriptor* cfield_descriptor) {
- PyObject* field = cfield_descriptor->descriptor_field;
- ScopedPyObjectPtr message_type(PyObject_GetAttr(field, kmessage_type));
- if (message_type == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr concrete_class(
- PyObject_GetAttr(message_type, k_concrete_class));
- if (concrete_class == NULL) {
+PyObject* InternalGetSubMessage(
+ CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) {
+ const google::protobuf::Reflection* reflection = self->message->GetReflection();
+ const google::protobuf::Message& sub_message = reflection->GetMessage(
+ *self->message, field_descriptor, global_message_factory);
+
+ PyObject *message_class = cdescriptor_pool::GetMessageClass(
+ descriptor_pool, field_descriptor->message_type());
+ if (message_class == NULL) {
return NULL;
}
- PyObject* py_cmsg = cmessage::NewEmpty(concrete_class);
- if (py_cmsg == NULL) {
+
+ CMessage* cmsg = cmessage::NewEmptyMessage(message_class,
+ sub_message.GetDescriptor());
+ if (cmsg == NULL) {
return NULL;
}
- if (!PyObject_TypeCheck(py_cmsg, &CMessage_Type)) {
- PyErr_SetString(PyExc_TypeError, "Not a CMessage!");
- }
- CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
- const google::protobuf::FieldDescriptor* field_descriptor =
- cfield_descriptor->descriptor;
- const google::protobuf::Reflection* reflection = self->message->GetReflection();
- const google::protobuf::Message& sub_message = reflection->GetMessage(
- *self->message, field_descriptor, global_message_factory);
cmsg->owner = self->owner;
cmsg->parent = self;
- cmsg->parent_field = cfield_descriptor;
+ cmsg->parent_field_descriptor = field_descriptor;
cmsg->read_only = !reflection->HasField(*self->message, field_descriptor);
cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
- if (InitAttributes(cmsg, NULL, NULL) < 0) {
- Py_DECREF(py_cmsg);
- return NULL;
- }
- return py_cmsg;
+ return reinterpret_cast<PyObject*>(cmsg);
}
int InternalSetScalar(
@@ -1747,9 +1759,7 @@ int InternalSetScalar(
google::protobuf::Message* message = self->message;
const google::protobuf::Reflection* reflection = message->GetReflection();
- if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
- PyErr_SetString(
- PyExc_KeyError, "Field does not belong to message!");
+ if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
return -1;
}
@@ -1838,25 +1848,35 @@ PyObject* FromString(PyTypeObject* cls, PyObject* serialized) {
return NULL;
}
- if (InitAttributes(cmsg, NULL, NULL) < 0) {
- Py_DECREF(py_cmsg);
- return NULL;
- }
return py_cmsg;
}
+
+// Finalize the creation of the Message class.
+// Called from its metaclass: GeneratedProtocolMessageType.__init__().
static PyObject* AddDescriptors(PyTypeObject* cls,
PyObject* descriptor) {
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- k_extensions_by_name, PyDict_New()) < 0) {
- return NULL;
- }
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- k_extensions_by_number, PyDict_New()) < 0) {
+ const google::protobuf::Descriptor* message_descriptor =
+ cdescriptor_pool::RegisterMessageClass(
+ descriptor_pool, reinterpret_cast<PyObject*>(cls), descriptor);
+ if (message_descriptor == NULL) {
return NULL;
}
- ScopedPyObjectPtr field_descriptors(PyDict_New());
+ // If there are extension_ranges, the message is "extendable", and extension
+ // classes will register themselves in this class.
+ if (message_descriptor->extension_range_count() > 0) {
+ ScopedPyObjectPtr by_name(PyDict_New());
+ if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
+ k_extensions_by_name, by_name) < 0) {
+ return NULL;
+ }
+ ScopedPyObjectPtr by_number(PyDict_New());
+ if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
+ k_extensions_by_number, by_number) < 0) {
+ return NULL;
+ }
+ }
ScopedPyObjectPtr fields(PyObject_GetAttrString(descriptor, "fields"));
if (fields == NULL) {
@@ -1878,19 +1898,14 @@ static PyObject* AddDescriptors(PyTypeObject* cls,
return NULL;
}
- PyObject* field_descriptor =
- cdescriptor_pool::FindFieldByName(descriptor_pool, full_field_name);
+ ScopedPyObjectPtr field_descriptor(
+ cdescriptor_pool::FindFieldByName(descriptor_pool, full_field_name));
if (field_descriptor == NULL) {
PyErr_SetString(PyExc_TypeError, "Couldn't find field");
return NULL;
}
- Py_INCREF(field);
CFieldDescriptor* cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(
- field_descriptor);
- cfield_descriptor->descriptor_field = field;
- if (PyDict_SetItem(field_descriptors, field_name, field_descriptor) < 0) {
- return NULL;
- }
+ field_descriptor.get());
// The FieldDescriptor's name field might either be of type bytes or
// of type unicode, depending on whether the FieldDescriptor was
@@ -1919,8 +1934,6 @@ static PyObject* AddDescriptors(PyTypeObject* cls,
}
}
- PyDict_SetItem(cls->tp_dict, k__descriptors, field_descriptors);
-
// Enum Values
ScopedPyObjectPtr enum_types(PyObject_GetAttrString(descriptor,
"enum_types"));
@@ -1994,15 +2007,11 @@ static PyObject* AddDescriptors(PyTypeObject* cls,
extension_name, extension_field) == -1) {
return NULL;
}
- ScopedPyObjectPtr py_cfield_descriptor(
- PyObject_GetAttrString(extension_field, "_cdescriptor"));
- if (py_cfield_descriptor == NULL) {
+ const google::protobuf::FieldDescriptor* field_descriptor =
+ GetExtensionDescriptor(extension_field);
+ if (field_descriptor == NULL) {
return NULL;
}
- CFieldDescriptor* cfield_descriptor =
- reinterpret_cast<CFieldDescriptor*>(py_cfield_descriptor.get());
- Py_INCREF(extension_field);
- cfield_descriptor->descriptor_field = extension_field;
ScopedPyObjectPtr field_name_upcased(
PyObject_CallMethod(extension_name, "upper", NULL));
@@ -2015,13 +2024,12 @@ static PyObject* AddDescriptors(PyTypeObject* cls,
return NULL;
}
ScopedPyObjectPtr number(PyInt_FromLong(
- cfield_descriptor->descriptor->number()));
+ field_descriptor->number()));
if (number == NULL) {
return NULL;
}
if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- field_number_name, PyInt_FromLong(
- cfield_descriptor->descriptor->number())) == -1) {
+ field_number_name, number) == -1) {
return NULL;
}
}
@@ -2039,10 +2047,6 @@ PyObject* DeepCopy(CMessage* self, PyObject* arg) {
Py_DECREF(clone);
return NULL;
}
- if (InitAttributes(reinterpret_cast<CMessage*>(clone), NULL, NULL) < 0) {
- Py_DECREF(clone);
- return NULL;
- }
if (MergeFrom(reinterpret_cast<CMessage*>(clone),
reinterpret_cast<PyObject*>(self)) == NULL) {
Py_DECREF(clone);
@@ -2202,48 +2206,30 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
return value;
}
- PyObject* descriptor = GetDescriptor(self, name);
- if (descriptor != NULL) {
- CFieldDescriptor* cdescriptor =
- reinterpret_cast<CFieldDescriptor*>(descriptor);
- const google::protobuf::FieldDescriptor* field_descriptor = cdescriptor->descriptor;
+ const google::protobuf::FieldDescriptor* field_descriptor = GetFieldDescriptor(
+ self, name);
+ if (field_descriptor != NULL) {
if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
if (field_descriptor->cpp_type() ==
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
- PyObject* py_container = PyObject_CallObject(
- reinterpret_cast<PyObject*>(&RepeatedCompositeContainer_Type),
- NULL);
- if (py_container == NULL) {
+ PyObject *message_class = cdescriptor_pool::GetMessageClass(
+ descriptor_pool, field_descriptor->message_type());
+ if (message_class == NULL) {
return NULL;
}
- RepeatedCompositeContainer* container =
- reinterpret_cast<RepeatedCompositeContainer*>(py_container);
- PyObject* field = cdescriptor->descriptor_field;
- PyObject* message_type = PyObject_GetAttr(field, kmessage_type);
- if (message_type == NULL) {
- return NULL;
- }
- PyObject* concrete_class =
- PyObject_GetAttr(message_type, k_concrete_class);
- if (concrete_class == NULL) {
+ PyObject* py_container = repeated_composite_container::NewContainer(
+ self, field_descriptor, message_class);
+ if (py_container == NULL) {
return NULL;
}
- container->parent = self;
- container->parent_field = cdescriptor;
- container->message = self->message;
- container->owner = self->owner;
- container->subclass_init = concrete_class;
- Py_DECREF(message_type);
if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) {
Py_DECREF(py_container);
return NULL;
}
return py_container;
} else {
- ScopedPyObjectPtr init_args(PyTuple_Pack(2, self, cdescriptor));
- PyObject* py_container = PyObject_CallObject(
- reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type),
- init_args);
+ PyObject* py_container = repeated_scalar_container::NewContainer(
+ self, field_descriptor);
if (py_container == NULL) {
return NULL;
}
@@ -2256,7 +2242,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
} else {
if (field_descriptor->cpp_type() ==
google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
- PyObject* sub_message = InternalGetSubMessage(self, cdescriptor);
+ PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
if (PyDict_SetItem(self->composite_fields, name, sub_message) < 0) {
Py_DECREF(sub_message);
return NULL;
@@ -2278,12 +2264,10 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
return -1;
}
- PyObject* descriptor = GetDescriptor(self, name);
- if (descriptor != NULL) {
+ const google::protobuf::FieldDescriptor* field_descriptor =
+ GetFieldDescriptor(self, name);
+ if (field_descriptor != NULL) {
AssureWritable(self);
- CFieldDescriptor* cdescriptor =
- reinterpret_cast<CFieldDescriptor*>(descriptor);
- const google::protobuf::FieldDescriptor* field_descriptor = cdescriptor->descriptor;
if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated "
"field \"%s\" in protocol message object.",
@@ -2401,22 +2385,18 @@ void InitGlobals() {
kuint64max_py = PyLong_FromUnsignedLongLong(kuint64max);
kDESCRIPTOR = PyString_FromString("DESCRIPTOR");
- k__descriptors = PyString_FromString("__descriptors");
+ k_cdescriptor = PyString_FromString("_cdescriptor");
kfull_name = PyString_FromString("full_name");
- kis_extendable = PyString_FromString("is_extendable");
kextensions_by_name = PyString_FromString("extensions_by_name");
k_extensions_by_name = PyString_FromString("_extensions_by_name");
k_extensions_by_number = PyString_FromString("_extensions_by_number");
- k_concrete_class = PyString_FromString("_concrete_class");
- kmessage_type = PyString_FromString("message_type");
kname = PyString_FromString("name");
kfields_by_name = PyString_FromString("fields_by_name");
- global_message_factory = new DynamicMessageFactory(GetDescriptorPool());
- global_message_factory->SetDelegateToGeneratedFactory(true);
+ descriptor_pool = cdescriptor_pool::NewDescriptorPool();
- descriptor_pool = reinterpret_cast<google::protobuf::python::CDescriptorPool*>(
- Python_NewCDescriptorPool(NULL, NULL));
+ global_message_factory = new DynamicMessageFactory(descriptor_pool->pool);
+ global_message_factory->SetDelegateToGeneratedFactory(true);
}
bool InitProto2MessageModule(PyObject *m) {
@@ -2427,19 +2407,32 @@ bool InitProto2MessageModule(PyObject *m) {
return false;
}
- // All three of these are actually set elsewhere, directly onto the child
- // protocol buffer message class, but set them here as well to document that
- // subclasses need to set these.
+ // DESCRIPTOR is set on each protocol buffer message class elsewhere, but set
+ // it here as well to document that subclasses need to set it.
PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, kDESCRIPTOR, Py_None);
- PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
- k_extensions_by_name, Py_None);
- PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
- k_extensions_by_number, Py_None);
+ // Subclasses with message extensions will override _extensions_by_name and
+ // _extensions_by_number with fresh mutable dictionaries in AddDescriptors.
+ // All other classes can share this same immutable mapping.
+ ScopedPyObjectPtr empty_dict(PyDict_New());
+ if (empty_dict == NULL) {
+ return false;
+ }
+ ScopedPyObjectPtr immutable_dict(PyDictProxy_New(empty_dict));
+ if (immutable_dict == NULL) {
+ return false;
+ }
+ if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
+ k_extensions_by_name, immutable_dict) < 0) {
+ return false;
+ }
+ if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
+ k_extensions_by_number, immutable_dict) < 0) {
+ return false;
+ }
PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(
&google::protobuf::python::CMessage_Type));
- google::protobuf::python::RepeatedScalarContainer_Type.tp_new = PyType_GenericNew;
google::protobuf::python::RepeatedScalarContainer_Type.tp_hash =
PyObject_HashNotImplemented;
if (PyType_Ready(&google::protobuf::python::RepeatedScalarContainer_Type) < 0) {
@@ -2450,7 +2443,6 @@ bool InitProto2MessageModule(PyObject *m) {
reinterpret_cast<PyObject*>(
&google::protobuf::python::RepeatedScalarContainer_Type));
- google::protobuf::python::RepeatedCompositeContainer_Type.tp_new = PyType_GenericNew;
google::protobuf::python::RepeatedCompositeContainer_Type.tp_hash =
PyObject_HashNotImplemented;
if (PyType_Ready(&google::protobuf::python::RepeatedCompositeContainer_Type) < 0) {
@@ -2462,7 +2454,6 @@ bool InitProto2MessageModule(PyObject *m) {
reinterpret_cast<PyObject*>(
&google::protobuf::python::RepeatedCompositeContainer_Type));
- google::protobuf::python::ExtensionDict_Type.tp_new = PyType_GenericNew;
google::protobuf::python::ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
if (PyType_Ready(&google::protobuf::python::ExtensionDict_Type) < 0) {
return false;
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 9f4978f4..73e5a7d3 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -49,12 +49,13 @@ namespace protobuf {
class Message;
class Reflection;
class FieldDescriptor;
+class Descriptor;
using internal::shared_ptr;
namespace python {
-struct CFieldDescriptor;
+struct PyDescriptorPool;
struct ExtensionDict;
typedef struct CMessage {
@@ -79,13 +80,11 @@ typedef struct CMessage {
// to use this pointer will result in a crash.
struct CMessage* parent;
- // Weak reference to the parent's descriptor that describes this submessage.
+ // Pointer to the parent's descriptor that describes this submessage.
// Used together with the parent's message when making a default message
// instance mutable.
- // TODO(anuraag): With a bit of work on the Python/C++ layer, it should be
- // possible to make this a direct pointer to a C++ FieldDescriptor, this would
- // be easier if this implementation replaces upstream.
- CFieldDescriptor* parent_field;
+ // The pointer is owned by the global DescriptorPool.
+ const google::protobuf::FieldDescriptor* parent_field_descriptor;
// Pointer to the C++ Message object for this CMessage. The
// CMessage does not own this pointer.
@@ -113,8 +112,11 @@ extern PyTypeObject CMessage_Type;
namespace cmessage {
-// Create a new empty message that can be populated by the parent.
-PyObject* NewEmpty(PyObject* type);
+// Internal function to create a new empty Message Python object, but with empty
+// pointers to the C++ objects.
+// The caller must fill self->message, self->owner and eventually self->parent.
+CMessage* NewEmptyMessage(PyObject* type,
+ const google::protobuf::Descriptor* descriptor);
// Release a submessage from its proto tree, making it a new top-level messgae.
// A new message will be created if this is a read-only default instance.
@@ -124,12 +126,16 @@ int ReleaseSubMessage(google::protobuf::Message* message,
const google::protobuf::FieldDescriptor* field_descriptor,
CMessage* child_cmessage);
+// Retrieves the C++ descriptor of a Python Extension descriptor.
+// On error, return NULL with an exception set.
+const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension);
+
// Initializes a new CMessage instance for a submessage. Only called once per
// submessage as the result is cached in composite_fields.
//
// Corresponds to reflection api method GetMessage.
-PyObject* InternalGetSubMessage(CMessage* self,
- CFieldDescriptor* cfield_descriptor);
+PyObject* InternalGetSubMessage(
+ CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor);
// Deletes a range of C++ submessages in a repeated field (following a
// removal in a RepeatedCompositeContainer).
@@ -190,10 +196,8 @@ PyObject* HasFieldByDescriptor(
// Corresponds to reflection api method HasField.
PyObject* HasField(CMessage* self, PyObject* arg);
-// Initializes constants/enum values on a message. This is called by
-// RepeatedCompositeContainer and ExtensionDict after calling the constructor.
-// TODO(anuraag): Make it always called from within the constructor since it can
-int InitAttributes(CMessage* self, PyObject* descriptor, PyObject* kwargs);
+// Initializes values of fields on a newly constructed message.
+int InitAttributes(CMessage* self, PyObject* kwargs);
PyObject* MergeFrom(CMessage* self, PyObject* arg);
@@ -218,12 +222,14 @@ int AssureWritable(CMessage* self);
} // namespace cmessage
+
+// Retrieve the global descriptor pool owned by the _message module.
+PyDescriptorPool* GetDescriptorPool();
+
+
/* 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)
@@ -296,6 +302,11 @@ bool CheckAndSetString(
PyObject* ToStringObject(
const google::protobuf::FieldDescriptor* descriptor, string value);
+// Check if the passed field descriptor belongs to the given message.
+// If not, return false and set a Python exception (a KeyError)
+bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor,
+ const google::protobuf::Message* message);
+
extern PyObject* PickleError_class;
} // namespace python
diff --git a/python/google/protobuf/pyext/proto2_api_test.proto b/python/google/protobuf/pyext/proto2_api_test.proto
index 72c31b1c..18aecfb7 100644
--- a/python/google/protobuf/pyext/proto2_api_test.proto
+++ b/python/google/protobuf/pyext/proto2_api_test.proto
@@ -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.
+syntax = "proto2";
+
import "google/protobuf/internal/cpp/proto1_api_test.proto";
package google.protobuf.python.internal;
diff --git a/python/google/protobuf/pyext/python.proto b/python/google/protobuf/pyext/python.proto
index d47d402c..cce645d7 100644
--- a/python/google/protobuf/pyext/python.proto
+++ b/python/google/protobuf/pyext/python.proto
@@ -33,6 +33,7 @@
// These message definitions are used to exercises known corner cases
// in the C++ implementation of the Python API.
+syntax = "proto2";
package google.protobuf.python.internal;
@@ -63,4 +64,5 @@ message TestAllExtensions {
extend TestAllExtensions {
optional TestAllTypes.NestedMessage optional_nested_message_extension = 1;
+ repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 2;
}
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 5c05b3d8..36fe86ae 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -65,14 +65,14 @@ namespace repeated_composite_container {
#define GOOGLE_CHECK_ATTACHED(self) \
do { \
GOOGLE_CHECK_NOTNULL((self)->message); \
- GOOGLE_CHECK_NOTNULL((self)->parent_field); \
+ GOOGLE_CHECK_NOTNULL((self)->parent_field_descriptor); \
} while (0);
#define GOOGLE_CHECK_RELEASED(self) \
do { \
GOOGLE_CHECK((self)->owner.get() == NULL); \
GOOGLE_CHECK((self)->message == NULL); \
- GOOGLE_CHECK((self)->parent_field == NULL); \
+ GOOGLE_CHECK((self)->parent_field_descriptor == NULL); \
GOOGLE_CHECK((self)->parent == NULL); \
} while (0);
@@ -122,7 +122,7 @@ static int InternalQuickSort(RepeatedCompositeContainer* self,
google::protobuf::Message* message = self->message;
const google::protobuf::Reflection* reflection = message->GetReflection();
- const google::protobuf::FieldDescriptor* descriptor = self->parent_field->descriptor;
+ const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor;
Py_ssize_t left;
Py_ssize_t right;
@@ -202,7 +202,7 @@ static Py_ssize_t Length(RepeatedCompositeContainer* self) {
google::protobuf::Message* message = self->message;
if (message != NULL) {
return message->GetReflection()->FieldSize(*message,
- self->parent_field->descriptor);
+ self->parent_field_descriptor);
} else {
// The container has been released (i.e. by a call to Clear() or
// ClearField() on the parent) and thus there's no message.
@@ -225,19 +225,19 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) {
const google::protobuf::Reflection* reflection = message->GetReflection();
for (Py_ssize_t i = child_length; i < message_length; ++i) {
const Message& sub_message = reflection->GetRepeatedMessage(
- *(self->message), self->parent_field->descriptor, i);
- ScopedPyObjectPtr py_cmsg(cmessage::NewEmpty(self->subclass_init));
- if (py_cmsg == NULL) {
+ *(self->message), self->parent_field_descriptor, i);
+ CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init,
+ sub_message.GetDescriptor());
+ ScopedPyObjectPtr py_cmsg(reinterpret_cast<PyObject*>(cmsg));
+ if (cmsg == NULL) {
return -1;
}
- CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg.get());
cmsg->owner = self->owner;
cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
cmsg->parent = self->parent;
- if (cmessage::InitAttributes(cmsg, NULL, NULL) < 0) {
+ if (PyList_Append(self->child_messages, py_cmsg) < 0) {
return -1;
}
- PyList_Append(self->child_messages, py_cmsg);
}
return 0;
}
@@ -258,23 +258,25 @@ static PyObject* AddToAttached(RepeatedCompositeContainer* self,
google::protobuf::Message* message = self->message;
google::protobuf::Message* sub_message =
message->GetReflection()->AddMessage(message,
- self->parent_field->descriptor);
- PyObject* py_cmsg = cmessage::NewEmpty(self->subclass_init);
- if (py_cmsg == NULL) {
+ self->parent_field_descriptor);
+ CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init,
+ sub_message->GetDescriptor());
+ if (cmsg == NULL)
return NULL;
- }
- CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
cmsg->owner = self->owner;
cmsg->message = sub_message;
cmsg->parent = self->parent;
- // cmessage::InitAttributes must be called after cmsg->message has
- // been set.
- if (cmessage::InitAttributes(cmsg, NULL, kwargs) < 0) {
+ if (cmessage::InitAttributes(cmsg, kwargs) < 0) {
+ Py_DECREF(cmsg);
+ return NULL;
+ }
+
+ PyObject* py_cmsg = reinterpret_cast<PyObject*>(cmsg);
+ if (PyList_Append(self->child_messages, py_cmsg) < 0) {
Py_DECREF(py_cmsg);
return NULL;
}
- PyList_Append(self->child_messages, py_cmsg);
return py_cmsg;
}
@@ -283,20 +285,16 @@ static PyObject* AddToReleased(RepeatedCompositeContainer* self,
PyObject* kwargs) {
GOOGLE_CHECK_RELEASED(self);
- // Create the CMessage
- PyObject* py_cmsg = PyObject_CallObject(self->subclass_init, NULL);
+ // Create a new Message detached from the rest.
+ PyObject* py_cmsg = PyEval_CallObjectWithKeywords(
+ self->subclass_init, NULL, kwargs);
if (py_cmsg == NULL)
return NULL;
- CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
- if (cmessage::InitAttributes(cmsg, NULL, kwargs) < 0) {
+
+ if (PyList_Append(self->child_messages, py_cmsg) < 0) {
Py_DECREF(py_cmsg);
return NULL;
}
-
- // The Message got created by the call to subclass_init above and
- // it set self->owner to the newly allocated message.
-
- PyList_Append(self->child_messages, py_cmsg);
return py_cmsg;
}
@@ -354,35 +352,9 @@ PyObject* Subscript(RepeatedCompositeContainer* self, PyObject* slice) {
if (UpdateChildMessages(self) < 0) {
return NULL;
}
- Py_ssize_t from;
- Py_ssize_t to;
- Py_ssize_t step;
- Py_ssize_t length = Length(self);
- Py_ssize_t slicelength;
- if (PySlice_Check(slice)) {
-#if PY_MAJOR_VERSION >= 3
- if (PySlice_GetIndicesEx(slice,
-#else
- if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
-#endif
- length, &from, &to, &step, &slicelength) == -1) {
- return NULL;
- }
- return PyList_GetSlice(self->child_messages, from, to);
- } else if (PyInt_Check(slice) || PyLong_Check(slice)) {
- from = to = PyLong_AsLong(slice);
- if (from < 0) {
- from = to = length + from;
- }
- PyObject* result = PyList_GetItem(self->child_messages, from);
- if (result == NULL) {
- return NULL;
- }
- Py_INCREF(result);
- return result;
- }
- PyErr_SetString(PyExc_TypeError, "index must be an integer or slice");
- return NULL;
+ // Just forward the call to the subscript-handling function of the
+ // list containing the child messages.
+ return PyObject_GetItem(self->child_messages, slice);
}
int AssignSubscript(RepeatedCompositeContainer* self,
@@ -399,7 +371,7 @@ int AssignSubscript(RepeatedCompositeContainer* self,
// Delete from the underlying Message, if any.
if (self->message != NULL) {
if (cmessage::InternalDeleteRepeatedField(self->message,
- self->parent_field->descriptor,
+ self->parent_field_descriptor,
slice,
self->child_messages) < 0) {
return -1;
@@ -512,7 +484,7 @@ static PyObject* SortAttached(RepeatedCompositeContainer* self,
if (reverse) {
google::protobuf::Message* message = self->message;
const google::protobuf::Reflection* reflection = message->GetReflection();
- const google::protobuf::FieldDescriptor* descriptor = self->parent_field->descriptor;
+ const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor;
// Reverse the Message array.
for (int i = 0; i < length / 2; ++i)
@@ -554,8 +526,9 @@ static PyObject* Sort(RepeatedCompositeContainer* self,
}
}
- if (UpdateChildMessages(self) < 0)
+ if (UpdateChildMessages(self) < 0) {
return NULL;
+ }
if (self->message == NULL) {
return SortReleased(self, args, kwds);
} else {
@@ -617,7 +590,7 @@ void ReleaseLastTo(const FieldDescriptor* field,
shared_ptr<Message> released_message(
ReleaseLast(field, cmessage->message->GetDescriptor(), message));
cmessage->parent = NULL;
- cmessage->parent_field = NULL;
+ cmessage->parent_field_descriptor = NULL;
cmessage->message = released_message.get();
cmessage->read_only = false;
cmessage::SetOwner(cmessage, released_message);
@@ -633,7 +606,7 @@ int Release(RepeatedCompositeContainer* self) {
}
Message* message = self->message;
- const FieldDescriptor* field = self->parent_field->descriptor;
+ const FieldDescriptor* field = self->parent_field_descriptor;
// The reflection API only lets us release the last message in a
// repeated field. Therefore we iterate through the children
@@ -648,7 +621,7 @@ int Release(RepeatedCompositeContainer* self) {
// Detach from containing message.
self->parent = NULL;
- self->parent_field = NULL;
+ self->parent_field_descriptor = NULL;
self->message = NULL;
self->owner.reset();
@@ -670,22 +643,40 @@ int SetOwner(RepeatedCompositeContainer* self,
return 0;
}
-static int Init(RepeatedCompositeContainer* self,
- PyObject* args,
- PyObject* kwargs) {
- self->message = NULL;
- self->parent = NULL;
- self->parent_field = NULL;
- self->subclass_init = NULL;
+// The private constructor of RepeatedCompositeContainer objects.
+PyObject *NewContainer(
+ CMessage* parent,
+ const google::protobuf::FieldDescriptor* parent_field_descriptor,
+ PyObject *concrete_class) {
+ if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+ return NULL;
+ }
+
+ RepeatedCompositeContainer* self =
+ reinterpret_cast<RepeatedCompositeContainer*>(
+ PyType_GenericAlloc(&RepeatedCompositeContainer_Type, 0));
+ if (self == NULL) {
+ return NULL;
+ }
+
+ self->message = parent->message;
+ self->parent = parent;
+ self->parent_field_descriptor = parent_field_descriptor;
+ self->owner = parent->owner;
+ Py_INCREF(concrete_class);
+ self->subclass_init = concrete_class;
self->child_messages = PyList_New(0);
- return 0;
+
+ return reinterpret_cast<PyObject*>(self);
}
static void Dealloc(RepeatedCompositeContainer* self) {
Py_CLEAR(self->child_messages);
+ Py_CLEAR(self->subclass_init);
// TODO(tibell): Do we need to call delete on these objects to make
// sure their destructors are called?
self->owner.reset();
+
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
@@ -755,7 +746,7 @@ PyTypeObject RepeatedCompositeContainer_Type = {
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
- (initproc)repeated_composite_container::Init, // tp_init
+ 0, // tp_init
};
} // namespace python
diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h
index 898ef5a7..a76a5d6a 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.h
+++ b/python/google/protobuf/pyext/repeated_composite_container.h
@@ -55,7 +55,6 @@ using internal::shared_ptr;
namespace python {
struct CMessage;
-struct CFieldDescriptor;
// A RepeatedCompositeContainer can be in one of two states: attached
// or released.
@@ -66,7 +65,7 @@ struct CFieldDescriptor;
// 'child_messages' are owner by the 'owner'.
//
// When in the released state 'message', 'owner', 'parent', and
-// 'parent_field' are NULL.
+// 'parent_field_descriptor' are NULL.
typedef struct RepeatedCompositeContainer {
PyObject_HEAD;
@@ -82,7 +81,8 @@ typedef struct RepeatedCompositeContainer {
CMessage* parent;
// A descriptor used to modify the underlying 'message'.
- CFieldDescriptor* parent_field;
+ // The pointer is owned by the global DescriptorPool.
+ const google::protobuf::FieldDescriptor* parent_field_descriptor;
// Pointer to the C++ Message that contains this container. The
// RepeatedCompositeContainer does not own this pointer.
@@ -102,6 +102,13 @@ extern PyTypeObject RepeatedCompositeContainer_Type;
namespace repeated_composite_container {
+// Builds a RepeatedCompositeContainer object, from a parent message and a
+// field descriptor.
+PyObject *NewContainer(
+ CMessage* parent,
+ const google::protobuf::FieldDescriptor* parent_field_descriptor,
+ PyObject *concrete_class);
+
// Returns the number of items in this repeated composite container.
static Py_ssize_t Length(RepeatedCompositeContainer* self);
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index e627d37d..49d23fd6 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -52,7 +52,7 @@
#error "Python 3.0 - 3.2 are not supported."
#else
#define PyString_AsString(ob) \
- (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AS_STRING(ob))
+ (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
#endif
#endif
@@ -67,7 +67,7 @@ namespace repeated_scalar_container {
static int InternalAssignRepeatedField(
RepeatedScalarContainer* self, PyObject* list) {
self->message->GetReflection()->ClearField(self->message,
- self->parent_field->descriptor);
+ self->parent_field_descriptor);
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
PyObject* value = PyList_GET_ITEM(list, i);
if (Append(self, value) == NULL) {
@@ -80,7 +80,7 @@ static int InternalAssignRepeatedField(
static Py_ssize_t Len(RepeatedScalarContainer* self) {
google::protobuf::Message* message = self->message;
return message->GetReflection()->FieldSize(*message,
- self->parent_field->descriptor);
+ self->parent_field_descriptor);
}
static int AssignItem(RepeatedScalarContainer* self,
@@ -89,12 +89,7 @@ static int AssignItem(RepeatedScalarContainer* self,
cmessage::AssureWritable(self->parent);
google::protobuf::Message* message = self->message;
const google::protobuf::FieldDescriptor* field_descriptor =
- self->parent_field->descriptor;
- if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
- PyErr_SetString(
- PyExc_KeyError, "Field does not belong to message!");
- return -1;
- }
+ self->parent_field_descriptor;
const google::protobuf::Reflection* reflection = message->GetReflection();
int field_size = reflection->FieldSize(*message, field_descriptor);
@@ -175,7 +170,7 @@ static int AssignItem(RepeatedScalarContainer* self,
ScopedPyObjectPtr s(PyObject_Str(arg));
if (s != NULL) {
PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
- PyString_AsString(s.get()));
+ PyString_AsString(s));
}
return -1;
}
@@ -193,7 +188,7 @@ static int AssignItem(RepeatedScalarContainer* self,
static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
google::protobuf::Message* message = self->message;
const google::protobuf::FieldDescriptor* field_descriptor =
- self->parent_field->descriptor;
+ self->parent_field_descriptor;
const google::protobuf::Reflection* reflection = message->GetReflection();
int field_size = reflection->FieldSize(*message, field_descriptor);
@@ -358,13 +353,7 @@ PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
cmessage::AssureWritable(self->parent);
google::protobuf::Message* message = self->message;
const google::protobuf::FieldDescriptor* field_descriptor =
- self->parent_field->descriptor;
-
- if (!FIELD_BELONGS_TO_MESSAGE(field_descriptor, message)) {
- PyErr_SetString(
- PyExc_KeyError, "Field does not belong to message!");
- return NULL;
- }
+ self->parent_field_descriptor;
const google::protobuf::Reflection* reflection = message->GetReflection();
switch (field_descriptor->cpp_type()) {
@@ -422,7 +411,7 @@ PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
ScopedPyObjectPtr s(PyObject_Str(item));
if (s != NULL) {
PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
- PyString_AsString(s.get()));
+ PyString_AsString(s));
}
return NULL;
}
@@ -451,7 +440,7 @@ static int AssSubscript(RepeatedScalarContainer* self,
cmessage::AssureWritable(self->parent);
google::protobuf::Message* message = self->message;
const google::protobuf::FieldDescriptor* field_descriptor =
- self->parent_field->descriptor;
+ self->parent_field_descriptor;
#if PY_MAJOR_VERSION < 3
if (PyInt_Check(slice)) {
@@ -638,47 +627,25 @@ static PyObject* Sort(RepeatedScalarContainer* self,
Py_RETURN_NONE;
}
-static int Init(RepeatedScalarContainer* self,
- PyObject* args,
- PyObject* kwargs) {
- PyObject* py_parent;
- PyObject* py_parent_field;
- if (!PyArg_UnpackTuple(args, "__init__()", 2, 2, &py_parent,
- &py_parent_field)) {
- return -1;
- }
-
- if (!PyObject_TypeCheck(py_parent, &CMessage_Type)) {
- PyErr_Format(PyExc_TypeError,
- "expect %s, but got %s",
- CMessage_Type.tp_name,
- Py_TYPE(py_parent)->tp_name);
- return -1;
+// The private constructor of RepeatedScalarContainer objects.
+PyObject *NewContainer(
+ CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) {
+ if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+ return NULL;
}
- if (!PyObject_TypeCheck(py_parent_field, &CFieldDescriptor_Type)) {
- PyErr_Format(PyExc_TypeError,
- "expect %s, but got %s",
- CFieldDescriptor_Type.tp_name,
- Py_TYPE(py_parent_field)->tp_name);
- return -1;
+ RepeatedScalarContainer* self = reinterpret_cast<RepeatedScalarContainer*>(
+ PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
+ if (self == NULL) {
+ return NULL;
}
- CMessage* cmessage = reinterpret_cast<CMessage*>(py_parent);
- CFieldDescriptor* cdescriptor = reinterpret_cast<CFieldDescriptor*>(
- py_parent_field);
-
- if (!FIELD_BELONGS_TO_MESSAGE(cdescriptor->descriptor, cmessage->message)) {
- PyErr_SetString(
- PyExc_KeyError, "Field does not belong to message!");
- return -1;
- }
+ self->message = parent->message;
+ self->parent = parent;
+ self->parent_field_descriptor = parent_field_descriptor;
+ self->owner = parent->owner;
- self->message = cmessage->message;
- self->parent = cmessage;
- self->parent_field = cdescriptor;
- self->owner = cmessage->owner;
- return 0;
+ return reinterpret_cast<PyObject*>(self);
}
// Initializes the underlying Message object of "to" so it becomes a new parent
@@ -699,10 +666,7 @@ static int InitializeAndCopyToParentContainer(
google::protobuf::Message* new_message = global_message_factory->GetPrototype(
from->message->GetDescriptor())->New();
to->parent = NULL;
- // TODO(anuraag): Document why it's OK to hang on to parent_field,
- // even though it's a weak reference. It ought to be enough to
- // hold on to the FieldDescriptor only.
- to->parent_field = from->parent_field;
+ to->parent_field_descriptor = from->parent_field_descriptor;
to->message = new_message;
to->owner.reset(new_message);
if (InternalAssignRepeatedField(to, values) < 0) {
@@ -716,23 +680,17 @@ int Release(RepeatedScalarContainer* self) {
}
PyObject* DeepCopy(RepeatedScalarContainer* self, PyObject* arg) {
- ScopedPyObjectPtr init_args(
- PyTuple_Pack(2, self->parent, self->parent_field));
- PyObject* clone = PyObject_CallObject(
- reinterpret_cast<PyObject*>(&RepeatedScalarContainer_Type), init_args);
+ RepeatedScalarContainer* clone = reinterpret_cast<RepeatedScalarContainer*>(
+ PyType_GenericAlloc(&RepeatedScalarContainer_Type, 0));
if (clone == NULL) {
return NULL;
}
- if (!PyObject_TypeCheck(clone, &RepeatedScalarContainer_Type)) {
- Py_DECREF(clone);
- return NULL;
- }
- if (InitializeAndCopyToParentContainer(
- self, reinterpret_cast<RepeatedScalarContainer*>(clone)) < 0) {
+
+ if (InitializeAndCopyToParentContainer(self, clone) < 0) {
Py_DECREF(clone);
return NULL;
}
- return clone;
+ return reinterpret_cast<PyObject*>(clone);
}
static void Dealloc(RepeatedScalarContainer* self) {
@@ -817,7 +775,7 @@ PyTypeObject RepeatedScalarContainer_Type = {
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
- (initproc)repeated_scalar_container::Init, // tp_init
+ 0, // tp_init
};
} // namespace python
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h
index 69d15d5c..513bfe48 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.h
+++ b/python/google/protobuf/pyext/repeated_scalar_container.h
@@ -41,6 +41,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
@@ -51,7 +52,6 @@ using internal::shared_ptr;
namespace python {
-struct CFieldDescriptor;
struct CMessage;
typedef struct RepeatedScalarContainer {
@@ -73,16 +73,22 @@ typedef struct RepeatedScalarContainer {
// modifying the container.
CMessage* parent;
- // Weak reference to the parent's descriptor that describes this
+ // Pointer to the parent's descriptor that describes this
// field. Used together with the parent's message when making a
// default message instance mutable.
- CFieldDescriptor* parent_field;
+ // The pointer is owned by the global DescriptorPool.
+ const google::protobuf::FieldDescriptor* parent_field_descriptor;
} RepeatedScalarContainer;
extern PyTypeObject RepeatedScalarContainer_Type;
namespace repeated_scalar_container {
+// Builds a RepeatedScalarContainer object, from a parent message and a
+// field descriptor.
+extern PyObject *NewContainer(
+ CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor);
+
// Appends the scalar 'item' to the end of the container 'self'.
//
// Returns None if successful; returns NULL and sets an exception if
diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
index 9f337c3c..fefebb6a 100644
--- a/python/google/protobuf/pyext/scoped_pyobject_ptr.h
+++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
@@ -33,6 +33,8 @@
#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
#define GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
+#include <google/protobuf/stubs/common.h>
+
#include <Python.h>
namespace google {
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index 2429fa59..b2f3d32c 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -112,15 +112,17 @@ def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False,
for element in value:
PrintField(field, element, out, indent, as_utf8, as_one_line,
pointy_brackets=pointy_brackets,
+ use_index_order=use_index_order,
float_format=float_format)
else:
PrintField(field, value, out, indent, as_utf8, as_one_line,
pointy_brackets=pointy_brackets,
+ use_index_order=use_index_order,
float_format=float_format)
def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False,
- pointy_brackets=False, float_format=None):
+ pointy_brackets=False, use_index_order=False, float_format=None):
"""Print a single field name/value pair. For repeated fields, the value
should be a single element."""
@@ -148,6 +150,7 @@ def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False,
PrintFieldValue(field, value, out, indent, as_utf8, as_one_line,
pointy_brackets=pointy_brackets,
+ use_index_order=use_index_order,
float_format=float_format)
if as_one_line:
out.write(' ')
@@ -157,6 +160,7 @@ def PrintField(field, value, out, indent=0, as_utf8=False, as_one_line=False,
def PrintFieldValue(field, value, out, indent=0, as_utf8=False,
as_one_line=False, pointy_brackets=False,
+ use_index_order=False,
float_format=None):
"""Print a single field value (not including name). For repeated fields,
the value should be a single element."""
@@ -173,12 +177,14 @@ def PrintFieldValue(field, value, out, indent=0, as_utf8=False,
out.write(' %s ' % openb)
PrintMessage(value, out, indent, as_utf8, as_one_line,
pointy_brackets=pointy_brackets,
+ use_index_order=use_index_order,
float_format=float_format)
out.write(closeb)
else:
out.write(' %s\n' % openb)
PrintMessage(value, out, indent + 2, as_utf8, as_one_line,
pointy_brackets=pointy_brackets,
+ use_index_order=use_index_order,
float_format=float_format)
out.write(' ' * indent + closeb)
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM:
diff --git a/python/setup.py b/python/setup.py
index 22a2c98f..7337260a 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -86,6 +86,8 @@ def GenerateUnittestProtos():
generate_proto("google/protobuf/internal/more_messages.proto")
generate_proto("google/protobuf/internal/factory_test1.proto")
generate_proto("google/protobuf/internal/factory_test2.proto")
+ generate_proto("google/protobuf/internal/import_test_package/inner.proto")
+ generate_proto("google/protobuf/internal/import_test_package/outer.proto")
generate_proto("google/protobuf/pyext/python.proto")
def MakeTestSuite():
@@ -185,6 +187,7 @@ if __name__ == '__main__':
'google.protobuf.descriptor_database',
'google.protobuf.descriptor_pool',
'google.protobuf.message_factory',
+ 'google.protobuf.proto_builder',
'google.protobuf.pyext.cpp_message',
'google.protobuf.reflection',
'google.protobuf.service',
diff --git a/src/Makefile.am b/src/Makefile.am
index 2e22b020..a111e14c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,6 +38,7 @@ MAINTAINERCLEANFILES = \
Makefile.in
nobase_include_HEADERS = \
+ google/protobuf/stubs/atomic_sequence_num.h \
google/protobuf/stubs/atomicops.h \
google/protobuf/stubs/atomicops_internals_arm64_gcc.h \
google/protobuf/stubs/atomicops_internals_arm_gcc.h \
@@ -51,24 +52,32 @@ nobase_include_HEADERS = \
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/casts.h \
+ google/protobuf/stubs/singleton.h \
google/protobuf/stubs/common.h \
- google/protobuf/stubs/platform_macros.h \
+ google/protobuf/stubs/fastmem.h \
google/protobuf/stubs/once.h \
+ google/protobuf/stubs/platform_macros.h \
google/protobuf/stubs/stl_util.h \
google/protobuf/stubs/template_util.h \
google/protobuf/stubs/type_traits.h \
+ google/protobuf/arena.h \
+ google/protobuf/arenastring.h \
+ google/protobuf/descriptor_database.h \
google/protobuf/descriptor.h \
google/protobuf/descriptor.pb.h \
- google/protobuf/descriptor_database.h \
google/protobuf/dynamic_message.h \
google/protobuf/extension_set.h \
google/protobuf/generated_enum_reflection.h \
- google/protobuf/generated_message_util.h \
google/protobuf/generated_message_reflection.h \
+ google/protobuf/generated_message_util.h \
google/protobuf/message.h \
google/protobuf/message_lite.h \
+ google/protobuf/metadata.h \
+ google/protobuf/reflection.h \
google/protobuf/reflection_ops.h \
google/protobuf/repeated_field.h \
+ google/protobuf/repeated_field_reflection.h \
google/protobuf/service.h \
google/protobuf/text_format.h \
google/protobuf/unknown_field_set.h \
@@ -107,6 +116,8 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/shared_ptr.h \
google/protobuf/stubs/stringprintf.cc \
google/protobuf/stubs/stringprintf.h \
+ google/protobuf/arena.cc \
+ google/protobuf/arenastring.cc \
google/protobuf/extension_set.cc \
google/protobuf/generated_message_util.cc \
google/protobuf/message_lite.cc \
@@ -127,12 +138,13 @@ libprotobuf_la_SOURCES = \
google/protobuf/stubs/substitute.h \
google/protobuf/stubs/structurally_valid.cc \
google/protobuf/descriptor.cc \
- google/protobuf/descriptor.pb.cc \
google/protobuf/descriptor_database.cc \
+ google/protobuf/descriptor.pb.cc \
google/protobuf/dynamic_message.cc \
google/protobuf/extension_set_heavy.cc \
google/protobuf/generated_message_reflection.cc \
google/protobuf/message.cc \
+ google/protobuf/reflection_internal.h \
google/protobuf/reflection_ops.cc \
google/protobuf/service.cc \
google/protobuf/text_format.cc \
@@ -184,9 +196,9 @@ libprotoc_la_SOURCES = \
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 \
google/protobuf/compiler/java/java_enum_field.h \
+ google/protobuf/compiler/java/java_enum.h \
google/protobuf/compiler/java/java_extension.cc \
google/protobuf/compiler/java/java_extension.h \
google/protobuf/compiler/java/java_field.cc \
@@ -200,10 +212,12 @@ libprotoc_la_SOURCES = \
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_map_field.cc \
+ google/protobuf/compiler/java/java_map_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_message.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 \
@@ -226,18 +240,25 @@ protoc_SOURCES = google/protobuf/compiler/main.cc
protoc_inputs = \
google/protobuf/unittest.proto \
- google/protobuf/unittest_empty.proto \
- google/protobuf/unittest_import.proto \
- google/protobuf/unittest_import_public.proto \
- google/protobuf/unittest_mset.proto \
- google/protobuf/unittest_optimize_for.proto \
- google/protobuf/unittest_embed_optimize_for.proto \
+ google/protobuf/unittest_arena.proto \
google/protobuf/unittest_custom_options.proto \
- google/protobuf/unittest_lite.proto \
+ google/protobuf/unittest_drop_unknown_fields.proto \
+ google/protobuf/unittest_embed_optimize_for.proto \
+ google/protobuf/unittest_empty.proto \
google/protobuf/unittest_import_lite.proto \
+ google/protobuf/unittest_import.proto \
google/protobuf/unittest_import_public_lite.proto \
+ google/protobuf/unittest_import_public.proto \
google/protobuf/unittest_lite_imports_nonlite.proto \
+ google/protobuf/unittest_lite.proto \
+ google/protobuf/unittest_mset.proto \
+ google/protobuf/unittest_no_arena_import.proto \
+ google/protobuf/unittest_no_arena.proto \
+ google/protobuf/unittest_no_field_presence.proto \
google/protobuf/unittest_no_generic_services.proto \
+ google/protobuf/unittest_optimize_for.proto \
+ google/protobuf/unittest_preserve_unknown_enum.proto \
+ google/protobuf/unittest_proto3_arena.proto \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
EXTRA_DIST = \
@@ -273,24 +294,38 @@ protoc_outputs = \
$(protoc_lite_outputs) \
google/protobuf/unittest.pb.cc \
google/protobuf/unittest.pb.h \
+ google/protobuf/unittest_arena.pb.cc \
+ google/protobuf/unittest_arena.pb.h \
+ google/protobuf/unittest_custom_options.pb.cc \
+ google/protobuf/unittest_custom_options.pb.h \
+ google/protobuf/unittest_drop_unknown_fields.pb.cc \
+ google/protobuf/unittest_drop_unknown_fields.pb.h \
+ google/protobuf/unittest_embed_optimize_for.pb.cc \
+ google/protobuf/unittest_embed_optimize_for.pb.h \
google/protobuf/unittest_empty.pb.cc \
google/protobuf/unittest_empty.pb.h \
google/protobuf/unittest_import.pb.cc \
google/protobuf/unittest_import.pb.h \
google/protobuf/unittest_import_public.pb.cc \
google/protobuf/unittest_import_public.pb.h \
- google/protobuf/unittest_mset.pb.cc \
- google/protobuf/unittest_mset.pb.h \
- google/protobuf/unittest_optimize_for.pb.cc \
- google/protobuf/unittest_optimize_for.pb.h \
- google/protobuf/unittest_embed_optimize_for.pb.cc \
- google/protobuf/unittest_embed_optimize_for.pb.h \
- google/protobuf/unittest_custom_options.pb.cc \
- google/protobuf/unittest_custom_options.pb.h \
google/protobuf/unittest_lite_imports_nonlite.pb.cc \
google/protobuf/unittest_lite_imports_nonlite.pb.h \
+ google/protobuf/unittest_mset.pb.cc \
+ google/protobuf/unittest_mset.pb.h \
+ google/protobuf/unittest_no_arena.pb.cc \
+ google/protobuf/unittest_no_arena.pb.h \
+ google/protobuf/unittest_no_arena_import.pb.cc \
+ google/protobuf/unittest_no_arena_import.pb.h \
+ google/protobuf/unittest_no_field_presence.pb.cc \
+ google/protobuf/unittest_no_field_presence.pb.h \
google/protobuf/unittest_no_generic_services.pb.cc \
google/protobuf/unittest_no_generic_services.pb.h \
+ google/protobuf/unittest_optimize_for.pb.cc \
+ google/protobuf/unittest_optimize_for.pb.h \
+ google/protobuf/unittest_preserve_unknown_enum.pb.cc \
+ google/protobuf/unittest_preserve_unknown_enum.pb.h \
+ google/protobuf/unittest_proto3_arena.pb.cc \
+ google/protobuf/unittest_proto3_arena.pb.h \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
@@ -342,15 +377,21 @@ protobuf_test_SOURCES = \
google/protobuf/stubs/stringprintf_unittest.cc \
google/protobuf/stubs/template_util_unittest.cc \
google/protobuf/stubs/type_traits_unittest.cc \
+ google/protobuf/arenastring_unittest.cc \
+ google/protobuf/arena_unittest.cc \
google/protobuf/descriptor_database_unittest.cc \
google/protobuf/descriptor_unittest.cc \
+ google/protobuf/drop_unknown_fields_test.cc \
google/protobuf/dynamic_message_unittest.cc \
google/protobuf/extension_set_unittest.cc \
google/protobuf/generated_message_reflection_unittest.cc \
google/protobuf/message_unittest.cc \
+ google/protobuf/no_field_presence_test.cc \
+ google/protobuf/preserve_unknown_enum_test.cc \
+ google/protobuf/proto3_arena_unittest.cc \
google/protobuf/reflection_ops_unittest.cc \
- google/protobuf/repeated_field_unittest.cc \
google/protobuf/repeated_field_reflection_unittest.cc \
+ google/protobuf/repeated_field_unittest.cc \
google/protobuf/text_format_unittest.cc \
google/protobuf/unknown_field_set_unittest.cc \
google/protobuf/wire_format_unittest.cc \
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
new file mode 100644
index 00000000..59863986
--- /dev/null
+++ b/src/google/protobuf/arena.cc
@@ -0,0 +1,238 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/arena.h>
+
+namespace google {
+namespace protobuf {
+
+google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
+__thread Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
+
+void Arena::Init(const ArenaOptions& options) {
+ lifecycle_id_ = lifecycle_id_generator_.GetNext();
+ start_block_size_ = options.start_block_size;
+ max_block_size_ = options.max_block_size;
+ block_alloc = options.block_alloc;
+ block_dealloc = options.block_dealloc;
+ blocks_ = NULL;
+ hint_ = NULL;
+ owns_first_block_ = true;
+ cleanup_list_ = NULL;
+
+ if (options.initial_block != NULL && options.initial_block_size > 0) {
+ // Add first unowned block to list.
+ Block* first_block = reinterpret_cast<Block*>(options.initial_block);
+ first_block->size = options.initial_block_size;
+ first_block->pos = kHeaderSize;
+ first_block->next = NULL;
+ first_block->owner = &first_block->owner;
+ AddBlock(first_block);
+ owns_first_block_ = false;
+ }
+}
+
+uint64 Arena::Reset() {
+ CleanupList();
+ uint64 space_used = FreeBlocks();
+ // Invalidate any ThreadCaches pointing to any blocks we just destroyed.
+ lifecycle_id_ = lifecycle_id_generator_.GetNext();
+ return space_used;
+}
+
+Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
+ size_t start_block_size, size_t max_block_size) {
+ size_t size;
+ if (my_last_block != NULL) {
+ // Double the current block size, up to a limit.
+ size = 2 * (my_last_block->size);
+ if (size > max_block_size) size = max_block_size;
+ } else {
+ size = start_block_size;
+ }
+ if (n > size - kHeaderSize) {
+ // TODO(sanjay): Check if n + kHeaderSize would overflow
+ size = kHeaderSize + n;
+ }
+
+ Block* b = reinterpret_cast<Block*>(block_alloc(size));
+ b->pos = kHeaderSize + n;
+ b->size = size;
+ if (b->avail() == 0) {
+ // Do not attempt to reuse this block.
+ b->owner = NULL;
+ } else {
+ b->owner = me;
+ }
+ return b;
+}
+
+void Arena::AddBlock(Block* b) {
+ MutexLock l(&blocks_lock_);
+ b->next = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+ google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
+ if (b->avail() != 0) {
+ // Direct future allocations to this block.
+ google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
+ }
+}
+
+void Arena::AddListNode(void* elem, void (*cleanup)(void*)) {
+ Node* node = reinterpret_cast<Node*>(AllocateAligned(sizeof(Node)));
+ node->elem = elem;
+ node->cleanup = cleanup;
+ node->next = reinterpret_cast<Node*>(
+ google::protobuf::internal::NoBarrier_AtomicExchange(&cleanup_list_,
+ reinterpret_cast<google::protobuf::internal::AtomicWord>(node)));
+}
+
+void* Arena::AllocateAligned(size_t n) {
+ // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
+ n = (n + 7) & -8;
+
+ // If this thread already owns a block in this arena then try to use that.
+ // This fast path optimizes the case where multiple threads allocate from the
+ // same arena.
+ if (thread_cache_.last_lifecycle_id_seen == lifecycle_id_ &&
+ thread_cache_.last_block_used_ != NULL) {
+ if (thread_cache_.last_block_used_->avail() < n) {
+ return SlowAlloc(n);
+ }
+ return AllocFromBlock(thread_cache_.last_block_used_, n);
+ }
+
+ // Check whether we own the last accessed block on this arena.
+ // This fast path optimizes the case where a single thread uses multiple
+ // arenas.
+ void* me = &thread_cache_;
+ Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
+ if (!b || b->owner != me || b->avail() < n) {
+ // If the next block to allocate from is the first block, try to claim it
+ // for this thread.
+ if (!owns_first_block_ && b->next == NULL) {
+ MutexLock l(&blocks_lock_);
+ if (b->owner == &b->owner) {
+ b->owner = me;
+ SetThreadCacheBlock(b);
+ return AllocFromBlock(b, n);
+ }
+ }
+ return SlowAlloc(n);
+ }
+ return AllocFromBlock(b, n);
+}
+
+void* Arena::AllocFromBlock(Block* b, size_t n) {
+ size_t p = b->pos;
+ b->pos = p + n;
+ return reinterpret_cast<char*>(b) + p;
+}
+
+void* Arena::SlowAlloc(size_t n) {
+ void* me = &thread_cache_;
+ Block* b = FindBlock(me); // Find block owned by me.
+ // See if allocation fits in my latest block.
+ if (b != NULL && b->avail() >= n) {
+ SetThreadCacheBlock(b);
+ google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
+ return AllocFromBlock(b, n);
+ }
+ b = NewBlock(me, b, n, start_block_size_, max_block_size_);
+ AddBlock(b);
+ if (b->owner == me) { // If this block can be reused (see NewBlock()).
+ SetThreadCacheBlock(b);
+ }
+ return reinterpret_cast<char*>(b) + kHeaderSize;
+}
+
+uint64 Arena::SpaceUsed() const {
+ uint64 space_used = 0;
+ Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+ while (b != NULL) {
+ space_used += (b->size);
+ b = b->next;
+ }
+ return space_used;
+}
+
+
+uint64 Arena::FreeBlocks() {
+ uint64 space_used = 0;
+ Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+ Block* first_block = NULL;
+ while (b != NULL) {
+ space_used += (b->size);
+ Block* next = b->next;
+ if (next != NULL) {
+ block_dealloc(b, b->size);
+ } else {
+ if (owns_first_block_) {
+ block_dealloc(b, b->size);
+ } else {
+ // User passed in the first block, skip free'ing the memory.
+ first_block = b;
+ }
+ }
+ b = next;
+ }
+ blocks_ = 0;
+ hint_ = 0;
+ if (!owns_first_block_) {
+ // Make the first block that was passed in through ArenaOptions
+ // available for reuse.
+ first_block->pos = kHeaderSize;
+ first_block->owner = &first_block->owner;
+ AddBlock(first_block);
+ }
+ return space_used;
+}
+
+void Arena::CleanupList() {
+ Node* head =
+ reinterpret_cast<Node*>(google::protobuf::internal::NoBarrier_Load(&cleanup_list_));
+ while (head != NULL) {
+ head->cleanup(head->elem);
+ head = head->next;
+ }
+ cleanup_list_ = 0;
+}
+
+Arena::Block* Arena::FindBlock(void* me) {
+ // TODO(sanjay): We might want to keep a separate list with one
+ // entry per thread.
+ Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&blocks_));
+ while (b != NULL && b->owner != me) {
+ b = b->next;
+ }
+ return b;
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
new file mode 100644
index 00000000..519e3569
--- /dev/null
+++ b/src/google/protobuf/arena.h
@@ -0,0 +1,479 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header is logically internal, but is made public because it is used
+// from protocol-compiler-generated code, which may reside in other components.
+
+#ifndef GOOGLE_PROTOBUF_ARENA_H__
+#define GOOGLE_PROTOBUF_ARENA_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/atomic_sequence_num.h>
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/type_traits.h>
+
+namespace google {
+namespace protobuf {
+
+class Arena; // defined below
+class Message; // message.h
+
+namespace internal {
+class ArenaString; // arenastring.h
+class LazyField; // lazy_field.h
+
+template<typename Type>
+class GenericTypeHandler; // repeated_field.h
+
+// Templated cleanup methods.
+template<typename T> void arena_destruct_object(void* object) {
+ reinterpret_cast<T*>(object)->~T();
+}
+template<typename T> void arena_delete_object(void* object) {
+ delete reinterpret_cast<T*>(object);
+}
+inline void arena_free(void* object, size_t size) {
+ free(object);
+}
+
+} // namespace internal
+
+// ArenaOptions provides optional additional parameters to arena construction
+// that control its block-allocation behavior.
+struct ArenaOptions {
+ // This defines the size of the first block requested from the system malloc.
+ // Subsequent block sizes will increase in a geometric series up to a maximum.
+ size_t start_block_size;
+
+ // This defines the maximum block size requested from system malloc (unless an
+ // individual arena allocation request occurs with a size larger than this
+ // maximum). Requested block sizes increase up to this value, then remain
+ // here.
+ size_t max_block_size;
+
+ // An initial block of memory for the arena to use, or NULL for none. If
+ // provided, the block must live at least as long as the arena itself. The
+ // creator of the Arena retains ownership of the block after the Arena is
+ // destroyed.
+ char* initial_block;
+
+ // The size of the initial block, if provided.
+ size_t initial_block_size;
+
+ // A function pointer to an alloc method that returns memory blocks of size
+ // requested. By default, it contains a ptr to the malloc function.
+ void* (*block_alloc)(size_t);
+ // A function pointer to a dealloc method that takes ownership of the blocks
+ // from the arena. By default, it contains a ptr to a wrapper function that
+ // calls free.
+ void (*block_dealloc)(void*, size_t);
+
+ ArenaOptions()
+ : start_block_size(kDefaultStartBlockSize),
+ max_block_size(kDefaultMaxBlockSize),
+ initial_block(NULL),
+ initial_block_size(0),
+ block_alloc(&malloc),
+ block_dealloc(&internal::arena_free) {}
+
+ private:
+ // Constants define default starting block size and max block size for
+ // arena allocator behavior -- see descriptions above.
+ static const size_t kDefaultStartBlockSize = 256;
+ static const size_t kDefaultMaxBlockSize = 8192;
+};
+
+// Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
+// with new/delete, and improves performance by aggregating allocations into
+// larger blocks and freeing allocations all at once. Protocol messages are
+// allocated on an arena by using Arena::CreateMessage<T>(Arena*), below, and
+// are automatically freed when the arena is destroyed.
+//
+// This is a thread-safe implementation: multiple threads may allocate from the
+// arena concurrently. Destruction is not thread-safe and the destructing
+// thread must synchronize with users of the arena first.
+class LIBPROTOBUF_EXPORT Arena {
+ public:
+ // Arena constructor taking custom options. See ArenaOptions below for
+ // descriptions of the options available.
+ explicit Arena(const ArenaOptions& options) {
+ Init(options);
+ }
+
+ // Default constructor with sensible default options, tuned for average
+ // use-cases.
+ Arena() {
+ Init(ArenaOptions());
+ }
+
+ // Destructor deletes all owned heap allocated objects, and destructs objects
+ // that have non-trivial destructors, except for proto2 message objects whose
+ // destructors can be skipped. Also, frees all blocks except the initial block
+ // if it was passed in.
+ ~Arena() {
+ Reset();
+ }
+
+ // API to create proto2 message objects on the arena. If the arena passed in
+ // is NULL, then a heap allocated object is returned. Type T must be a message
+ // defined in a .proto file with cc_enable_arenas set to true, otherwise a
+ // compilation error will occur.
+ //
+ // RepeatedField and RepeatedPtrField may also be instantiated directly on an
+ // arena with this method: they act as "arena-capable message types" for the
+ // purposes of the Arena API.
+ template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* CreateMessage(::google::protobuf::Arena* arena) {
+ if (arena == NULL) {
+ return new T;
+ } else {
+ return arena->CreateMessageInternal<T>(static_cast<T*>(0));
+ }
+ }
+
+ // API to create any objects on the arena. Note that only the object will
+ // be created on the arena; the underlying ptrs (in case of a proto2 message)
+ // will be still heap allocated. Proto messages should usually be allocated
+ // with CreateMessage<T>() instead.
+ template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* Create(::google::protobuf::Arena* arena) {
+ if (arena == NULL) {
+ return new T();
+ } else {
+ return arena->CreateInternal<T>(
+ SkipDeleteList<T>(static_cast<T*>(0)));
+ }
+ }
+
+ // Version of the above with one constructor argument for the created object.
+ template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* Create(::google::protobuf::Arena* arena, const Arg& arg) {
+ if (arena == NULL) {
+ return new T(arg);
+ } else {
+ return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
+ arg);
+ }
+ }
+
+ // Version of the above with two constructor arguments for the created object.
+ template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* Create(::google::protobuf::Arena* arena, const Arg1& arg1, const Arg2& arg2) {
+ if (arena == NULL) {
+ return new T(arg1, arg2);
+ } else {
+ return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
+ arg1,
+ arg2);
+ }
+ }
+
+ // Create an array of object type T on the arena. Type T must have a trivial
+ // constructor, as it will not be invoked when created on the arena.
+ template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
+ if (arena == NULL) {
+ return new T[num_elements];
+ } else {
+ return static_cast<T*>(
+ arena->AllocateAligned(num_elements * sizeof(T)));
+ }
+ }
+
+ // Returns the total space used by the arena, which is the sums of the sizes
+ // of the underlying blocks. The total space used may not include the new
+ // blocks that are allocated by this arena from other threads concurrently
+ // with the call to this method.
+ uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE;
+
+ // Frees all storage allocated by this arena after calling destructors
+ // registered with OwnDestructor() and freeing objects registered with Own().
+ // Any objects allocated on this arena are unusable after this call. It also
+ // returns the total space used by the arena which is the sums of the sizes
+ // of the allocated blocks. This method is not thread-safe.
+ uint64 Reset() GOOGLE_ATTRIBUTE_NOINLINE;
+
+ // Adds |object| to a list of heap-allocated objects to be freed with |delete|
+ // when the arena is destroyed or reset.
+ template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
+ void Own(T* object) {
+ OwnInternal(object, google::protobuf::internal::is_convertible<T*, ::google::protobuf::Message*>());
+ }
+
+ // Adds |object| to a list of objects whose destructors will be manually
+ // called when the arena is destroyed or reset. This differs from Own() in
+ // that it does not free the underlying memory with |delete|; hence, it is
+ // normally only used for objects that are placement-newed into
+ // arena-allocated memory.
+ template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
+ void OwnDestructor(T* object) {
+ if (object != NULL) {
+ AddListNode(object, &internal::arena_destruct_object<T>);
+ }
+ }
+
+ // Adds a custom member function on an object to the list of destructors that
+ // will be manually called when the arena is destroyed or reset. This differs
+ // from OwnDestructor() in that any member function may be specified, not only
+ // the class destructor.
+ void OwnCustomDestructor(void* object, void (*destruct)(void*))
+ GOOGLE_ATTRIBUTE_NOINLINE {
+ AddListNode(object, destruct);
+ }
+
+ // Retrieves the arena associated with |value| if |value| is an arena-capable
+ // message, or NULL otherwise. This differs from value->GetArena() in that the
+ // latter is a virtual call, while this method is a templated call that
+ // resolves at compile-time.
+ template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static inline ::google::protobuf::Arena* GetArena(T* value) {
+ return GetArenaInternal(value, static_cast<T*>(0));
+ }
+
+ // Helper typetrait that indicates support for arenas in a type T at compile
+ // time. This is public only to allow construction of higher-level templated
+ // utilities. is_arena_constructable<T>::value is an instance of
+ // google::protobuf::internal::true_type if the message type T has arena support enabled, and
+ // google::protobuf::internal::false_type otherwise.
+ //
+ // This is inside Arena because only Arena has the friend relationships
+ // necessary to see the underlying generated code traits.
+ template<typename T>
+ struct is_arena_constructable {
+ template<typename U>
+ static char ArenaConstructable(
+ const typename U::InternalArenaConstructable_*);
+ template<typename U>
+ static double ArenaConstructable(...);
+
+ // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
+ typedef google::protobuf::internal::integral_constant<bool,
+ sizeof(ArenaConstructable<const T>(static_cast<const T*>(0))) ==
+ sizeof(char)> type;
+ static const type value;
+ };
+
+ private:
+ // Blocks are variable length malloc-ed objects. The following structure
+ // describes the common header for all blocks.
+ struct Block {
+ void* owner; // &ThreadCache of thread that owns this block, or
+ // &this->owner if not yet owned by a thread.
+ Block* next; // Next block in arena (may have different owner)
+ // ((char*) &block) + pos is next available byte. It is always
+ // aligned at a multiple of 8 bytes.
+ size_t pos;
+ size_t size; // total size of the block.
+ size_t avail() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { return size - pos; }
+ // data follows
+ };
+
+ void* (*block_alloc)(size_t); // Allocates a free block of a particular size.
+ void (*block_dealloc)(void*, size_t); // Deallocates the given block.
+
+ template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
+ friend class MockArena; // For unit-testing.
+ friend class internal::ArenaString; // For AllocateAligned.
+ friend class internal::LazyField; // For CreateMaybeMessage.
+
+ struct ThreadCache {
+ // The ThreadCache is considered valid as long as this matches the
+ // lifecycle_id of the arena being used.
+ int64 last_lifecycle_id_seen;
+ Block* last_block_used_;
+ };
+
+ static const size_t kHeaderSize = sizeof(Block);
+ static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
+ static __thread ThreadCache thread_cache_;
+
+ // SFINAE for skipping addition to delete list for a Type. This is mainly to
+ // skip proto2/proto1 message objects with cc_enable_arenas=true from being
+ // part of the delete list. Also, note, compiler will optimize out the branch
+ // in CreateInternal<T>.
+ //
+ template<typename T>
+ static inline bool SkipDeleteList(typename T::DestructorSkippable_*) {
+ return true;
+ }
+
+ // For non message objects, we skip addition to delete list if the object has
+ // a trivial destructor.
+ template<typename T>
+ static inline bool SkipDeleteList(...) {
+ return google::protobuf::internal::has_trivial_destructor<T>::value;
+ }
+
+ // CreateMessage<T> requires that T supports arenas, but this private method
+ // works whether or not T supports arenas. These are not exposed to user code
+ // as it can cause confusing API usages, and end up having double free in
+ // user code. These are used only internally from LazyField and Repeated
+ // fields, since they are designed to work in all mode combinations.
+ template<typename Msg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static Msg* CreateMaybeMessage(
+ Arena* arena, typename Msg::InternalArenaConstructable_*) {
+ return CreateMessage<Msg>(arena);
+ }
+
+ template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* CreateMaybeMessage(Arena* arena, ...) {
+ return Create<T>(arena);
+ }
+
+ template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateInternal(
+ bool skip_explicit_ownership) {
+ T* t = new (AllocateAligned(sizeof(T))) T();
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateInternal(
+ bool skip_explicit_ownership, const Arg& arg) {
+ T* t = new (AllocateAligned(sizeof(T))) T(arg);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateInternal(
+ bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
+ T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
+ return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+ this);
+ }
+
+ // These implement Own(), which registers an object for deletion (destructor
+ // call and operator delete()). The second parameter has type 'true_type' if T
+ // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
+ // all template instantiations to one for generic Message reduces code size,
+ // using the virtual destructor instead.
+ template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ void OwnInternal(T* object, google::protobuf::internal::true_type) {
+ if (object != NULL) {
+ AddListNode(object, &internal::arena_delete_object< ::google::protobuf::Message >);
+ }
+ }
+ template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ void OwnInternal(T* object, google::protobuf::internal::false_type) {
+ if (object != NULL) {
+ AddListNode(object, &internal::arena_delete_object<T>);
+ }
+ }
+
+ // Implementation for GetArena(). Only message objects with
+ // InternalArenaConstructable_ tags can be associated with an arena, and such
+ // objects must implement a GetArenaNoVirtual() method.
+ template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static inline ::google::protobuf::Arena* GetArenaInternal(T* value,
+ typename T::InternalArenaConstructable_*) {
+ return value->GetArenaNoVirtual();
+ }
+
+ template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static inline ::google::protobuf::Arena* GetArenaInternal(T* value, ...) {
+ return NULL;
+ }
+
+
+ void* AllocateAligned(size_t size);
+
+ void Init(const ArenaOptions& options);
+
+ // Free all blocks and return the total space used which is the sums of sizes
+ // of the all the allocated blocks.
+ uint64 FreeBlocks();
+
+ // Add object pointer and cleanup function pointer to the list.
+ // TODO(rohananil, cfallin): We could pass in a sub-arena into this method
+ // to avoid polluting blocks of this arena with list nodes. This would help in
+ // mixed mode (where many protobufs have cc_enable_arenas=false), and is an
+ // alternative to a chunked linked-list, but with extra overhead of *next.
+ void AddListNode(void* elem, void (*cleanup)(void*));
+ // Delete or Destruct all objects owned by the arena.
+ void CleanupList();
+
+ inline void SetThreadCacheBlock(Block* block) {
+ thread_cache_.last_block_used_ = block;
+ thread_cache_.last_lifecycle_id_seen = lifecycle_id_;
+ }
+
+ int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
+ size_t start_block_size_; // Starting block size of the arena.
+ size_t max_block_size_; // Max block size of the arena.
+
+ google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks
+ google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
+
+ // Node contains the ptr of the object to be cleaned up and the associated
+ // cleanup function ptr.
+ struct Node {
+ void* elem; // Pointer to the object to be cleaned up.
+ void (*cleanup)(void*); // Function pointer to the destructor or deleter.
+ Node* next; // Next node in the list.
+ };
+
+ google::protobuf::internal::AtomicWord cleanup_list_; // Head of a linked list of nodes containing object
+ // ptrs and cleanup methods.
+
+ bool owns_first_block_; // Indicates that arena owns the first block
+ Mutex blocks_lock_;
+
+ void AddBlock(Block* b);
+ void* SlowAlloc(size_t n);
+ Block* FindBlock(void* me);
+ Block* NewBlock(void* me, Block* my_last_block, size_t n,
+ size_t start_block_size, size_t max_block_size);
+ static void* AllocFromBlock(Block* b, size_t n);
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
+};
+
+template<typename T>
+const typename Arena::is_arena_constructable<T>::type
+ Arena::is_arena_constructable<T>::value =
+ typename Arena::is_arena_constructable<T>::type();
+
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_ARENA_H__
diff --git a/src/google/protobuf/arena_nc.cc b/src/google/protobuf/arena_nc.cc
new file mode 100644
index 00000000..f2f08427
--- /dev/null
+++ b/src/google/protobuf/arena_nc.cc
@@ -0,0 +1,45 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Negative compilation test for arena usage.
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/unittest.pb.h>
+
+#ifdef TEST_ARENA_PRIVATE_CONSTRUCTOR
+
+namespace google {
+void ArenaPrivateConstructor() {
+ google::protobuf::Arena arena;
+ protobuf_unittest::TestAllTypes message(&arena);
+}
+
+#endif
+} // namespace google
diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
new file mode 100644
index 00000000..41b1b5f8
--- /dev/null
+++ b/src/google/protobuf/arena_nc_test.py
@@ -0,0 +1,59 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Negative compilation unit tests for arena API."""
+
+from google3.testing.pybase import fake_target_util
+from google.apputils import basetest
+
+
+class ArenaNcTest(basetest.TestCase):
+
+ def testCompilerErrors(self):
+ """Runs a list of tests to verify compiler error messages."""
+
+ # Defines a list of test specs, where each element is a tuple
+ # (test name, list of regexes for matching the compiler errors).
+ test_specs = [
+ ('ARENA_PRIVATE_CONSTRUCTOR',
+ [r'calling a protected constructor']),
+ ('SANITY', None)]
+
+ fake_target_util.AssertCcCompilerErrors(
+ self, # The current test case.
+ 'google3/google/protobuf/arena_nc', # The fake target file.
+ 'arena_nc.o', # The sub-target to build.
+ test_specs # List of test specifications.
+ )
+
+if __name__ == '__main__':
+ basetest.main()
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
new file mode 100644
index 00000000..7ab6fad8
--- /dev/null
+++ b/src/google/protobuf/arena_unittest.cc
@@ -0,0 +1,972 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/arena.h>
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest_arena.pb.h>
+#include <google/protobuf/unittest_no_arena.pb.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+
+namespace google {
+using proto2_arena_unittest::ArenaMessage;
+using protobuf_unittest::TestAllTypes;
+using protobuf_unittest::TestAllExtensions;
+using protobuf_unittest::TestOneof2;
+using protobuf_unittest::TestEmptyMessage;
+
+namespace protobuf {
+namespace {
+
+class Notifier {
+ public:
+ Notifier() : count_(0) {}
+ void Notify() {
+ count_++;
+ }
+ int GetCount() {
+ return count_;
+ }
+
+ private:
+ int count_;
+};
+
+class SimpleDataType {
+ public:
+ SimpleDataType() : notifier_(NULL) {}
+ void SetNotifier(Notifier* notifier) {
+ notifier_ = notifier;
+ }
+ virtual ~SimpleDataType() {
+ if (notifier_ != NULL) {
+ notifier_->Notify();
+ }
+ };
+ private:
+ Notifier* notifier_;
+};
+} // namespace
+
+TEST(ArenaTest, ArenaConstructable) {
+ EXPECT_TRUE(Arena::is_arena_constructable<TestAllTypes>::type::value);
+ EXPECT_TRUE(Arena::is_arena_constructable<const TestAllTypes>::type::value);
+ EXPECT_FALSE(Arena::is_arena_constructable<Arena>::type::value);
+}
+
+TEST(ArenaTest, BasicCreate) {
+ Arena arena;
+ EXPECT_TRUE(Arena::Create<int32>(&arena) != NULL);
+ EXPECT_TRUE(Arena::Create<int64>(&arena) != NULL);
+ EXPECT_TRUE(Arena::Create<float>(&arena) != NULL);
+ EXPECT_TRUE(Arena::Create<double>(&arena) != NULL);
+ EXPECT_TRUE(Arena::Create<string>(&arena) != NULL);
+ arena.Own(new int32);
+ arena.Own(new int64);
+ arena.Own(new float);
+ arena.Own(new double);
+ arena.Own(new string);
+ arena.Own<int>(NULL);
+ Notifier notifier;
+ SimpleDataType* data = Arena::Create<SimpleDataType>(&arena);
+ data->SetNotifier(&notifier);
+ data = new SimpleDataType;
+ data->SetNotifier(&notifier);
+ arena.Own(data);
+ arena.Reset();
+ EXPECT_EQ(2, notifier.GetCount());
+}
+
+TEST(ArenaTest, Parsing) {
+ TestAllTypes original;
+ TestUtil::SetAllFields(&original);
+
+ // Test memory leak.
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->ParseFromString(original.SerializeAsString());
+ TestUtil::ExpectAllFieldsSet(*arena_message);
+
+ // Test that string fields have null terminator bytes (earlier bug).
+ EXPECT_EQ(strlen(original.optional_string().c_str()),
+ strlen(arena_message->optional_string().c_str()));
+}
+
+TEST(ArenaTest, UnknownFields) {
+ TestAllTypes original;
+ TestUtil::SetAllFields(&original);
+
+ // Test basic parsing into (populating) and reading out of unknown fields on
+ // an arena.
+ Arena arena;
+ TestEmptyMessage* arena_message =
+ Arena::CreateMessage<TestEmptyMessage>(&arena);
+ arena_message->ParseFromString(original.SerializeAsString());
+
+ TestAllTypes copied;
+ copied.ParseFromString(arena_message->SerializeAsString());
+ TestUtil::ExpectAllFieldsSet(copied);
+
+ // Exercise UFS manual manipulation (setters).
+ arena_message = Arena::CreateMessage<TestEmptyMessage>(&arena);
+ arena_message->mutable_unknown_fields()->AddVarint(
+ TestAllTypes::kOptionalInt32FieldNumber, 42);
+ copied.Clear();
+ copied.ParseFromString(arena_message->SerializeAsString());
+ EXPECT_TRUE(copied.has_optional_int32());
+ EXPECT_EQ(42, copied.optional_int32());
+
+ // Exercise UFS swap path.
+ TestEmptyMessage* arena_message_2 =
+ Arena::CreateMessage<TestEmptyMessage>(&arena);
+ arena_message_2->Swap(arena_message);
+ copied.Clear();
+ copied.ParseFromString(arena_message_2->SerializeAsString());
+ EXPECT_TRUE(copied.has_optional_int32());
+ EXPECT_EQ(42, copied.optional_int32());
+
+ // Test field manipulation.
+ TestEmptyMessage* arena_message_3 =
+ Arena::CreateMessage<TestEmptyMessage>(&arena);
+ arena_message_3->mutable_unknown_fields()->AddVarint(1000, 42);
+ arena_message_3->mutable_unknown_fields()->AddFixed32(1001, 42);
+ arena_message_3->mutable_unknown_fields()->AddFixed64(1002, 42);
+ arena_message_3->mutable_unknown_fields()->AddLengthDelimited(1003);
+ arena_message_3->mutable_unknown_fields()->DeleteSubrange(0, 2);
+ arena_message_3->mutable_unknown_fields()->DeleteByNumber(1002);
+ arena_message_3->mutable_unknown_fields()->DeleteByNumber(1003);
+ EXPECT_TRUE(arena_message_3->unknown_fields().empty());
+}
+
+TEST(ArenaTest, Swap) {
+ Arena arena1;
+ Arena arena2;
+ TestAllTypes* arena1_message;
+ TestAllTypes* arena2_message;
+
+ // Case 1: Swap(), no UFS on either message, both messages on different
+ // arenas. Arena pointers should remain the same after swap.
+ arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ arena1_message->Swap(arena2_message);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(&arena2, arena2_message->GetArena());
+
+ // Case 2: Swap(), UFS on one message, both messages on different arenas.
+ arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
+ arena1_message->Swap(arena2_message);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(&arena2, arena2_message->GetArena());
+ EXPECT_EQ(0, arena1_message->unknown_fields().field_count());
+ EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
+ EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
+
+ // Case 3: Swap(), UFS on both messages, both messages on different arenas.
+ arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ arena1_message->mutable_unknown_fields()->AddVarint(1, 42);
+ arena2_message->mutable_unknown_fields()->AddVarint(2, 84);
+ arena1_message->Swap(arena2_message);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(&arena2, arena2_message->GetArena());
+ EXPECT_EQ(1, arena1_message->unknown_fields().field_count());
+ EXPECT_EQ(1, arena2_message->unknown_fields().field_count());
+ EXPECT_EQ(84, arena1_message->unknown_fields().field(0).varint());
+ EXPECT_EQ(42, arena2_message->unknown_fields().field(0).varint());
+}
+
+TEST(ArenaTest, SetAllocatedMessage) {
+ Arena arena;
+ TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
+ nested->set_bb(118);
+ arena_message->set_allocated_optional_nested_message(nested);
+ EXPECT_EQ(118, arena_message->optional_nested_message().bb());
+
+ protobuf_unittest_no_arena::TestNoArenaMessage no_arena_message;
+ EXPECT_FALSE(no_arena_message.has_arena_message());
+ no_arena_message.set_allocated_arena_message(NULL);
+ EXPECT_FALSE(no_arena_message.has_arena_message());
+ no_arena_message.set_allocated_arena_message(new ArenaMessage);
+ EXPECT_TRUE(no_arena_message.has_arena_message());
+}
+
+TEST(ArenaTest, ReleaseMessage) {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->mutable_optional_nested_message()->set_bb(118);
+ scoped_ptr<TestAllTypes::NestedMessage> nested(
+ arena_message->release_optional_nested_message());
+ EXPECT_EQ(118, nested->bb());
+
+ TestAllTypes::NestedMessage* released_null =
+ arena_message->release_optional_nested_message();
+ EXPECT_EQ(NULL, released_null);
+}
+
+TEST(ArenaTest, SetAllocatedString) {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ string* allocated_str = new string("hello");
+ arena_message->set_allocated_optional_string(allocated_str);
+ EXPECT_EQ("hello", arena_message->optional_string());
+}
+
+TEST(ArenaTest, ReleaseString) {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->set_optional_string("hello");
+ scoped_ptr<string> released_str(
+ arena_message->release_optional_string());
+ EXPECT_EQ("hello", *released_str);
+
+ // Test default value.
+}
+
+
+TEST(ArenaTest, SwapBetweenArenasWithAllFieldsSet) {
+ Arena arena1;
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ {
+ Arena arena2;
+ TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ TestUtil::SetAllFields(arena2_message);
+ arena2_message->Swap(arena1_message);
+ string output;
+ arena2_message->SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+ }
+ TestUtil::ExpectAllFieldsSet(*arena1_message);
+}
+
+TEST(ArenaTest, SwapBetweenArenaAndNonArenaWithAllFieldsSet) {
+ TestAllTypes non_arena_message;
+ TestUtil::SetAllFields(&non_arena_message);
+ {
+ Arena arena2;
+ TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ TestUtil::SetAllFields(arena2_message);
+ arena2_message->Swap(&non_arena_message);
+ TestUtil::ExpectAllFieldsSet(*arena2_message);
+ TestUtil::ExpectAllFieldsSet(non_arena_message);
+ }
+}
+
+TEST(ArenaTest, UnsafeArenaSwap) {
+ Arena shared_arena;
+ TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&shared_arena);
+ TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&shared_arena);
+ TestUtil::SetAllFields(message1);
+ message1->UnsafeArenaSwap(message2);
+ TestUtil::ExpectAllFieldsSet(*message2);
+}
+
+TEST(ArenaTest, SwapBetweenArenasUsingReflection) {
+ Arena arena1;
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ {
+ Arena arena2;
+ TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ TestUtil::SetAllFields(arena2_message);
+ const Reflection* r = arena2_message->GetReflection();
+ r->Swap(arena1_message, arena2_message);
+ string output;
+ arena2_message->SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+ }
+ TestUtil::ExpectAllFieldsSet(*arena1_message);
+}
+
+TEST(ArenaTest, SwapBetweenArenaAndNonArenaUsingReflection) {
+ TestAllTypes non_arena_message;
+ TestUtil::SetAllFields(&non_arena_message);
+ {
+ Arena arena2;
+ TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ TestUtil::SetAllFields(arena2_message);
+ const Reflection* r = arena2_message->GetReflection();
+ r->Swap(&non_arena_message, arena2_message);
+ TestUtil::ExpectAllFieldsSet(*arena2_message);
+ TestUtil::ExpectAllFieldsSet(non_arena_message);
+ }
+}
+
+TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) {
+ TestAllTypes::NestedMessage* nested_msg = NULL;
+ string* nested_string = NULL;
+ {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->mutable_optional_nested_message()->set_bb(42);
+ *arena_message->mutable_optional_string() = "Hello";
+ nested_msg = arena_message->release_optional_nested_message();
+ nested_string = arena_message->release_optional_string();
+ }
+ EXPECT_EQ(42, nested_msg->bb());
+ EXPECT_EQ("Hello", *nested_string);
+ delete nested_msg;
+ delete nested_string;
+}
+
+TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
+ TestAllTypes::NestedMessage* nested_msg = NULL;
+ // Note: no string: reflection API only supports releasing submessages.
+ {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->mutable_optional_nested_message()->set_bb(42);
+ const Reflection* r = arena_message->GetReflection();
+ const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName(
+ "optional_nested_message");
+ nested_msg = dynamic_cast<TestAllTypes::NestedMessage*>(
+ r->ReleaseMessage(arena_message, f));
+ }
+ EXPECT_EQ(42, nested_msg->bb());
+ delete nested_msg;
+}
+
+TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ TestAllTypes::NestedMessage* nested_msg = NULL;
+ TestAllTypes::NestedMessage* orig_nested_msg = NULL;
+ string* nested_string = NULL;
+ string* orig_nested_string = NULL;
+ arena_message->mutable_optional_nested_message()->set_bb(42);
+ *arena_message->mutable_optional_string() = "Hello";
+ orig_nested_msg = arena_message->mutable_optional_nested_message();
+ orig_nested_string = arena_message->mutable_optional_string();
+ nested_msg = arena_message->unsafe_arena_release_optional_nested_message();
+ nested_string = arena_message->unsafe_arena_release_optional_string();
+
+ EXPECT_EQ(orig_nested_msg, nested_msg);
+ EXPECT_EQ(orig_nested_string, nested_string);
+ // Released pointers still on arena; no 'delete' calls needed here.
+}
+
+TEST(ArenaTest, SetAllocatedAcrossArenas) {
+ Arena arena1;
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ TestAllTypes::NestedMessage* heap_submessage =
+ new TestAllTypes::NestedMessage();
+ heap_submessage->set_bb(42);
+ arena1_message->set_allocated_optional_nested_message(heap_submessage);
+ // Should keep same object and add to arena's Own()-list.
+ EXPECT_EQ(heap_submessage,
+ arena1_message->mutable_optional_nested_message());
+ {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ arena1_message->set_allocated_optional_nested_message(arena2_submessage);
+ EXPECT_NE(arena2_submessage,
+ arena1_message->mutable_optional_nested_message());
+ }
+
+ TestAllTypes::NestedMessage* arena1_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
+ arena1_submessage->set_bb(42);
+ TestAllTypes* heap_message = new TestAllTypes;
+ heap_message->set_allocated_optional_nested_message(arena1_submessage);
+ EXPECT_NE(arena1_submessage,
+ heap_message->mutable_optional_nested_message());
+ delete heap_message;
+}
+
+TEST(ArenaTest, SetAllocatedAcrossArenasWithReflection) {
+ // Same as above, with reflection.
+ Arena arena1;
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ const Reflection* r = arena1_message->GetReflection();
+ const Descriptor* d = arena1_message->GetDescriptor();
+ const FieldDescriptor* msg_field = d->FindFieldByName(
+ "optional_nested_message");
+ TestAllTypes::NestedMessage* heap_submessage =
+ new TestAllTypes::NestedMessage();
+ heap_submessage->set_bb(42);
+ r->SetAllocatedMessage(arena1_message, heap_submessage, msg_field);
+ // Should keep same object and add to arena's Own()-list.
+ EXPECT_EQ(heap_submessage,
+ arena1_message->mutable_optional_nested_message());
+ {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ r->SetAllocatedMessage(arena1_message, arena2_submessage, msg_field);
+ EXPECT_NE(arena2_submessage,
+ arena1_message->mutable_optional_nested_message());
+ }
+
+ TestAllTypes::NestedMessage* arena1_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena1);
+ arena1_submessage->set_bb(42);
+ TestAllTypes* heap_message = new TestAllTypes;
+ r->SetAllocatedMessage(heap_message, arena1_submessage, msg_field);
+ EXPECT_NE(arena1_submessage,
+ heap_message->mutable_optional_nested_message());
+ delete heap_message;
+}
+
+TEST(ArenaTest, AddAllocatedWithReflection) {
+ Arena arena1;
+ ArenaMessage* arena1_message = Arena::CreateMessage<ArenaMessage>(&arena1);
+ const Reflection* r = arena1_message->GetReflection();
+ const Descriptor* d = arena1_message->GetDescriptor();
+ const FieldDescriptor* fd =
+ d->FindFieldByName("repeated_import_no_arena_message");
+ // Message with cc_enable_arenas = false;
+ r->AddMessage(arena1_message, fd);
+ r->AddMessage(arena1_message, fd);
+ r->AddMessage(arena1_message, fd);
+ EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
+ // Message with cc_enable_arenas = true;
+ fd = d->FindFieldByName("repeated_nested_message");
+ r->AddMessage(arena1_message, fd);
+ r->AddMessage(arena1_message, fd);
+ r->AddMessage(arena1_message, fd);
+ EXPECT_EQ(3, r->FieldSize(*arena1_message, fd));
+}
+
+TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) {
+ {
+ RepeatedPtrField<TestAllTypes> repeated_field;
+ EXPECT_TRUE(repeated_field.empty());
+ EXPECT_EQ(0, repeated_field.size());
+ // Ownership is passed to repeated_field.
+ TestAllTypes* cleared = new TestAllTypes();
+ repeated_field.AddCleared(cleared);
+ EXPECT_TRUE(repeated_field.empty());
+ EXPECT_EQ(0, repeated_field.size());
+ }
+ {
+ RepeatedPtrField<TestAllTypes> repeated_field;
+ EXPECT_TRUE(repeated_field.empty());
+ EXPECT_EQ(0, repeated_field.size());
+ // Ownership is passed to repeated_field.
+ TestAllTypes* cleared = new TestAllTypes();
+ repeated_field.AddAllocated(cleared);
+ EXPECT_FALSE(repeated_field.empty());
+ EXPECT_EQ(1, repeated_field.size());
+ }
+}
+
+// N.B.: no reflection version of this test because all the arena-specific code
+// is in RepeatedPtrField, and the reflection works implicitly based on that.
+TEST(ArenaTest, AddAllocatedToRepeatedField) {
+ // Heap->arena case.
+ Arena arena1;
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ for (int i = 0; i < 10; i++) {
+ TestAllTypes::NestedMessage* heap_submessage =
+ new TestAllTypes::NestedMessage();
+ heap_submessage->set_bb(42);
+ arena1_message->mutable_repeated_nested_message()->
+ AddAllocated(heap_submessage);
+ // Should not copy object -- will use arena_->Own().
+ EXPECT_EQ(heap_submessage,
+ &arena1_message->repeated_nested_message(i));
+ EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+ }
+
+ // Arena1->Arena2 case.
+ arena1_message->Clear();
+ for (int i = 0; i < 10; i++) {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ arena1_message->mutable_repeated_nested_message()->
+ AddAllocated(arena2_submessage);
+ // Should copy object.
+ EXPECT_NE(arena2_submessage,
+ &arena1_message->repeated_nested_message(i));
+ EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+ }
+
+ // Arena->heap case.
+ TestAllTypes* heap_message = new TestAllTypes();
+ for (int i = 0; i < 10; i++) {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ heap_message->mutable_repeated_nested_message()->
+ AddAllocated(arena2_submessage);
+ // Should copy object.
+ EXPECT_NE(arena2_submessage,
+ &heap_message->repeated_nested_message(i));
+ EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
+ }
+ delete heap_message;
+
+ // Heap-arena case for strings (which are not arena-allocated).
+ arena1_message->Clear();
+ for (int i = 0; i < 10; i++) {
+ string* s = new string("Test");
+ arena1_message->mutable_repeated_string()->
+ AddAllocated(s);
+ // Should not copy.
+ EXPECT_EQ(s, &arena1_message->repeated_string(i));
+ EXPECT_EQ("Test", arena1_message->repeated_string(i));
+ }
+}
+
+TEST(ArenaTest, ReleaseLastRepeatedField) {
+ // Release from arena-allocated repeated field and ensure that returned object
+ // is heap-allocated.
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ for (int i = 0; i < 10; i++) {
+ TestAllTypes::NestedMessage* nested =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena);
+ nested->set_bb(42);
+ arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
+ }
+
+ for (int i = 0; i < 10; i++) {
+ const TestAllTypes::NestedMessage *orig_submessage =
+ &arena_message->repeated_nested_message(10 - 1 - i); // last element
+ TestAllTypes::NestedMessage *released =
+ arena_message->mutable_repeated_nested_message()->ReleaseLast();
+ EXPECT_NE(released, orig_submessage);
+ EXPECT_EQ(42, released->bb());
+ delete released;
+ }
+
+ // Test UnsafeArenaReleaseLast().
+ for (int i = 0; i < 10; i++) {
+ TestAllTypes::NestedMessage* nested =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena);
+ nested->set_bb(42);
+ arena_message->mutable_repeated_nested_message()->AddAllocated(nested);
+ }
+
+ for (int i = 0; i < 10; i++) {
+ const TestAllTypes::NestedMessage *orig_submessage =
+ &arena_message->repeated_nested_message(10 - 1 - i); // last element
+ TestAllTypes::NestedMessage *released =
+ arena_message->mutable_repeated_nested_message()->
+ UnsafeArenaReleaseLast();
+ EXPECT_EQ(released, orig_submessage);
+ EXPECT_EQ(42, released->bb());
+ // no delete -- |released| is on the arena.
+ }
+
+ // Test string case as well. ReleaseLast() in this case must copy the string,
+ // even though it was originally heap-allocated and its pointer was simply
+ // appended to the repeated field's internal vector, because the string was
+ // placed on the arena's destructor list and cannot be removed from that list
+ // (so the arena permanently owns the original instance).
+ arena_message->Clear();
+ for (int i = 0; i < 10; i++) {
+ string* s = new string("Test");
+ arena_message->mutable_repeated_string()->AddAllocated(s);
+ }
+ for (int i = 0; i < 10; i++) {
+ const string* orig_element = &arena_message->repeated_string(10 - 1 - i);
+ string* released = arena_message->mutable_repeated_string()->ReleaseLast();
+ EXPECT_NE(released, orig_element);
+ EXPECT_EQ("Test", *released);
+ delete released;
+ }
+}
+
+TEST(ArenaTest, UnsafeArenaReleaseAdd) {
+ // Use unsafe_arena_release() and unsafe_arena_set_allocated() to transfer an
+ // arena-allocated string from one message to another.
+ Arena arena;
+ TestAllTypes* message1 = Arena::CreateMessage<TestAllTypes>(&arena);
+ TestAllTypes* message2 = Arena::CreateMessage<TestAllTypes>(&arena);
+ string* arena_string = Arena::Create<string>(&arena);
+ *arena_string = "Test content";
+
+ message1->unsafe_arena_set_allocated_optional_string(arena_string);
+ EXPECT_EQ(arena_string, message1->mutable_optional_string());
+ message2->unsafe_arena_set_allocated_optional_string(
+ message1->unsafe_arena_release_optional_string());
+ EXPECT_EQ(arena_string, message2->mutable_optional_string());
+}
+
+TEST(ArenaTest, UnsafeArenaAddAllocated) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ for (int i = 0; i < 10; i++) {
+ string* arena_string = Arena::Create<string>(&arena);
+ message->mutable_repeated_string()->UnsafeArenaAddAllocated(arena_string);
+ EXPECT_EQ(arena_string, message->mutable_repeated_string(i));
+ }
+}
+
+namespace {
+void TestSwapRepeatedField(Arena* arena1, Arena* arena2) {
+ // Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField
+ // between arenas.
+ RepeatedPtrField<TestAllTypes> field1(arena1);
+ RepeatedPtrField<TestAllTypes> field2(arena2);
+ for (int i = 0; i < 10; i++) {
+ TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena1);
+ t->set_optional_string("field1");
+ t->set_optional_int32(i);
+ if (arena1 != NULL) {
+ field1.UnsafeArenaAddAllocated(t);
+ } else {
+ field1.AddAllocated(t);
+ }
+ }
+ for (int i = 0; i < 5; i++) {
+ TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena2);
+ t->set_optional_string("field2");
+ t->set_optional_int32(i);
+ if (arena2 != NULL) {
+ field2.UnsafeArenaAddAllocated(t);
+ } else {
+ field2.AddAllocated(t);
+ }
+ }
+ field1.Swap(&field2);
+ EXPECT_EQ(5, field1.size());
+ EXPECT_EQ(10, field2.size());
+ EXPECT_TRUE(string("field1") == field2.Get(0).optional_string());
+ EXPECT_TRUE(string("field2") == field1.Get(0).optional_string());
+ // Ensure that fields retained their original order:
+ for (int i = 0; i < field1.size(); i++) {
+ EXPECT_EQ(i, field1.Get(i).optional_int32());
+ }
+ for (int i = 0; i < field2.size(); i++) {
+ EXPECT_EQ(i, field2.Get(i).optional_int32());
+ }
+}
+} // namespace
+
+TEST(ArenaTest, SwapRepeatedField) {
+ Arena arena;
+ TestSwapRepeatedField(&arena, &arena);
+}
+
+TEST(ArenaTest, SwapRepeatedFieldWithDifferentArenas) {
+ Arena arena1;
+ Arena arena2;
+ TestSwapRepeatedField(&arena1, &arena2);
+}
+
+TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnRightHandSide) {
+ Arena arena;
+ TestSwapRepeatedField(&arena, NULL);
+}
+
+TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnLeftHandSide) {
+ Arena arena;
+ TestSwapRepeatedField(NULL, &arena);
+}
+
+TEST(ArenaTest, ExtensionsOnArena) {
+ Arena arena;
+ // Ensure no leaks.
+ TestAllExtensions* message_ext =
+ Arena::CreateMessage<TestAllExtensions>(&arena);
+ message_ext->SetExtension(
+ protobuf_unittest::optional_int32_extension, 42);
+ message_ext->SetExtension(
+ protobuf_unittest::optional_string_extension, string("test"));
+ message_ext->MutableExtension(
+ protobuf_unittest::optional_nested_message_extension)->set_bb(42);
+}
+
+class NoHeapChecker {
+ public:
+ NoHeapChecker() {
+ capture_alloc.Hook();
+ }
+ ~NoHeapChecker() {
+ capture_alloc.Unhook();
+ EXPECT_EQ(0, capture_alloc.alloc_count());
+ EXPECT_EQ(0, capture_alloc.free_count());
+ }
+ private:
+ class NewDeleteCapture {
+ public:
+ // TOOD(xiaofeng): Implement this for opensource protobuf.
+ void Hook() {}
+ void Unhook() {}
+ int alloc_count() { return 0; }
+ int free_count() { return 0; }
+ } capture_alloc;
+};
+
+TEST(ArenaTest, RepeatedFieldOnArena) {
+ // Preallocate an initial arena block to avoid mallocs during hooked region.
+ std::vector<char> arena_block(1024 * 1024);
+ ArenaOptions options;
+ options.initial_block = arena_block.data();
+ options.initial_block_size = arena_block.size();
+ Arena arena(options);
+
+ {
+ NoHeapChecker no_heap;
+
+ // Fill some repeated fields on the arena to test for leaks. Also verify no
+ // memory allocations.
+ RepeatedField<int32> repeated_int32(&arena);
+ RepeatedPtrField<TestAllTypes> repeated_message(&arena);
+ for (int i = 0; i < 100; i++) {
+ repeated_int32.Add(42);
+ repeated_message.Add()->set_optional_int32(42);
+ EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
+ const TestAllTypes* msg_in_repeated_field = &repeated_message.Get(0);
+ TestAllTypes* msg = repeated_message.UnsafeArenaReleaseLast();
+ EXPECT_EQ(msg_in_repeated_field, msg);
+ }
+
+ // UnsafeArenaExtractSubrange (i) should not leak and (ii) should return
+ // on-arena pointers.
+ for (int i = 0; i < 10; i++) {
+ repeated_message.Add()->set_optional_int32(42);
+ }
+ TestAllTypes* extracted_messages[5];
+ repeated_message.UnsafeArenaExtractSubrange(0, 5, extracted_messages);
+ EXPECT_EQ(&arena, repeated_message.Get(0).GetArena());
+ EXPECT_EQ(5, repeated_message.size());
+ }
+
+ // Now, outside the scope of the NoHeapChecker, test ExtractSubrange's copying
+ // semantics.
+ {
+ RepeatedPtrField<TestAllTypes> repeated_message(&arena);
+ for (int i = 0; i < 100; i++) {
+ repeated_message.Add()->set_optional_int32(42);
+ }
+
+ TestAllTypes* extracted_messages[5];
+ // ExtractSubrange should copy to the heap.
+ repeated_message.ExtractSubrange(0, 5, extracted_messages);
+ EXPECT_EQ(NULL, extracted_messages[0]->GetArena());
+ // We need to free the heap-allocated messages to prevent a leak.
+ for (int i = 0; i < 5; i++) {
+ delete extracted_messages[i];
+ extracted_messages[i] = NULL;
+ }
+ }
+
+ // Now check that we can create RepeatedFields/RepeatedPtrFields themselves on
+ // the arena. They have the necessary type traits so that they can behave like
+ // messages in this way. This is useful for higher-level generic templated
+ // code that may allocate messages or repeated fields of messages on an arena.
+ {
+ RepeatedPtrField<TestAllTypes>* repeated_ptr_on_arena =
+ Arena::CreateMessage< RepeatedPtrField<TestAllTypes> >(&arena);
+ for (int i = 0; i < 10; i++) {
+ // Add some elements and let the leak-checker ensure that everything is
+ // freed.
+ repeated_ptr_on_arena->Add();
+ }
+
+ RepeatedField<int>* repeated_int_on_arena =
+ Arena::CreateMessage< RepeatedField<int> >(&arena);
+ for (int i = 0; i < 100; i++) {
+ repeated_int_on_arena->Add(i);
+ }
+
+ }
+
+ arena.Reset();
+}
+
+
+TEST(ArenaTest, MutableMessageReflection) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ const Reflection* r = message->GetReflection();
+ const Descriptor* d = message->GetDescriptor();
+ const FieldDescriptor* field = d->FindFieldByName("optional_nested_message");
+ TestAllTypes::NestedMessage* submessage =
+ dynamic_cast<TestAllTypes::NestedMessage*>(
+ r->MutableMessage(message, field));
+ TestAllTypes::NestedMessage* submessage_expected =
+ message->mutable_optional_nested_message();
+
+ EXPECT_EQ(submessage_expected, submessage);
+ EXPECT_EQ(&arena, submessage->GetArena());
+
+ const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message");
+ submessage = dynamic_cast<TestAllTypes::NestedMessage*>(
+ r->MutableMessage(message, oneof_field));
+ submessage_expected = message->mutable_oneof_nested_message();
+
+ EXPECT_EQ(submessage_expected, submessage);
+ EXPECT_EQ(&arena, submessage->GetArena());
+}
+
+
+namespace {
+
+void FillArenaAwareFields(TestAllTypes* message) {
+ string test_string = "hello world";
+ message->set_optional_int32(42);
+ message->set_optional_string(test_string);
+ message->set_optional_bytes(test_string);
+ message->mutable_optional_nested_message()->set_bb(42);
+
+ message->set_oneof_uint32(42);
+ message->mutable_oneof_nested_message()->set_bb(42);
+ message->set_oneof_string(test_string);
+ message->set_oneof_bytes(test_string);
+
+ message->add_repeated_int32(42);
+ // No repeated string: not yet arena-aware.
+ message->add_repeated_nested_message()->set_bb(42);
+ message->mutable_optional_lazy_message()->set_bb(42);
+}
+
+}
+
+// Test: no allocations occur on heap while touching all supported field types.
+TEST(ArenaTest, NoHeapAllocationsTest) {
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ ArenaOptions options;
+ options.initial_block = arena_block.data();
+ options.initial_block_size = arena_block.size();
+ Arena arena(options);
+
+ {
+
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ FillArenaAwareFields(message);
+ }
+
+ arena.Reset();
+}
+
+
+// Test construction on an arena via generic MessageLite interface. We should be
+// able to successfully deserialize on the arena without incurring heap
+// allocations, i.e., everything should still be arena-allocation-aware.
+TEST(ArenaTest, MessageLiteOnArena) {
+ std::vector<char> arena_block(128 * 1024);
+ ArenaOptions options;
+ options.initial_block = arena_block.data();
+ options.initial_block_size = arena_block.size();
+ Arena arena(options);
+ const google::protobuf::MessageLite* prototype = dynamic_cast<
+ const google::protobuf::MessageLite*>(&TestAllTypes::default_instance());
+
+ TestAllTypes initial_message;
+ FillArenaAwareFields(&initial_message);
+ string serialized;
+ initial_message.SerializeToString(&serialized);
+
+ {
+
+ google::protobuf::MessageLite* generic_message = prototype->New(&arena);
+ EXPECT_TRUE(generic_message != NULL);
+ EXPECT_EQ(&arena, generic_message->GetArena());
+ EXPECT_TRUE(generic_message->ParseFromString(serialized));
+ TestAllTypes* deserialized = dynamic_cast<TestAllTypes*>(generic_message);
+ EXPECT_TRUE(deserialized != NULL);
+ EXPECT_EQ(42, deserialized->optional_int32());
+ }
+
+ arena.Reset();
+}
+
+
+// RepeatedField should support non-POD types, and invoke constructors and
+// destructors appropriately, because it's used this way by lots of other code
+// (even if this was not its original intent).
+TEST(ArenaTest, RepeatedFieldWithNonPODType) {
+ {
+ RepeatedField<string> field_on_heap;
+ for (int i = 0; i < 100; i++) {
+ *field_on_heap.Add() = "test string long enough to exceed inline buffer";
+ }
+ }
+ {
+ Arena arena;
+ RepeatedField<string> field_on_arena(&arena);
+ for (int i = 0; i < 100; i++) {
+ *field_on_arena.Add() = "test string long enough to exceed inline buffer";
+ }
+ }
+}
+
+TEST(ArenaTest, SpaceUsed) {
+ ArenaOptions options;
+ options.start_block_size = 256;
+ options.max_block_size = 8192;
+ Arena arena_1(options);
+ EXPECT_EQ(0, arena_1.SpaceUsed());
+ EXPECT_EQ(0, arena_1.Reset());
+ ::google::protobuf::Arena::CreateArray<char>(&arena_1, 320);
+ // Arena will allocate slightly more than 320 for the block headers.
+ EXPECT_LE(320, arena_1.SpaceUsed());
+ EXPECT_LE(320, arena_1.Reset());
+
+ // Test with initial block.
+ std::vector<char> arena_block(1024);
+ options.initial_block = arena_block.data();
+ options.initial_block_size = arena_block.size();
+ Arena arena_2(options);
+ EXPECT_EQ(1024, arena_2.SpaceUsed());
+ EXPECT_EQ(1024, arena_2.Reset());
+ ::google::protobuf::Arena::CreateArray<char>(&arena_2, 55);
+ EXPECT_EQ(1024, arena_2.SpaceUsed());
+ EXPECT_EQ(1024, arena_2.Reset());
+
+ // Reset options to test doubling policy explicitly.
+ options.initial_block = NULL;
+ options.initial_block_size = 0;
+ Arena arena_3(options);
+ ::google::protobuf::Arena::CreateArray<char>(&arena_3, 190);
+ EXPECT_EQ(256, arena_3.SpaceUsed());
+ ::google::protobuf::Arena::CreateArray<char>(&arena_3, 70);
+ EXPECT_EQ(256 + 512, arena_3.SpaceUsed());
+ EXPECT_EQ(256 + 512, arena_3.Reset());
+}
+
+TEST(ArenaTest, Alignment) {
+ ::google::protobuf::Arena arena;
+ for (int i = 0; i < 200; i++) {
+ void* p = ::google::protobuf::Arena::CreateArray<char>(&arena, i);
+ GOOGLE_CHECK_EQ(reinterpret_cast<uintptr_t>(p) % 8, 0) << i << ": " << p;
+ }
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc
new file mode 100644
index 00000000..7f33a0c8
--- /dev/null
+++ b/src/google/protobuf/arenastring.cc
@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// The ArenaString implementation is not included in the open-source release. Do
+// not include this file in the distribution.
+
+#include <google/protobuf/arenastring.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
new file mode 100755
index 00000000..5f02ef0d
--- /dev/null
+++ b/src/google/protobuf/arenastring.h
@@ -0,0 +1,314 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_ARENASTRING_H__
+#define GOOGLE_PROTOBUF_ARENASTRING_H__
+
+#include <stdint.h>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/fastmem.h>
+
+#include <google/protobuf/arena.h>
+#include <google/protobuf/generated_message_util.h>
+
+
+
+// This is the implementation of arena string fields written for the open-source
+// release. The ArenaStringPtr struct below is an internal implementation class
+// and *should not be used* by user code. It is used to collect string
+// operations together into one place and abstract away the underlying
+// string-field pointer representation, so that (for example) an alternate
+// implementation that knew more about ::std::string's internals could integrate more
+// closely with the arena allocator.
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+struct ArenaStringPtr {
+ inline void Set(const ::std::string* default_value,
+ const ::std::string& value, ::google::protobuf::Arena* arena) {
+ if (ptr_ == default_value) {
+ CreateInstance(arena, &value);
+ } else {
+ *ptr_ = value;
+ }
+ }
+
+ // Basic accessors.
+ inline const ::std::string& Get(const ::std::string* default_value) const {
+ return *ptr_;
+ }
+
+ inline ::std::string* Mutable(const ::std::string* default_value,
+ ::google::protobuf::Arena* arena) {
+ if (ptr_ == default_value) {
+ CreateInstance(arena, default_value);
+ }
+ return ptr_;
+ }
+
+ // Release returns a ::std::string* instance that is heap-allocated and is not
+ // Own()'d by any arena. If the field was not set, it returns NULL. The caller
+ // retains ownership. Clears this field back to NULL state. Used to implement
+ // release_<field>() methods on generated classes.
+ inline ::std::string* Release(const ::std::string* default_value,
+ ::google::protobuf::Arena* arena) {
+ if (ptr_ == default_value) {
+ return NULL;
+ }
+ ::std::string* released = NULL;
+ if (arena != NULL) {
+ // ptr_ is owned by the arena -- we need to return a copy.
+ released = new ::std::string(*ptr_);
+ } else {
+ released = ptr_;
+ }
+ ptr_ = const_cast< ::std::string* >(default_value);
+ return released;
+ }
+
+ // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned (i.e.
+ // have its destructor already registered) if arena != NULL. If the field was
+ // not set, this returns NULL. This method clears this field back to NULL
+ // state. Used to implement unsafe_arena_release_<field>() methods on
+ // generated classes.
+ inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value,
+ ::google::protobuf::Arena* arena) {
+ if (ptr_ == default_value) {
+ return NULL;
+ }
+ ::std::string* released = ptr_;
+ ptr_ = const_cast< ::std::string* >(default_value);
+ return released;
+ }
+
+ // Takes a string that is heap-allocated, and takes ownership. The string's
+ // destructor is registered with the arena. Used to implement
+ // set_allocated_<field> in generated classes.
+ inline void SetAllocated(const ::std::string* default_value,
+ ::std::string* value, ::google::protobuf::Arena* arena) {
+ if (arena == NULL && ptr_ != default_value) {
+ Destroy(default_value, arena);
+ }
+ if (value != NULL) {
+ ptr_ = value;
+ if (arena != NULL) {
+ arena->Own(value);
+ }
+ } else {
+ ptr_ = const_cast< ::std::string* >(default_value);
+ }
+ }
+
+ // Takes a string that has lifetime equal to the arena's lifetime. The arena
+ // must be non-null. It is safe only to pass this method a value returned by
+ // UnsafeArenaRelease() on another field of a message in the same arena. Used
+ // to implement unsafe_arena_set_allocated_<field> in generated classes.
+ inline void UnsafeArenaSetAllocated(const ::std::string* default_value,
+ ::std::string* value, ::google::protobuf::Arena* arena) {
+ if (value != NULL) {
+ ptr_ = value;
+ } else {
+ ptr_ = const_cast< ::std::string* >(default_value);
+ }
+ }
+
+ // Swaps internal pointers. Arena-safety semantics: this is guarded by the
+ // logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
+ // 'unsafe' if called directly.
+ inline void Swap(ArenaStringPtr* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ std::swap(ptr_, other->ptr_);
+ }
+
+ // Frees storage (if not on an arena) and sets field to default value.
+ inline void Destroy(const ::std::string* default_value,
+ ::google::protobuf::Arena* arena) {
+ if (arena == NULL && ptr_ != default_value) {
+ delete ptr_;
+ }
+ ptr_ = const_cast< ::std::string* >(default_value);
+ }
+
+ // Clears content, but keeps allocated string if arena != NULL, to avoid the
+ // overhead of heap operations. After this returns, the content (as seen by
+ // the user) will always be the empty string. Assumes that |default_value|
+ // is an empty string.
+ inline void ClearToEmpty(const ::std::string* default_value,
+ ::google::protobuf::Arena* arena) {
+ if (ptr_ == default_value) {
+ // Already set to default (which is empty) -- do nothing.
+ } else {
+ ptr_->clear();
+ }
+ }
+
+ // Clears content, but keeps allocated string if arena != NULL, to avoid the
+ // overhead of heap operations. After this returns, the content (as seen by
+ // the user) will always be equal to |default_value|.
+ inline void ClearToDefault(const ::std::string* default_value,
+ ::google::protobuf::Arena* arena) {
+ if (ptr_ == default_value) {
+ // Already set to default -- do nothing.
+ } else {
+ // Have another allocated string -- rather than throwing this away and
+ // resetting ptr_ to the canonical default string instance, we just reuse
+ // this instance.
+ *ptr_ = *default_value;
+ }
+ }
+
+ // Called from generated code / reflection runtime only. Resets value to point
+ // to a default string pointer, with the semantics that this ArenaStringPtr
+ // does not own the pointed-to memory. Disregards initial value of ptr_ (so
+ // this is the *ONLY* safe method to call after construction or when
+ // reinitializing after becoming the active field in a oneof union).
+ inline void UnsafeSetDefault(const ::std::string* default_value) {
+ // Casting away 'const' is safe here: accessors ensure that ptr_ is only
+ // returned as a const if it is equal to default_value.
+ ptr_ = const_cast< ::std::string* >(default_value);
+ }
+
+ // The 'NoArena' variants of methods below assume arena == NULL and are
+ // optimized to provide very little overhead relative to a raw string pointer
+ // (while still being in-memory compatible with other code that assumes
+ // ArenaStringPtr). Note the invariant that a class instance that has only
+ // ever been mutated by NoArena methods must *only* be in the String state
+ // (i.e., tag bits are not used), *NEVER* ArenaString. This allows all
+ // tagged-pointer manipulations to be avoided.
+ inline void SetNoArena(const ::std::string* default_value,
+ const ::std::string& value) {
+ if (ptr_ == default_value) {
+ CreateInstanceNoArena(&value);
+ } else {
+ *ptr_ = value;
+ }
+ }
+
+ inline const ::std::string& GetNoArena(const ::std::string* default_value) const {
+ return *ptr_;
+ }
+
+ inline ::std::string* MutableNoArena(const ::std::string* default_value) {
+ if (ptr_ == default_value) {
+ CreateInstanceNoArena(default_value);
+ }
+ return ptr_;
+ }
+
+ inline ::std::string* ReleaseNoArena(const ::std::string* default_value) {
+ if (ptr_ == default_value) {
+ return NULL;
+ } else {
+ ::std::string* released = ptr_;
+ ptr_ = const_cast< ::std::string* >(default_value);
+ return released;
+ }
+ }
+
+ inline void SetAllocatedNoArena(const ::std::string* default_value,
+ ::std::string* value) {
+ if (ptr_ != default_value) {
+ delete ptr_;
+ }
+ if (value != NULL) {
+ ptr_ = value;
+ } else {
+ ptr_ = const_cast< ::std::string* >(default_value);
+ }
+ }
+
+ inline void DestroyNoArena(const ::std::string* default_value) {
+ if (ptr_ != default_value) {
+ delete ptr_;
+ }
+ ptr_ = NULL;
+ }
+
+ inline void ClearToEmptyNoArena(const ::std::string* default_value) {
+ if (ptr_ == default_value) {
+ // Nothing: already equal to default (which is the empty string).
+ } else {
+ ptr_->clear();
+ }
+ }
+
+ inline void ClearToDefaultNoArena(const ::std::string* default_value) {
+ if (ptr_ == default_value) {
+ // Nothing: already set to default.
+ } else {
+ // Reuse existing allocated instance.
+ *ptr_ = *default_value;
+ }
+ }
+
+ // Internal accessor used only at parse time to provide direct access to the
+ // raw pointer from the shared parse routine (in the non-arenas case). The
+ // parse routine does the string allocation in order to save code size in the
+ // generated parsing code.
+ inline ::std::string** UnsafeRawStringPointer() {
+ return &ptr_;
+ }
+
+ private:
+ ::std::string* ptr_;
+
+ inline void CreateInstance(::google::protobuf::Arena* arena,
+ const ::std::string* initial_value)
+ GOOGLE_ATTRIBUTE_NOINLINE {
+ // Assumes ptr_ is not NULL.
+ if (initial_value != NULL) {
+ ptr_ = new ::std::string(*initial_value);
+ } else {
+ ptr_ = new ::std::string();
+ }
+ if (arena != NULL) {
+ arena->Own(ptr_);
+ }
+ }
+ inline void CreateInstanceNoArena(const ::std::string* initial_value)
+ GOOGLE_ATTRIBUTE_NOINLINE {
+ if (initial_value != NULL) {
+ ptr_ = new ::std::string(*initial_value);
+ } else {
+ ptr_ = new ::std::string();
+ }
+ }
+};
+
+} // namespace internal
+} // namespace protobuf
+
+
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_ARENASTRING_H__
diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
new file mode 100644
index 00000000..8ebd4b9c
--- /dev/null
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -0,0 +1,112 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// arenastring_unittest.cc is not open-sourced. Do not include in open-source
+// distribution.
+
+// Based on mvels@'s frankenstring.
+
+#include <google/protobuf/arenastring.h>
+
+#include <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <cstdlib>
+
+#include <google/protobuf/stubs/common.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using google::protobuf::internal::ArenaString;
+using google::protobuf::internal::ArenaStringPtr;
+
+namespace protobuf {
+
+
+static string WrapString(const char* value) {
+ return value;
+}
+
+// Test ArenaStringPtr with arena == NULL.
+TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) {
+ ArenaStringPtr field;
+ ::std::string default_value = "default";
+ field.UnsafeSetDefault(&default_value);
+ EXPECT_EQ(string("default"), field.Get(&default_value));
+ field.Set(&default_value, WrapString("Test short"), NULL);
+ EXPECT_EQ(string("Test short"), field.Get(&default_value));
+ field.Set(&default_value, WrapString("Test long long long long value"), NULL);
+ EXPECT_EQ(string("Test long long long long value"), field.Get(&default_value));
+ field.Set(&default_value, string(""), NULL);
+ field.Destroy(&default_value, NULL);
+
+ ArenaStringPtr field2;
+ field2.UnsafeSetDefault(&default_value);
+ ::std::string* mut = field2.Mutable(&default_value, NULL);
+ EXPECT_EQ(mut, field2.Mutable(&default_value, NULL));
+ EXPECT_EQ(mut, &field2.Get(&default_value));
+ EXPECT_NE(&default_value, mut);
+ EXPECT_EQ(string("default"), *mut);
+ *mut = "Test long long long long value"; // ensure string allocates storage
+ EXPECT_EQ(string("Test long long long long value"), field2.Get(&default_value));
+ field2.Destroy(&default_value, NULL);
+}
+
+TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) {
+ google::protobuf::Arena arena;
+ ArenaStringPtr field;
+ ::std::string default_value = "default";
+ field.UnsafeSetDefault(&default_value);
+ EXPECT_EQ(string("default"), field.Get(&default_value));
+ field.Set(&default_value, WrapString("Test short"), &arena);
+ EXPECT_EQ(string("Test short"), field.Get(&default_value));
+ field.Set(&default_value, WrapString("Test long long long long value"), &arena);
+ EXPECT_EQ(string("Test long long long long value"),
+ field.Get(&default_value));
+ field.Set(&default_value, string(""), &arena);
+ field.Destroy(&default_value, &arena);
+
+ ArenaStringPtr field2;
+ field2.UnsafeSetDefault(&default_value);
+ ::std::string* mut = field2.Mutable(&default_value, &arena);
+ EXPECT_EQ(mut, field2.Mutable(&default_value, &arena));
+ EXPECT_EQ(mut, &field2.Get(&default_value));
+ EXPECT_NE(&default_value, mut);
+ EXPECT_EQ(string("default"), *mut);
+ *mut = "Test long long long long value"; // ensure string allocates storage
+ EXPECT_EQ(string("Test long long long long value"),
+ field2.Get(&default_value));
+ field2.Destroy(&default_value, &arena);
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index f9f27bd8..fc7df414 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -50,6 +50,9 @@
#include <google/protobuf/stubs/hash.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 5bc1fea9..6e1a204d 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -41,6 +41,9 @@
#include <unistd.h>
#endif
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/descriptor.pb.h>
@@ -48,6 +51,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/compiler/mock_code_generator.h>
#include <google/protobuf/compiler/subprocess.h>
#include <google/protobuf/io/printer.h>
@@ -59,6 +63,7 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -77,6 +82,10 @@ namespace compiler {
namespace {
+bool FileExists(const string& path) {
+ return File::Exists(path);
+}
+
class CommandLineInterfaceTest : public testing::Test {
protected:
virtual void SetUp();
@@ -226,7 +235,7 @@ void CommandLineInterfaceTest::SetUp() {
// If the temp directory already exists, it must be left over from a
// previous run. Delete it.
- if (File::Exists(temp_directory_)) {
+ if (FileExists(temp_directory_)) {
File::DeleteRecursively(temp_directory_, NULL, NULL);
}
@@ -335,7 +344,7 @@ void CommandLineInterfaceTest::CreateTempFile(
string::size_type slash_pos = name.find_last_of('/');
if (slash_pos != string::npos) {
string dir = name.substr(0, slash_pos);
- if (!File::Exists(temp_directory_ + "/" + dir)) {
+ if (!FileExists(temp_directory_ + "/" + dir)) {
GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir,
0777));
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index c31cb5b3..32d5516e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -101,6 +101,15 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
}
}
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ // For new enum semantics: generate min and max sentinel values equal to
+ // INT32_MIN and INT32_MAX
+ if (descriptor_->value_count() > 0) printer->Print(",\n");
+ printer->Print(vars,
+ "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = INT32_MIN,\n"
+ "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = INT32_MAX");
+ }
+
printer->Outdent();
printer->Print("\n};\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 20b18ade..17926135 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -87,9 +87,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@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"
+ "inline void $classname$::set_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
+ " $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
@@ -121,21 +125,27 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"int value;\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
- " input, &value)));\n"
- "if ($type$_IsValid(value)) {\n"
- " set_$name$(static_cast< $type$ >(value));\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
+ " input, &value)));\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables_,
- "} else {\n"
- " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ "set_$name$(static_cast< $type$ >(value));\n");
} else {
- printer->Print(
- "} else {\n"
- " unknown_fields_stream.WriteVarint32(tag);\n"
- " unknown_fields_stream.WriteVarint32(value);\n");
+ printer->Print(variables_,
+ "if ($type$_IsValid(value)) {\n"
+ " set_$name$(static_cast< $type$ >(value));\n");
+ 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");
}
- printer->Print(variables_,
- "}\n");
}
void EnumFieldGenerator::
@@ -174,18 +184,24 @@ void EnumOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\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"
+ "inline void $classname$::set_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" }\n"
" $oneof_prefix$$name$_ = value;\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
@@ -245,13 +261,21 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@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"
+ "inline void $classname$::set_$name$(int index, $type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
" $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"
+ "inline void $classname$::add_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
@@ -280,7 +304,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedEnumFieldGenerator::
@@ -295,20 +319,26 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"int value;\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
- " input, &value)));\n"
- "if ($type$_IsValid(value)) {\n"
- " add_$name$(static_cast< $type$ >(value));\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
+ " input, &value)));\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables_,
- "} else {\n"
- " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ "add_$name$(static_cast< $type$ >(value));\n");
} else {
- printer->Print(
- "} else {\n"
- " unknown_fields_stream.WriteVarint32(tag);\n"
- " unknown_fields_stream.WriteVarint32(value);\n");
+ printer->Print(variables_,
+ "if ($type$_IsValid(value)) {\n"
+ " add_$name$(static_cast< $type$ >(value));\n");
+ 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");
}
- printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::
@@ -318,8 +348,15 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
// rarely be executed.
printer->Print(variables_,
"DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
- " input,\n"
- " &$type$_IsValid,\n"
+ " input,\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " NULL,\n");
+ } else {
+ printer->Print(variables_,
+ " &$type$_IsValid,\n");
+ }
+ printer->Print(variables_,
" this->mutable_$name$())));\n");
} else {
printer->Print(variables_,
@@ -331,10 +368,17 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
" int value;\n"
" DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
- " input, &value)));\n"
+ " input, &value)));\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " add_$name$(static_cast< $type$ >(value));\n");
+ } else {
+ printer->Print(variables_,
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
- " }\n"
+ " }\n");
+ }
+ printer->Print(variables_,
"}\n"
"input->PopLimit(limit);\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 1e9a40ac..85838ac3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -34,6 +34,9 @@
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
@@ -68,6 +71,20 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
? " PROTOBUF_DEPRECATED" : "";
(*variables)["cppget"] = "Get";
+
+ if (HasFieldPresence(descriptor->file())) {
+ (*variables)["set_hasbit"] =
+ "set_has_" + FieldName(descriptor) + "();";
+ (*variables)["clear_hasbit"] =
+ "clear_has_" + FieldName(descriptor) + "();";
+ } else {
+ (*variables)["set_hasbit"] = "";
+ (*variables)["clear_hasbit"] = "";
+ }
+
+ // By default, empty string, so that generic code used for both oneofs and
+ // singular fields can be written.
+ (*variables)["oneof_prefix"] = "";
}
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 0342c35e..088e5063 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -37,6 +37,9 @@
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <google/protobuf/descriptor.h>
@@ -124,6 +127,16 @@ class FieldGenerator {
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateDestructorCode(io::Printer* /*printer*/) const {}
+ // Generate a manual destructor invocation for use when the message is on an
+ // arena. The code that this method generates will be executed inside a
+ // shared-for-the-whole-message-class method registered with OwnDestructor().
+ // The method should return |true| if it generated any code that requires a
+ // call; this allows the message generator to eliminate the OwnDestructor()
+ // registration if no fields require it.
+ virtual bool GenerateArenaDestructorCode(io::Printer* printer) const {
+ return false;
+ }
+
// Generate code that allocates the fields's default instance.
virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/)
const {}
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index fa194273..dc8bf613 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -34,6 +34,9 @@
#include <google/protobuf/compiler/cpp/cpp_file.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <set>
#include <google/protobuf/compiler/cpp/cpp_enum.h>
@@ -102,6 +105,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"#define PROTOBUF_$filename_identifier$__INCLUDED\n"
"\n"
"#include <string>\n"
+ "#include <stdint.h>\n" // INT32_MIN, INT32_MAX
"\n",
"filename", file_->name(),
"filename_identifier", filename_identifier);
@@ -131,7 +135,10 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// OK, it's now safe to #include other files.
printer->Print(
- "#include <google/protobuf/generated_message_util.h>\n");
+ "#include <google/protobuf/arena.h>\n"
+ "#include <google/protobuf/arenastring.h>\n"
+ "#include <google/protobuf/generated_message_util.h>\n"
+ "#include <google/protobuf/metadata.h>\n");
if (file_->message_type_count() > 0) {
if (HasDescriptorMethods(file_)) {
printer->Print(
@@ -181,6 +188,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"// @@protoc_insertion_point(includes)\n");
+
// Open namespace.
GenerateNamespaceOpeners(printer);
@@ -189,9 +197,10 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(
"\n"
"// Internal implementation detail -- do not call these.\n"
- "void $dllexport_decl$ $adddescriptorsname$();\n",
+ "void $dllexport_decl$$adddescriptorsname$();\n",
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "dllexport_decl", options_.dllexport_decl);
+ "dllexport_decl",
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
printer->Print(
// Note that we don't put dllexport_decl on these because they are only
@@ -295,7 +304,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
}
printer->Print(
"\n"
- "} // namespace google\n} // namespace protobuf\n"
+ "} // namespace protobuf\n} // namespace google\n"
"#endif // SWIG\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 4e4d8b6a..13d06f98 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 75d558ea..a2fb7162 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -36,6 +36,9 @@
#include <vector>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <utility>
#include <google/protobuf/compiler/cpp/cpp_file.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index b7a47acb..63b0265e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -60,16 +60,17 @@ string DotsToColons(const string& name) {
}
const char* const kKeywordList[] = {
- "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case",
- "catch", "char", "class", "compl", "const", "const_cast", "continue",
- "default", "delete", "do", "double", "dynamic_cast", "else", "enum",
- "explicit", "extern", "false", "float", "for", "friend", "goto", "if",
- "inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq",
- "operator", "or", "or_eq", "private", "protected", "public", "register",
- "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
- "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
- "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
- "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
+ "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
+ "bool", "break", "case", "catch", "char", "class", "compl", "const",
+ "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
+ "double", "dynamic_cast", "else", "enum", "explicit", "extern", "false",
+ "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
+ "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or",
+ "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
+ "return", "short", "signed", "sizeof", "static", "static_assert",
+ "static_cast", "struct", "switch", "template", "this", "thread_local",
+ "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
+ "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
};
hash_set<string> MakeKeywordsMap() {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 5d30240c..1cff17c8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -135,8 +135,15 @@ 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
+// Returns true if unknown fields are preseved after parsing.
+inline bool PreserveUnknownFields(const Descriptor* message) {
+ return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// If PreserveUnknownFields() is true, determines whether unknown
+// fields will be stored in an UnknownFieldSet or a string.
+// If PreserveUnknownFields() is false, this method will not be
+// used.
inline bool UseUnknownFieldSet(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
@@ -198,6 +205,28 @@ bool IsStringOrMessage(const FieldDescriptor* field);
string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
+inline bool HasFieldPresence(const FileDescriptor* file) {
+ return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns true if 'enum' semantics are such that unknown values are preserved
+// in the enum field itself, rather than going to the UnknownFieldSet.
+inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool SupportsArenas(const FileDescriptor* file) {
+ return true;
+}
+
+inline bool SupportsArenas(const Descriptor* desc) {
+ return SupportsArenas(desc->file());
+}
+
+inline bool SupportsArenas(const FieldDescriptor* field) {
+ return SupportsArenas(field->file());
+}
+
} // 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 3a9d2639..54a92ae4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -36,6 +36,9 @@
#include <google/protobuf/stubs/hash.h>
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <set>
#include <utility>
#include <vector>
@@ -281,8 +284,67 @@ string MessageTypeProtoName(const FieldDescriptor* field) {
return field->message_type()->full_name();
}
+// Emits an if-statement with a condition that evaluates to true if |field| is
+// considered non-default (will be sent over the wire), for message types
+// without true field presence. Should only be called if
+// !HasFieldPresence(message_descriptor).
+bool EmitFieldNonDefaultCondition(io::Printer* printer,
+ const string& prefix,
+ const FieldDescriptor* field) {
+ // Merge and serialize semantics: primitive fields are merged/serialized only
+ // if non-zero (numeric) or non-empty (string).
+ if (!field->is_repeated() && !field->containing_oneof()) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ printer->Print(
+ "if ($prefix$$name$().size() > 0) {\n",
+ "prefix", prefix,
+ "name", FieldName(field));
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Message fields still have has_$name$() methods.
+ printer->Print(
+ "if ($prefix$has_$name$()) {\n",
+ "prefix", prefix,
+ "name", FieldName(field));
+ } else {
+ printer->Print(
+ "if ($prefix$$name$() != 0) {\n",
+ "prefix", prefix,
+ "name", FieldName(field));
+ }
+ printer->Indent();
+ return true;
+ } else if (field->containing_oneof()) {
+ printer->Print(
+ "if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ return true;
+ }
+ return false;
+}
+
+// Does the given field have a has_$name$() method?
+bool HasHasMethod(const FieldDescriptor* field) {
+ if (HasFieldPresence(field->file())) {
+ // In proto1/proto2, every field has a has_$name$() method.
+ return true;
+ }
+ // For message types without true field presence, only fields with a message
+ // type have a has_$name$() method.
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
}
+// Does the given field have a private (internal helper only) has_$name$()
+// method?
+bool HasPrivateHasMethod(const FieldDescriptor* field) {
+ // Only for oneofs in message types with no field presence. has_$name$(),
+ // based on the oneof case, is still useful internally for generated code.
+ return (!HasFieldPresence(field->file()) &&
+ field->containing_oneof() != NULL);
+}
+
+} // anonymous namespace
+
// ===================================================================
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
@@ -312,6 +374,13 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
extension_generators_[i].reset(
new ExtensionGenerator(descriptor->extension(i), options));
}
+
+ num_required_fields_ = 0;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (descriptor->field(i)->is_required()) {
+ ++num_required_fields_;
+ }
+ }
}
MessageGenerator::~MessageGenerator() {}
@@ -360,8 +429,13 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
if (field->is_repeated()) {
printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
- } else {
+ } else if (HasHasMethod(field)) {
printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
+ } else if (HasPrivateHasMethod(field)) {
+ printer->Print(vars,
+ "private:\n"
+ "inline bool has_$name$() const$deprecation$;\n"
+ "public:\n");
}
printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
@@ -410,32 +484,59 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
"}\n");
} else if (field->containing_oneof()) {
// Singular field in a oneof
+ // N.B.: Without field presence, we do not use has-bits or generate
+ // has_$name$() methods, but oneofs still have set_has_$name$().
+ // Oneofs also have has_$name$() but only as a private helper
+ // method, so that generated code is slightly cleaner (vs. comparing
+ // _oneof_case_[index] against a constant everywhere).
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"
+ "}\n");
+ printer->Print(vars,
"inline void $classname$::set_has_$name$() {\n"
" _oneof_case_[$oneof_index$] = k$field_name$;\n"
"}\n");
} else {
// Singular field.
- char buffer[kFastToBufferSize];
- vars["has_array_index"] = SimpleItoa(field->index() / 32);
- vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer);
- printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
- " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
- "}\n"
- "inline void $classname$::set_has_$name$() {\n"
- " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
- "}\n"
- "inline void $classname$::clear_has_$name$() {\n"
- " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
- "}\n"
- );
+ if (HasFieldPresence(descriptor_->file())) {
+ // N.B.: without field presence, we do not use has-bits or generate
+ // has_$name$() methods.
+ char buffer[kFastToBufferSize];
+ vars["has_array_index"] = SimpleItoa(field->index() / 32);
+ vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32),
+ buffer);
+ printer->Print(vars,
+ "inline bool $classname$::has_$name$() const {\n"
+ " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
+ "}\n"
+ "inline void $classname$::set_has_$name$() {\n"
+ " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
+ "}\n"
+ "inline void $classname$::clear_has_$name$() {\n"
+ " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
+ "}\n"
+ );
+ } else {
+ // Message fields have a has_$name$() method.
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ bool is_lazy = false;
+ if (is_lazy) {
+ printer->Print(vars,
+ "inline bool $classname$::has_$name$() const {\n"
+ " return !$name$_.IsCleared();\n"
+ "}\n");
+ } else {
+ printer->Print(vars,
+ "inline bool $classname$::has_$name$() const {\n"
+ " return $name$_ != NULL;\n"
+ "}\n");
+ }
+ }
+ }
}
// Generate clear_$name$()
@@ -457,9 +558,11 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
printer->Print("}\n");
} else {
field_generators_.get(field).GenerateClearingCode(printer);
- if (!field->is_repeated()) {
- printer->Print(vars,
- "clear_has_$name$();\n");
+ if (HasFieldPresence(descriptor_->file())) {
+ if (!field->is_repeated()) {
+ printer->Print(vars,
+ "clear_has_$name$();\n");
+ }
}
}
@@ -553,26 +656,41 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(
- "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
- " return _unknown_fields_;\n"
- "}\n"
- "\n"
- "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
- " return &_unknown_fields_;\n"
- "}\n"
- "\n");
- } else {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
+ " return _internal_metadata_.unknown_fields();\n"
+ "}\n"
+ "\n"
+ "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
+ " return _internal_metadata_.mutable_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");
+ }
+ }
+
+ // N.B.: We exclude GetArena() when arena support is disabled, falling back on
+ // MessageLite's implementation which returns NULL rather than generating our
+ // own method which returns NULL, in order to reduce code size.
+ if (SupportsArenas(descriptor_)) {
+ // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a
+ // MessageLite* (e.g., in RepeatedField::AddAllocated()).
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");
+ "inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }\n"
+ "inline void* GetMaybeArenaPointer() const {\n"
+ " return MaybeArenaPtr();\n"
+ "}\n");
}
// Only generate this member if it's not disabled.
@@ -628,12 +746,18 @@ GenerateClassDefinition(io::Printer* printer) {
}
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(vars,
+ "void UnsafeArenaSwap($classname$* other);\n");
+ }
printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
"// implements Message ----------------------------------------------\n"
"\n"
- "$classname$* New() const;\n");
+ "inline $classname$* New() const { return New(NULL); }\n"
+ "\n"
+ "$classname$* New(::google::protobuf::Arena* arena) const;\n");
if (HasGeneratedMethods(descriptor_->file())) {
if (HasDescriptorMethods(descriptor_->file())) {
@@ -699,7 +823,41 @@ GenerateClassDefinition(io::Printer* printer) {
"void SharedCtor();\n"
"void SharedDtor();\n"
"void SetCachedSize(int size) const;\n"
- "public:\n");
+ "void InternalSwap($classname$* other);\n",
+ "classname", classname_);
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "protected:\n"
+ "explicit $classname$(::google::protobuf::Arena* arena);\n"
+ "private:\n"
+ "static void ArenaDtor(void* object);\n"
+ "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n",
+ "classname", classname_);
+ }
+
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "private:\n"
+ "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
+ " return _internal_metadata_.arena();\n"
+ "}\n"
+ "inline void* MaybeArenaPtr() const {\n"
+ " return _internal_metadata_.raw_arena_ptr();\n"
+ "}\n"
+ "public:\n"
+ "\n");
+ } else {
+ printer->Print(
+ "private:\n"
+ "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
+ " return _arena_ptr_;\n"
+ "}\n"
+ "inline ::google::protobuf::Arena* MaybeArenaPtr() const {\n"
+ " return _arena_ptr_;\n"
+ "}\n"
+ "public:\n"
+ "\n");
+ }
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(
@@ -759,10 +917,18 @@ GenerateClassDefinition(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->is_repeated()) {
- printer->Print(
- "inline void set_has_$name$();\n",
- "name", FieldName(descriptor_->field(i)));
- if (!descriptor_->field(i)->containing_oneof()) {
+ // set_has_***() generated in all proto1/2 code and in oneofs (only) for
+ // messages without true field presence.
+ if (HasFieldPresence(descriptor_->file()) ||
+ descriptor_->field(i)->containing_oneof()) {
+ printer->Print(
+ "inline void set_has_$name$();\n",
+ "name", FieldName(descriptor_->field(i)));
+ }
+ // clear_has_***() generated only for non-oneof fields
+ // in proto1/2.
+ if (!descriptor_->field(i)->containing_oneof() &&
+ HasFieldPresence(descriptor_->file())) {
printer->Print(
"inline void clear_has_$name$();\n",
"name", FieldName(descriptor_->field(i)));
@@ -780,6 +946,14 @@ GenerateClassDefinition(io::Printer* printer) {
"oneof_name", descriptor_->oneof_decl(i)->name());
}
+ if (HasGeneratedMethods(descriptor_->file()) &&
+ !descriptor_->options().message_set_wire_format() &&
+ num_required_fields_ > 1) {
+ printer->Print(
+ "// helper for ByteSize()\n"
+ "int RequiredFieldsByteSizeFallback() const;\n\n");
+ }
+
// Prepare decls for _cached_size_ and _has_bits_. Their position in the
// output will be determined later.
@@ -816,23 +990,32 @@ GenerateClassDefinition(io::Printer* printer) {
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(
- "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
- "\n");
+ "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
} else {
printer->Print(
"::std::string _unknown_fields_;\n"
+ "::google::protobuf::Arena* _arena_ptr_;\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;
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "friend class ::google::protobuf::Arena;\n"
+ "typedef void InternalArenaConstructable_;\n"
+ "typedef void DestructorSkippable_;\n");
+ }
+
+ if (HasFieldPresence(descriptor_->file())) {
+ // _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:
@@ -871,7 +1054,10 @@ GenerateClassDefinition(io::Printer* printer) {
// For each oneof generate a union
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
printer->Print(
- "union $camel_oneof_name$Union {\n",
+ "union $camel_oneof_name$Union {\n"
+ // explicit empty constructor is needed when union contains
+ // ArenaStringPtr members for string fields.
+ " $camel_oneof_name$Union() {}\n",
"camel_oneof_name",
UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
printer->Indent();
@@ -1029,10 +1215,28 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
" new ::google::protobuf::internal::GeneratedMessageReflection(\n"
" $classname$_descriptor_,\n"
" $classname$::default_instance_,\n"
- " $classname$_offsets_,\n"
- " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n"
+ " $classname$_offsets_,\n");
+ if (!HasFieldPresence(descriptor_->file())) {
+ // If we don't have field presence, then _has_bits_ does not exist.
+ printer->Print(vars,
+ " -1,\n");
+ } else {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n");
+ }
+
+ // Unknown field offset: either points to the unknown field set if embedded
+ // directly, or indicates that the unknown field set is stored as part of the
+ // internal metadata if not.
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(vars,
+ " -1,\n");
+ } else {
+ printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
"$classname$, _unknown_fields_),\n");
+ }
+
if (descriptor_->extension_range_count() > 0) {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
@@ -1054,8 +1258,23 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
" ::google::protobuf::DescriptorPool::generated_pool(),\n");
printer->Print(vars,
" ::google::protobuf::MessageFactory::generated_factory(),\n");
+
printer->Print(vars,
- " sizeof($classname$));\n");
+ " sizeof($classname$),\n");
+
+ // Arena offset: either an offset to the metadata struct that contains the
+ // arena pointer and unknown field set (in a space-efficient way) if we use
+ // that implementation strategy, or an offset directly to the arena pointer if
+ // not (because e.g. we don't have an unknown field set).
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+ "$classname$, _internal_metadata_));\n");
+ } else {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+ "$classname$, _arena_));\n");
+ }
// Handle nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -1100,7 +1319,7 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
if ((descriptor_->oneof_decl_count() > 0) &&
HasDescriptorMethods(descriptor_->file())) {
printer->Print(
- "$classname$_default_oneof_instance_ = new $classname$OneofInstance;\n",
+ "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n",
"classname", classname_);
}
@@ -1312,8 +1531,10 @@ GenerateSharedConstructorCode(io::Printer* printer) {
}
}
- printer->Print(
- "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ }
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
printer->Print(
@@ -1331,6 +1552,14 @@ GenerateSharedDestructorCode(io::Printer* printer) {
"void $classname$::SharedDtor() {\n",
"classname", classname_);
printer->Indent();
+ if (SupportsArenas(descriptor_)) {
+ // Do nothing when the message is allocated in an arena.
+ printer->Print(
+ "if (GetArenaNoVirtual() != NULL) {\n"
+ " return;\n"
+ "}\n"
+ "\n");
+ }
// Write the destructors for each field except oneof members.
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
@@ -1381,19 +1610,107 @@ GenerateSharedDestructorCode(io::Printer* printer) {
}
void MessageGenerator::
+GenerateArenaDestructorCode(io::Printer* printer) {
+ // Generate the ArenaDtor() method. Track whether any fields actually produced
+ // code that needs to be called.
+ printer->Print(
+ "void $classname$::ArenaDtor(void* object) {\n",
+ "classname", classname_);
+ printer->Indent();
+
+ // This code is placed inside a static method, rather than an ordinary one,
+ // since that simplifies Arena's destructor list (ordinary function pointers
+ // rather than member function pointers). _this is the object being
+ // destructed.
+ printer->Print(
+ "$classname$* _this = reinterpret_cast< $classname$* >(object);\n"
+ // avoid an "unused variable" warning in case no fields have dtor code.
+ "(void)_this;\n",
+ "classname", classname_);
+
+ bool need_registration = false;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (field_generators_.get(descriptor_->field(i))
+ .GenerateArenaDestructorCode(printer)) {
+ need_registration = true;
+ }
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+
+ if (need_registration) {
+ printer->Print(
+ "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
+ " if (arena != NULL) {"
+ " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
+ " }\n"
+ "}\n",
+ "classname", classname_);
+ } else {
+ printer->Print(
+ "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
+ "}\n",
+ "classname", classname_);
+ }
+}
+
+void MessageGenerator::
GenerateStructors(io::Printer* printer) {
string superclass = SuperClassName(descriptor_);
+ string initializer_with_arena;
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ initializer_with_arena = "_internal_metadata_(arena)";
+ } else {
+ initializer_with_arena = "_arena_ptr_(arena)";
+ }
+ if (descriptor_->extension_range_count() > 0) {
+ initializer_with_arena = string("\n _extensions_(arena)") +
+ (!initializer_with_arena.empty() ? ", " : "") + initializer_with_arena;
+ } else {
+ initializer_with_arena = "\n " + initializer_with_arena;
+ }
+
+ // Initialize member variables with arena constructor.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ bool has_arena_constructor = descriptor_->field(i)->is_repeated();
+ if (has_arena_constructor) {
+ initializer_with_arena += string(",\n ") +
+ FieldName(descriptor_->field(i)) + string("_(arena)");
+ }
+ }
+ initializer_with_arena = superclass + "()" +
+ (!initializer_with_arena.empty() ? "," : " ") + initializer_with_arena;
+
+ string initializer_null;
+ initializer_null = (UseUnknownFieldSet(descriptor_->file()) ?
+ ", _internal_metadata_(NULL) " : ", _arena_ptr_(NULL)");
- // Generate the default constructor.
printer->Print(
- "$classname$::$classname$()\n"
- " : $superclass$() {\n"
- " SharedCtor();\n"
- " // @@protoc_insertion_point(constructor:$full_name$)\n"
- "}\n",
- "classname", classname_,
- "superclass", superclass,
- "full_name", descriptor_->full_name());
+ "$classname$::$classname$()\n"
+ " : $superclass$() $initializer$ {\n"
+ " SharedCtor();\n"
+ " // @@protoc_insertion_point(constructor:$full_name$)\n"
+ "}\n",
+ "classname", classname_,
+ "superclass", superclass,
+ "full_name", descriptor_->full_name(),
+ "initializer", initializer_null);
+
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "\n"
+ "$classname$::$classname$(::google::protobuf::Arena* arena)\n"
+ " : $initializer$ {\n"
+ " SharedCtor();\n"
+ " RegisterArenaDtor(arena);\n"
+ " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
+ "}\n",
+ "initializer", initializer_with_arena,
+ "classname", classname_,
+ "superclass", superclass,
+ "full_name", descriptor_->full_name());
+ }
printer->Print(
"\n"
@@ -1441,7 +1758,17 @@ GenerateStructors(io::Printer* printer) {
// Generate the copy constructor.
printer->Print(
"$classname$::$classname$(const $classname$& from)\n"
- " : $superclass$() {\n"
+ " : $superclass$()",
+ "classname", classname_,
+ "superclass", superclass,
+ "full_name", descriptor_->full_name());
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ ",\n _internal_metadata_(NULL) {\n");
+ } else if (!UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(",\n _arena_ptr_(NULL) {\n");
+ }
+ printer->Print(
" SharedCtor();\n"
" MergeFrom(from);\n"
" // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
@@ -1467,6 +1794,11 @@ GenerateStructors(io::Printer* printer) {
// Generate the shared destructor code.
GenerateSharedDestructorCode(printer);
+ // Generate the arena-specific destructor code.
+ if (SupportsArenas(descriptor_)) {
+ GenerateArenaDestructorCode(printer);
+ }
+
// Generate SetCachedSize.
printer->Print(
"void $classname$::SetCachedSize(int size) const {\n"
@@ -1512,11 +1844,23 @@ GenerateStructors(io::Printer* printer) {
"\n",
"classname", classname_);
- printer->Print(
- "$classname$* $classname$::New() const {\n"
- " return new $classname$;\n"
- "}\n",
- "classname", classname_);
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
+ " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n"
+ "}\n",
+ "classname", classname_);
+ } else {
+ printer->Print(
+ "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
+ " $classname$* n = new $classname$;\n"
+ " if (arena != NULL) {\n"
+ " arena->Own(n);\n"
+ " }\n"
+ " return n;\n"
+ "}\n",
+ "classname", classname_);
+ }
}
@@ -1616,16 +1960,19 @@ GenerateClear(io::Printer* printer) {
const string& memsets = memsets_for_chunk[i / 8];
uint32 mask = fields_mask_for_chunk[i / 8];
int count = popcnt(mask);
+ GOOGLE_DCHECK_GE(count, 1);
if (count == 1 ||
(count <= 4 && count == memset_field_count_for_chunk[i / 8])) {
// No "if" here because the chunk is trivial.
} else {
- printer->Print(
- "if (_has_bits_[$index$ / 32] & $mask$) {\n",
- "index", SimpleItoa(i / 8 * 8),
- "mask", SimpleItoa(mask));
- printer->Indent();
- chunk_block_in_progress = true;
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (_has_bits_[$index$ / 32] & $mask$) {\n",
+ "index", SimpleItoa(i / 8 * 8),
+ "mask", SimpleItoa(mask));
+ printer->Indent();
+ chunk_block_in_progress = true;
+ }
}
printer->Print(memsets.c_str());
}
@@ -1639,14 +1986,18 @@ GenerateClear(io::Printer* printer) {
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
- if (should_check_bit) {
+ bool have_enclosing_if = false;
+ if (should_check_bit &&
+ // If no field presence, then always clear strings/messages as well.
+ HasFieldPresence(descriptor_->file())) {
printer->Print("if (has_$name$()) {\n", "name", fieldname);
printer->Indent();
+ have_enclosing_if = true;
}
field_generators_.get(field).GenerateClearingCode(printer);
- if (should_check_bit) {
+ if (have_enclosing_if) {
printer->Outdent();
printer->Print("}\n");
}
@@ -1678,16 +2029,22 @@ GenerateClear(io::Printer* printer) {
"oneof_name", descriptor_->oneof_decl(i)->name());
}
- // Step 5: Everything else.
- printer->Print(
- "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
-
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (HasFieldPresence(descriptor_->file())) {
+ // Step 5: Everything else.
printer->Print(
- "mutable_unknown_fields()->Clear();\n");
- } else {
- printer->Print(
- "mutable_unknown_fields()->clear();\n");
+ "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "if (_internal_metadata_.have_unknown_fields()) {\n"
+ " mutable_unknown_fields()->Clear();\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "mutable_unknown_fields()->clear();\n");
+ }
}
printer->Outdent();
@@ -1748,12 +2105,42 @@ GenerateOneofClear(io::Printer* printer) {
void MessageGenerator::
GenerateSwap(io::Printer* printer) {
- // Generate the Swap member function.
- printer->Print("void $classname$::Swap($classname$* other) {\n",
+ if (SupportsArenas(descriptor_)) {
+ // Generate the Swap member function. This is a lightweight wrapper around
+ // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory
+ // ownership situation: swapping across arenas or between an arena and a
+ // heap requires copying.
+ printer->Print(
+ "void $classname$::Swap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n"
+ " InternalSwap(other);\n"
+ " } else {\n"
+ " $classname$ temp;\n"
+ " temp.MergeFrom(*this);\n"
+ " CopyFrom(*other);\n"
+ " other->CopyFrom(temp);\n"
+ " }\n"
+ "}\n"
+ "void $classname$::UnsafeArenaSwap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n"
+ " InternalSwap(other);\n"
+ "}\n",
+ "classname", classname_);
+ } else {
+ printer->Print(
+ "void $classname$::Swap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ " InternalSwap(other);\n"
+ "}\n",
+ "classname", classname_);
+ }
+
+ // Generate the UnsafeArenaSwap member function.
+ printer->Print("void $classname$::InternalSwap($classname$* other) {\n",
"classname", classname_);
printer->Indent();
- printer->Print("if (other != this) {\n");
- printer->Indent();
if (HasGeneratedMethods(descriptor_->file())) {
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -1769,15 +2156,25 @@ GenerateSwap(io::Printer* printer) {
"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 (HasFieldPresence(descriptor_->file())) {
+ 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 (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
+ } else {
+ printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n");
+ }
} else {
- printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n");
+ // Still swap internal_metadata as it may contain more than just
+ // unknown fields.
+ printer->Print(
+ "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
}
printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
if (descriptor_->extension_range_count() > 0) {
@@ -1789,8 +2186,6 @@ GenerateSwap(io::Printer* printer) {
printer->Outdent();
printer->Print("}\n");
- printer->Outdent();
- printer->Print("}\n");
}
void MessageGenerator::
@@ -1886,33 +2281,48 @@ GenerateMergeFrom(io::Printer* printer) {
const FieldDescriptor* field = descriptor_->field(i);
if (!field->is_repeated() && !field->containing_oneof()) {
- // See above in GenerateClear for an explanation of this.
- if (i / 8 != last_index / 8 || last_index < 0) {
- if (last_index >= 0) {
- printer->Outdent();
- printer->Print("}\n");
+ if (HasFieldPresence(descriptor_->file())) {
+ // See above in GenerateClear for an explanation of this.
+ if (i / 8 != last_index / 8 || last_index < 0) {
+ if (last_index >= 0) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Print(
+ "if (from._has_bits_[$index$ / 32] & "
+ "(0xffu << ($index$ % 32))) {\n",
+ "index", SimpleItoa(field->index()));
+ printer->Indent();
}
- printer->Print(
- "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
- "index", SimpleItoa(field->index()));
- printer->Indent();
}
last_index = i;
- printer->Print(
- "if (from.has_$name$()) {\n",
- "name", FieldName(field));
- printer->Indent();
+ bool have_enclosing_if = false;
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (from.has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ have_enclosing_if = true;
+ } else {
+ // Merge semantics without true field presence: primitive fields are
+ // merged only if non-zero (numeric) or non-empty (string).
+ have_enclosing_if = EmitFieldNonDefaultCondition(
+ printer, "from.", field);
+ }
field_generators_.get(field).GenerateMergingCode(printer);
- printer->Outdent();
- printer->Print("}\n");
+ if (have_enclosing_if) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
}
}
- if (last_index >= 0) {
+ if (HasFieldPresence(descriptor_->file()) &&
+ last_index >= 0) {
printer->Outdent();
printer->Print("}\n");
}
@@ -1921,12 +2331,16 @@ GenerateMergeFrom(io::Printer* printer) {
printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
}
- 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");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "if (from._internal_metadata_.have_unknown_fields()) {\n"
+ " mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "mutable_unknown_fields()->append(from.unknown_fields());\n");
+ }
}
printer->Outdent();
@@ -2171,24 +2585,33 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
}
printer->Print(") {\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
- PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
- " mutable_unknown_fields()));\n",
- // Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
- " mutable_unknown_fields()));\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ PrintHandlingOptionalStaticInitializers(
+ descriptor_->file(), printer,
+ // With static initializers.
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " mutable_unknown_fields()));\n",
+ // Without.
+ " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+ " mutable_unknown_fields()));\n");
+ } else {
+ PrintHandlingOptionalStaticInitializers(
+ descriptor_->file(), printer,
+ // With static initializers.
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " &unknown_fields_stream));\n",
+ // Without.
+ " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+ " &unknown_fields_stream));\n");
+ }
} else {
PrintHandlingOptionalStaticInitializers(
descriptor_->file(), printer,
// With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
- " &unknown_fields_stream));\n",
+ " DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
// Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
- " &unknown_fields_stream));\n");
+ " DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
}
printer->Print(
" continue;\n"
@@ -2196,14 +2619,19 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
// We really don't recognize this tag. Skip it.
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(
- "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
- " input, tag, mutable_unknown_fields()));\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ 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(\n"
+ " input, tag, &unknown_fields_stream));\n");
+ }
} else {
printer->Print(
- "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
- " input, tag, &unknown_fields_stream));\n");
+ "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
}
if (descriptor_->field_count() > 0) {
@@ -2232,11 +2660,15 @@ void MessageGenerator::GenerateSerializeOneField(
io::Printer* printer, const FieldDescriptor* field, bool to_array) {
PrintFieldComment(printer, field);
- if (!field->is_repeated()) {
+ bool have_enclosing_if = false;
+ if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) {
printer->Print(
"if (has_$name$()) {\n",
"name", FieldName(field));
printer->Indent();
+ have_enclosing_if = true;
+ } else if (!HasFieldPresence(descriptor_->file())) {
+ have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
}
if (to_array) {
@@ -2246,7 +2678,7 @@ void MessageGenerator::GenerateSerializeOneField(
field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
}
- if (!field->is_repeated()) {
+ if (have_enclosing_if) {
printer->Outdent();
printer->Print("}\n");
}
@@ -2386,28 +2818,69 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
}
}
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print("if (!unknown_fields().empty()) {\n");
- printer->Indent();
- if (to_array) {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n");
+ printer->Indent();
+ if (to_array) {
+ printer->Print(
+ "target = "
+ "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
+ " unknown_fields(), target);\n");
+ } else {
+ printer->Print(
+ "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
+ " unknown_fields(), output);\n");
+ }
+ printer->Outdent();
+
printer->Print(
- "target = "
- "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
- " unknown_fields(), target);\n");
+ "}\n");
} else {
printer->Print(
- "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
- " unknown_fields(), output);\n");
+ "output->WriteRaw(unknown_fields().data(),\n"
+ " unknown_fields().size());\n");
}
- printer->Outdent();
+ }
+}
- printer->Print(
- "}\n");
- } else {
- printer->Print(
- "output->WriteRaw(unknown_fields().data(),\n"
- " unknown_fields().size());\n");
+static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) {
+ vector<uint32> result;
+ uint32 mask = 0;
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (i > 0 && i % 32 == 0) {
+ result.push_back(mask);
+ mask = 0;
+ }
+ if (desc->field(i)->is_required()) {
+ mask |= (1 << (i & 31));
+ }
+ }
+ if (mask != 0) {
+ result.push_back(mask);
}
+ return result;
+}
+
+// Create an expression that evaluates to
+// "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
+// masks is allowed to be shorter than _has_bits_, but at least one element of
+// masks must be non-zero.
+static string ConditionalToCheckBitmasks(const vector<uint32>& masks) {
+ vector<string> parts;
+ for (int i = 0; i < masks.size(); i++) {
+ if (masks[i] == 0) continue;
+ char buffer[kFastToBufferSize];
+ FastHex32ToBuffer(masks[i], buffer);
+ string m = StrCat("0x", buffer);
+ // Each xor evaluates to 0 if the expected bits are present.
+ parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")"));
+ }
+ GOOGLE_CHECK(!parts.empty());
+ // If we have multiple parts, each expected to be 0, then bitwise-or them.
+ string result = parts.size() == 1 ? parts[0] :
+ StrCat("(", Join(parts, "\n | "), ")");
+ return result + " == 0";
}
void MessageGenerator::
@@ -2420,8 +2893,10 @@ GenerateByteSize(io::Printer* printer) {
"classname", classname_);
GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
printer->Print(
+ "if (_internal_metadata_.have_unknown_fields()) {\n"
" total_size += ::google::protobuf::internal::WireFormat::\n"
- " ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
+ " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"
+ "}\n");
printer->Print(
" GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
" _cached_size_ = total_size;\n"
@@ -2431,6 +2906,33 @@ GenerateByteSize(io::Printer* printer) {
return;
}
+ if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
+ // Emit a function (rarely used, we hope) that handles the required fields
+ // by checking for each one individually.
+ printer->Print(
+ "int $classname$::RequiredFieldsByteSizeFallback() const {\n",
+ "classname", classname_);
+ printer->Indent();
+ printer->Print("int total_size = 0;\n");
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->is_required()) {
+ printer->Print("\n"
+ "if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ PrintFieldComment(printer, field);
+ field_generators_.get(field).GenerateByteSize(printer);
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ printer->Print("\n"
+ "return total_size;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
printer->Print(
"int $classname$::ByteSize() const {\n",
"classname", classname_);
@@ -2439,45 +2941,121 @@ GenerateByteSize(io::Printer* printer) {
"int total_size = 0;\n"
"\n");
- int last_index = -1;
+ // Handle required fields (if any). We expect all of them to be
+ // present, so emit one conditional that checks for that. If they are all
+ // present then the fast path executes; otherwise the slow path executes.
+ if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
+ // The fast path works if all required fields are present.
+ vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_);
+ printer->Print((string("if (") +
+ ConditionalToCheckBitmasks(masks_for_has_bits) +
+ ") { // All required fields are present.\n").c_str());
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!field->is_required()) continue;
+ PrintFieldComment(printer, field);
+ field_generators_.get(field).GenerateByteSize(printer);
+ printer->Print("\n");
+ }
+ printer->Outdent();
+ printer->Print("} else {\n" // the slow path
+ " total_size += RequiredFieldsByteSizeFallback();\n"
+ "}\n");
+ } else {
+ // num_required_fields_ <= 1: no need to be tricky
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!field->is_required()) continue;
+ PrintFieldComment(printer, field);
+ printer->Print("if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ field_generators_.get(field).GenerateByteSize(printer);
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ // Handle optional fields (worry below about repeateds, oneofs, etc.).
+ // These are handled in chunks of 8. The first chunk is
+ // the non-requireds-non-repeateds-non-unions-non-extensions 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.
+ 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_required() && !field->is_repeated() &&
+ !field->containing_oneof()) {
+ fields_mask_for_chunk[i / 8] |= static_cast<uint32>(1) << (i % 32);
+ }
+ }
- if (!field->is_repeated() && !field->containing_oneof()) {
+ int last_index = -1;
+ bool chunk_block_in_progress = false;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!field->is_required() && !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.
- if ((i / 8) != (last_index / 8) ||
- last_index < 0) {
- if (last_index >= 0) {
+ 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;
+ }
+ // Start chunk.
+ uint32 mask = fields_mask_for_chunk[i / 8];
+ int count = popcnt(mask);
+ GOOGLE_DCHECK_GE(count, 1);
+ if (count == 1) {
+ // No "if" here because the chunk is trivial.
+ } else {
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (_has_bits_[$index$ / 32] & $mask$) {\n",
+ "index", SimpleItoa(i),
+ "mask", SimpleItoa(mask));
+ printer->Indent();
+ chunk_block_in_progress = true;
+ }
}
- printer->Print(
- "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
- "index", SimpleItoa(field->index()));
- printer->Indent();
}
last_index = i;
PrintFieldComment(printer, field);
- printer->Print(
- "if (has_$name$()) {\n",
- "name", FieldName(field));
- printer->Indent();
+ bool have_enclosing_if = false;
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ have_enclosing_if = true;
+ } else {
+ // Without field presence: field is serialized only if it has a
+ // non-default value.
+ have_enclosing_if = EmitFieldNonDefaultCondition(
+ printer, "this->", field);
+ }
field_generators_.get(field).GenerateByteSize(printer);
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n");
+ if (have_enclosing_if) {
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+ }
}
}
- if (last_index >= 0) {
+ if (chunk_block_in_progress) {
printer->Outdent();
printer->Print("}\n");
}
@@ -2532,19 +3110,19 @@ GenerateByteSize(io::Printer* printer) {
"\n");
}
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print("if (!unknown_fields().empty()) {\n");
- printer->Indent();
- printer->Print(
- "total_size +=\n"
- " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
- " unknown_fields());\n");
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(
- "total_size += unknown_fields().size();\n"
- "\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "if (_internal_metadata_.have_unknown_fields()) {\n"
+ " total_size +=\n"
+ " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
+ " unknown_fields());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "total_size += unknown_fields().size();\n"
+ "\n");
+ }
}
// We update _cached_size_ even though this is a const method. In theory,
@@ -2569,27 +3147,29 @@ GenerateIsInitialized(io::Printer* printer) {
"classname", classname_);
printer->Indent();
- // Check that all required fields in this message are set. We can do this
- // most efficiently by checking 32 "has bits" at a time.
- int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
- for (int i = 0; i < has_bits_array_size; i++) {
- uint32 mask = 0;
- for (int bit = 0; bit < 32; bit++) {
- int index = i * 32 + bit;
- if (index >= descriptor_->field_count()) break;
- const FieldDescriptor* field = descriptor_->field(index);
-
- if (field->is_required()) {
- mask |= 1 << bit;
+ if (HasFieldPresence(descriptor_->file())) {
+ // Check that all required fields in this message are set. We can do this
+ // most efficiently by checking 32 "has bits" at a time.
+ int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
+ for (int i = 0; i < has_bits_array_size; i++) {
+ uint32 mask = 0;
+ for (int bit = 0; bit < 32; bit++) {
+ int index = i * 32 + bit;
+ if (index >= descriptor_->field_count()) break;
+ const FieldDescriptor* field = descriptor_->field(index);
+
+ if (field->is_required()) {
+ mask |= 1 << bit;
+ }
}
- }
- if (mask != 0) {
- char buffer[kFastToBufferSize];
- printer->Print(
- "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
- "i", SimpleItoa(i),
- "mask", FastHex32ToBuffer(mask, buffer));
+ if (mask != 0) {
+ char buffer[kFastToBufferSize];
+ printer->Print(
+ "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
+ "i", SimpleItoa(i),
+ "mask", FastHex32ToBuffer(mask, buffer));
+ }
}
}
@@ -2607,7 +3187,7 @@ GenerateIsInitialized(io::Printer* printer) {
"name", FieldName(field));
} else {
if (field->options().weak()) {
- // For weak fields, use the data member (google::protobuf::Message*) instead
+ // 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(
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index bfd3cec1..a781c234 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
#include <google/protobuf/compiler/cpp/cpp_field.h>
@@ -58,8 +61,7 @@ class ExtensionGenerator; // extension.h
class MessageGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- explicit MessageGenerator(const Descriptor* descriptor,
- const Options& options);
+ MessageGenerator(const Descriptor* descriptor, const Options& options);
~MessageGenerator();
// Header stuff.
@@ -130,6 +132,8 @@ class MessageGenerator {
void GenerateSharedConstructorCode(io::Printer* printer);
// Generate the shared destructor code.
void GenerateSharedDestructorCode(io::Printer* printer);
+ // Generate the arena-specific destructor code.
+ void GenerateArenaDestructorCode(io::Printer* printer);
// Generate standard Message methods.
void GenerateClear(io::Printer* printer);
@@ -162,6 +166,7 @@ class MessageGenerator {
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
+ int num_required_fields_;
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 6ac15a5a..da1ec60b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -86,6 +86,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline $type$* mutable_$name$()$deprecation$;\n"
"inline $type$* $release_name$()$deprecation$;\n"
"inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "inline $type$* unsafe_arena_release_$name$()$deprecation$;\n"
+ "inline void unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$)$deprecation$;\n");
+ }
}
void MessageFieldGenerator::
@@ -101,36 +107,157 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
// Without.
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
- printer->Print(variables_,
- "}\n"
- "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"
- " clear_has_$name$();\n"
- " $type$* temp = $name$_;\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " delete $name$_;\n"
- " $name$_ = $name$;\n"
- " if ($name$) {\n"
- " set_has_$name$();\n"
- " } else {\n"
- " clear_has_$name$();\n"
- " }\n"
- " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
- "}\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " if ($name$_ == NULL) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ }
+ printer->Print(variables_, " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline $type$* $classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " if (GetArenaNoVirtual() != NULL) {\n"
+ " if ($name$_ == NULL) {\n"
+ " return NULL;\n"
+ " } else {\n"
+ " $type$* temp = new $type$;\n"
+ " temp->MergeFrom(*$name$_);\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ " } else {\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ "}\n"
+ "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " $clear_hasbit$\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " if ($name$ != NULL) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ // If we're on an arena and the incoming message is not, simply Own() it
+ // rather than copy to the arena -- either way we need a heap dealloc,
+ // so we might as well defer it. Otherwise, if incoming message is on a
+ // different ownership domain (specific arena, or the heap) than we are,
+ // copy to our arena (or heap, as the case may be).
+ printer->Print(variables_,
+ " if (GetArenaNoVirtual() != NULL && \n"
+ " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " } else if (GetArenaNoVirtual() !=\n"
+ " ::google::protobuf::Arena::GetArena($name$)) {\n"
+ " $type$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ } else {
+ printer->Print(variables_,
+ " if (GetArenaNoVirtual() != NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$) {\n"
+ // If we're not on an arena, free whatever we were holding before.
+ // (If we are on arena, we can just forget the earlier pointer.)
+ " if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
+ ":$full_name$)\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " if ($name$_ == NULL) {\n"
+ " $name$_ = new $type$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline $type$* $classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " delete $name$_;\n");
+
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
+ " $type$* new_$name$ = new $type$;\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ }
}
void MessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
+ if (!HasFieldPresence(descriptor_->file())) {
+ // If we don't have has-bits, message presence is indicated only by ptr !=
+ // NULL. Thus on clear, we need to delete the object.
+ printer->Print(variables_,
+ "if ($name$_ != NULL) delete $name$_;\n"
+ "$name$_ = NULL;\n");
+ } else {
+ printer->Print(variables_,
+ "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
+ }
}
void MessageFieldGenerator::
@@ -198,43 +325,165 @@ 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");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "inline const $type$& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\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");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " $oneof_prefix$$name$_ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ " $oneof_prefix$$name$_ = \n"
+ " ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ }
+ printer->Print(variables_,
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $oneof_prefix$$name$_;\n"
+ "}\n"
+ "inline $type$* $classname$::$release_name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " if (GetArenaNoVirtual() != NULL) {\n"
+ // N.B.: safe to use the underlying field pointer here because we are sure
+ // that it is non-NULL (because has_$name$() returned true).
+ " $type$* temp = new $type$;\n"
+ " temp->MergeFrom(*$oneof_prefix$$name$_);\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " } else {\n"
+ " $type$* temp = $oneof_prefix$$name$_;\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline $type$* $classname$::unsafe_arena_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");
+
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ // If incoming message is on the heap and we are on an arena, just Own()
+ // it (see above). If it's on a different arena than we are or one of us
+ // is on the heap, we make a copy to our arena/heap.
+ " if (GetArenaNoVirtual() != NULL &&\n"
+ " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " } else if (GetArenaNoVirtual() !=\n"
+ " ::google::protobuf::Arena::GetArena($name$)) {\n"
+ " $type$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ } else {
+ printer->Print(variables_,
+ " if (GetArenaNoVirtual() != NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_ = $name$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "$type$* $name$) {\n"
+ // We rely on the oneof clear method to free the earlier contents of this
+ // oneof. We can directly use the pointer we're given to set the new
+ // value.
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_ = $name$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+ "$full_name$)\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "inline const $type$& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\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"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\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");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " if ($name$->GetArena() != NULL) {\n"
+ " $type$* new_$name$ = new $type$;\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_ = $name$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\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");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $oneof_prefix$$name$_;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "delete $oneof_prefix$$name$_;\n");
+ }
}
void MessageOneofFieldGenerator::
@@ -318,7 +567,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 2dbf14ce..26cefb2e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -35,6 +35,9 @@
// worth.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
@@ -69,6 +72,100 @@ class TestGenerator : public CodeGenerator {
TryInsert("test.pb.cc", "includes", context);
TryInsert("test.pb.cc", "namespace_scope", context);
TryInsert("test.pb.cc", "global_scope", context);
+
+ // Check field accessors for an optional int32:
+ TryInsert("test.pb.h", "field_get:foo.Bar.optInt", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.optInt", context);
+
+ // Check field accessors for a repeated int32:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedInt", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedInt", context);
+
+ // Check field accessors for a required string:
+ TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
+ context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
+
+ // Check field accessors for a repeated string:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
+
+ // Check field accessors for an int inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfInt", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfInt", context);
+
+ // Check field accessors for a string inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
+
+ // Check field accessors for an optional message:
+ TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.optMessage", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.optMessage", context);
+
+ // Check field accessors for a repeated message:
+ TryInsert("test.pb.h", "field_add:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_list:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedMessage",
+ context);
+
+ // Check field accessors for a message inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfMessage", context);
+
+ // Check field accessors for an optional enum:
+ TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.optEnum", context);
+
+ // Check field accessors for a repeated enum:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_add:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_list:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedEnum", context);
+
+ // Check field accessors for an enum inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfEnum", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfEnum", context);
+
+ // Check field accessors for a required cord:
+ TryInsert("test.pb.h", "field_get:foo.Bar.requiredCord", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.requiredCord", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredCord", context);
+
+ // Check field accessors for a repeated cord:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_add:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_list:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedCord", context);
+
+ // Check field accessors for a cord inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfCord", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfCord", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfCord", context);
+
return true;
}
@@ -88,8 +185,39 @@ TEST(CppPluginTest, PluginTest) {
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
"syntax = \"proto2\";\n"
"package foo;\n"
+ "\n"
+ "enum Thud { VALUE = 0; }\n"
+ "\n"
"message Bar {\n"
" message Baz {}\n"
+ " optional int32 optInt = 1;\n"
+ " repeated int32 repeatedInt = 2;\n"
+ "\n"
+ " required string requiredString = 3;\n"
+ " repeated string repeatedString = 4;\n"
+ "\n"
+ " optional Baz optMessage = 6;\n"
+ " repeated Baz repeatedMessage = 7;\n"
+ "\n"
+ " optional Thud optEnum = 8;\n"
+ " repeated Thud repeatedEnum = 9;\n"
+ "\n"
+ " required string requiredCord = 10 [\n"
+ " ctype = CORD\n"
+ " ];\n"
+ " repeated string repeatedCord = 11 [\n"
+ " ctype = CORD\n"
+ " ];\n"
+ "\n"
+ " oneof Qux {\n"
+ " int64 oneOfInt = 20;\n"
+ " string oneOfString = 21;\n"
+ " Baz oneOfMessage = 22;\n"
+ " Thud oneOfEnum = 23;"
+ " string oneOfCord = 24 [\n"
+ " ctype = CORD\n"
+ " ];\n"
+ " }\n"
"}\n",
true));
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 44290a31..9a2c930e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -129,7 +129,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return $name$_;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
- " set_has_$name$();\n"
+ " $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
@@ -161,7 +161,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" $type$, $wire_format_field_type$>(\n"
" input, &$name$_)));\n"
- "set_has_$name$();\n");
+ "$set_hasbit$\n");
}
void PrimitiveFieldGenerator::
@@ -207,6 +207,7 @@ void PrimitiveOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_;\n"
" }\n"
@@ -218,6 +219,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" set_has_$name$();\n"
" }\n"
" $oneof_prefix$$name$_ = value;\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
@@ -330,7 +332,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 180d236b..a2a8c81c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -52,9 +52,14 @@ void SetStringVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["default_length"] =
SimpleItoa(descriptor->default_value_string().length());
- (*variables)["default_variable"] = descriptor->default_value_string().empty()
- ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
- : "_default_" + FieldName(descriptor) + "_";
+ string default_variable_string =
+ descriptor->default_value_string().empty()
+ ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
+ : "_default_" + FieldName(descriptor) + "_";
+ (*variables)["default_variable"] = default_variable_string;
+ (*variables)["default_value_init"] =
+ descriptor->default_value_string().empty()
+ ? "" : "*" + default_variable_string;
(*variables)["pointer_type"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
// NOTE: Escaped here to unblock proto1->proto2 migration.
@@ -63,6 +68,8 @@ void SetStringVariables(const FieldDescriptor* descriptor,
SafeFunctionName(descriptor->containing_type(),
descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
+
+ (*variables)["string_piece"] = "::std::string";
}
} // namespace
@@ -80,7 +87,19 @@ StringFieldGenerator::~StringFieldGenerator() {}
void StringFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
- printer->Print(variables_, "::std::string* $name$_;\n");
+ // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
+ // string fields, even when SupportArenas(descriptor_) == false. Why?
+ // The simple answer is to avoid unmaintainable complexity. The reflection
+ // code assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
+ // string*, except for the pointer tags and related ownership semantics. We
+ // could modify the runtime code to use string* for the not-supporting-arenas
+ // case, but this would require a way to detect which type of class was
+ // generated (adding overhead and complexity to GeneratedMessageReflection)
+ // and littering the runtime code paths with conditionals. It's simpler to
+ // stick with this but use lightweight accessors that assume arena == NULL.
+ // There should be very little overhead anyway because it's just a tagged
+ // pointer in-memory.
+ printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n");
}
void StringFieldGenerator::
@@ -125,6 +144,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline ::std::string* mutable_$name$()$deprecation$;\n"
"inline ::std::string* $release_name$()$deprecation$;\n"
"inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "inline ::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
+ "inline void unsafe_arena_set_allocated_$name$(\n"
+ " ::std::string* $name$)$deprecation$;\n");
+ }
if (descriptor_->options().ctype() != FieldOptions::STRING) {
@@ -136,74 +161,113 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void StringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return *$name$_;\n"
- "}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
- " set_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " $name$_ = new ::std::string;\n"
- " }\n"
- " $name$_->assign(value);\n"
- " // @@protoc_insertion_point(field_set:$full_name$)\n"
- "}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
- " set_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " $name$_ = new ::std::string;\n"
- " }\n"
- " $name$_->assign(value);\n"
- " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
- "}\n"
- "inline "
- "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
- " set_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " $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"
- " if ($name$_ == $default_variable$) {\n");
- if (descriptor_->default_value_string().empty()) {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- " $name$_ = new ::std::string;\n");
+ "inline const ::std::string& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $name$_.Get($default_variable$);\n"
+ "}\n"
+ "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ " $set_hasbit$\n"
+ " $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::set_$name$(const char* value) {\n"
+ " $set_hasbit$\n"
+ " $name$_.Set($default_variable$, $string_piece$(value),\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value,\n"
+ " size_t size) {\n"
+ " $set_hasbit$\n"
+ " $name$_.Set($default_variable$, $string_piece$(\n"
+ " reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+ "}\n"
+ "inline ::std::string* $classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
+ "}\n"
+ "inline ::std::string* $classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
+ "}\n"
+ "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+ " $clear_hasbit$\n"
+ " return $name$_.UnsafeArenaRelease($default_variable$,\n"
+ " GetArenaNoVirtual());\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if ($name$ != NULL) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " $name$_.SetAllocated($default_variable$, $name$,\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ " ::std::string* $name$) {\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+ " if ($name$ != NULL) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " $set_hasbit$\n"
+ " $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
+ " $name$, GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
} else {
+ // No-arena case.
printer->Print(variables_,
- " $name$_ = new ::std::string(*$default_variable$);\n");
+ "inline const ::std::string& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $name$_.GetNoArena($default_variable$);\n"
+ "}\n"
+ "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ " $set_hasbit$\n"
+ " $name$_.SetNoArena($default_variable$, value);\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::set_$name$(const char* value) {\n"
+ " $set_hasbit$\n"
+ " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value, "
+ "size_t size) {\n"
+ " $set_hasbit$\n"
+ " $name$_.SetNoArena($default_variable$,\n"
+ " $string_piece$(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_hasbit$\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_.MutableNoArena($default_variable$);\n"
+ "}\n"
+ "inline ::std::string* $classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " return $name$_.ReleaseNoArena($default_variable$);\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if ($name$ != NULL) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
}
- printer->Print(variables_,
- " }\n"
- " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_;\n"
- "}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
- " clear_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " return NULL;\n"
- " } else {\n"
- " ::std::string* temp = $name$_;\n"
- " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
- " return temp;\n"
- " }\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
- " if ($name$_ != $default_variable$) {\n"
- " delete $name$_;\n"
- " }\n"
- " if ($name$) {\n"
- " set_has_$name$();\n"
- " $name$_ = $name$;\n"
- " } else {\n"
- " clear_has_$name$();\n"
- " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
- " }\n"
- " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
- "}\n");
}
void StringFieldGenerator::
@@ -217,16 +281,26 @@ GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
void StringFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- if (descriptor_->default_value_string().empty()) {
- printer->Print(variables_,
- "if ($name$_ != $default_variable$) {\n"
- " $name$_->clear();\n"
- "}\n");
+ // Two-dimension specialization here: supporting arenas or not, and default
+ // value is the empty string or not. Complexity here ensures the minimal
+ // number of branches / amount of extraneous code at runtime (given that the
+ // below methods are inlined one-liners)!
+ if (SupportsArenas(descriptor_)) {
+ if (descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n");
+ }
} else {
- printer->Print(variables_,
- "if ($name$_ != $default_variable$) {\n"
- " $name$_->assign(*$default_variable$);\n"
- "}\n");
+ if (descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "$name$_.ClearToEmptyNoArena($default_variable$);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.ClearToDefaultNoArena($default_variable$);\n");
+ }
}
}
@@ -237,21 +311,24 @@ GenerateMergingCode(io::Printer* printer) const {
void StringFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+ printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
}
void StringFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$_ = const_cast< ::std::string*>($default_variable$);\n");
+ "$name$_.UnsafeSetDefault($default_variable$);\n");
}
void StringFieldGenerator::
GenerateDestructorCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if ($name$_ != $default_variable$) {\n"
- " delete $name$_;\n"
- "}\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "$name$_.Destroy($default_variable$, GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.DestroyNoArena($default_variable$);\n");
+ }
}
void StringFieldGenerator::
@@ -276,13 +353,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
+
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
}
@@ -294,7 +372,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
@@ -309,7 +387,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
printer->Print(variables_,
"target =\n"
@@ -338,84 +416,186 @@ 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()) {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- " $oneof_prefix$$name$_ = new ::std::string;\n");
+ "inline const ::std::string& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " if (has_$name$()) {\n"
+ " return $oneof_prefix$$name$_.Get($default_variable$);\n"
+ " }\n"
+ " return *$default_variable$;\n"
+ "}\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$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.Set($default_variable$, value,\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\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$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.Set($default_variable$,\n"
+ " $string_piece$(value), GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value,\n"
+ " size_t size) {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n"
+ " reinterpret_cast<const char*>(value), size),\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+ "}\n"
+ "inline ::std::string* $classname$::mutable_$name$() {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " return $oneof_prefix$$name$_.Mutable($default_variable$,\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ "}\n"
+ "inline ::std::string* $classname$::$release_name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " return $oneof_prefix$$name$_.Release($default_variable$,\n"
+ " GetArenaNoVirtual());\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " return $oneof_prefix$$name$_.UnsafeArenaRelease(\n"
+ " $default_variable$, GetArenaNoVirtual());\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if (!has_$name$()) {\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$ != NULL) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n"
+ " GetArenaNoVirtual());\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "::std::string* $name$) {\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+ " if (!has_$name$()) {\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
+ "$name$, GetArenaNoVirtual());\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
} else {
+ // No-arena case.
printer->Print(variables_,
- " $oneof_prefix$$name$_ = new ::std::string(*$default_variable$);\n");
+ "inline const ::std::string& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " if (has_$name$()) {\n"
+ " return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
+ " }\n"
+ " return *$default_variable$;\n"
+ "}\n"
+ "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\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$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.SetNoArena($default_variable$,\n"
+ " $string_piece$(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"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.SetNoArena($default_variable$, $string_piece$(\n"
+ " reinterpret_cast<const char*>(value), size));\n"
+ " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+ "}\n"
+ "inline ::std::string* $classname$::mutable_$name$() {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
+ "}\n"
+ "inline ::std::string* $classname$::$release_name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if (!has_$name$()) {\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$ != NULL) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n"
+ " $name$);\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\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 {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "delete $oneof_prefix$$name$_;\n");
+ "$oneof_prefix$$name$_.Destroy($default_variable$,\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ "$oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n");
+ }
}
void StringOneofFieldGenerator::
@@ -425,25 +605,45 @@ GenerateSwappingCode(io::Printer* printer) const {
void StringOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
- if (!descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ " const_cast< ::google::protobuf::internal::ArenaStringPtr*>("
+ "&$classname$_default_oneof_instance_->$name$_)->UnsafeSetDefault("
+ "$default_variable$);\n");
+}
+
+void StringOneofFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- " $classname$_default_oneof_instance_->$name$_ = "
- "$classname$::$default_variable$;\n");
+ "if (has_$name$()) {\n"
+ " $oneof_prefix$$name$_.Destroy($default_variable$,\n"
+ " GetArenaNoVirtual());\n"
+ "}\n");
} else {
printer->Print(variables_,
- " $classname$_default_oneof_instance_->$name$_ = "
- "$default_variable$;\n");
+ "if (has_$name$()) {\n"
+ " $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"
+ "}\n");
}
}
void StringOneofFieldGenerator::
-GenerateDestructorCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (has_$name$()) {\n"
- " delete $oneof_prefix$$name$_;\n"
- "}\n");
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+ printer->Print(variables_,
+ "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+ " input, this->mutable_$name$()));\n");
+
+ if (HasUtf8Verification(descriptor_->file()) &&
+ descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ printer->Print(variables_,
+ "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
+ " this->$name$().data(), this->$name$().length(),\n"
+ " ::google::protobuf::internal::WireFormat::PARSE,\n"
+ " \"$full_name$\");\n");
+ }
}
+
// ===================================================================
RepeatedStringFieldGenerator::
@@ -566,7 +766,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedStringFieldGenerator::
@@ -586,7 +786,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" this->$name$(this->$name$_size() - 1).data(),\n"
" this->$name$(this->$name$_size() - 1).length(),\n"
" ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
}
@@ -600,7 +800,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$(i).data(), this->$name$(i).length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
@@ -618,7 +818,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
" ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$(i).data(), this->$name$(i).length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_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 86da38f2..0a5ca440 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -88,6 +88,7 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateDestructorCode(io::Printer* printer) const;
+ void GenerateMergeFromCodedStream(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
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 6b7f8308..4fa3c144 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -35,6 +35,7 @@
// This file tests that various identifiers work as field and type names even
// though the same identifiers are used internally by the C++ code generator.
+syntax = "proto2";
// Some generic_services option(s) added automatically.
// See: http://go/proto2-generic-services-default
@@ -58,7 +59,7 @@ message TestConflictingSymbolNames {
optional int32 total_size = 6;
optional int32 tag = 7;
- enum TestEnum { FOO = 1; }
+ enum TestEnum { FOO = 0; }
message Data1 { repeated int32 data = 1; }
message Data2 { repeated TestEnum data = 1; }
message Data3 { repeated string data = 1; }
@@ -99,6 +100,8 @@ message TestConflictingSymbolNames {
optional uint32 int = 30;
optional uint32 friend = 31;
optional uint32 class = 37;
+ optional uint32 typedecl = 39;
+ optional uint32 auto = 40;
// The generator used to #define a macro called "DO" inside the .cc file.
message DO {}
@@ -116,15 +119,18 @@ message TestConflictingSymbolNames {
// names.
optional DO release_do = 36;
- extensions 1000 to max;
-}
+ // For clashing local variables in Serialize and ByteSize calculation.
+ optional string target = 38;
-message TestConflictingSymbolNamesExtension {
- extend TestConflictingSymbolNames {
- repeated int32 repeated_int32_ext = 20423638 [packed=true];
- }
+ extensions 1000 to max; // NO_PROTO3
}
+message TestConflictingSymbolNamesExtension { // NO_PROTO3
+ extend TestConflictingSymbolNames { // NO_PROTO3
+ repeated int32 repeated_int32_ext = 20423638 [packed=true]; // NO_PROTO3
+ } // NO_PROTO3
+} // NO_PROTO3
+
message DummyMessage {}
service TestConflictingMethodNames {
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 93e1c3f1..c509a6a9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -47,6 +47,9 @@
#include <google/protobuf/compiler/cpp/cpp_unittest.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/unittest.pb.h>
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index e6c446af..678823cd 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -44,6 +44,9 @@
#include <algorithm>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/importer.h>
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index 8cc5d882..81c636c6 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -34,9 +34,13 @@
#include <google/protobuf/stubs/hash.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/map_util.h>
@@ -53,6 +57,10 @@ namespace compiler {
namespace {
+bool FileExists(const string& path) {
+ return File::Exists(path);
+}
+
#define EXPECT_SUBSTRING(needle, haystack) \
EXPECT_PRED_FORMAT2(testing::IsSubstring, (needle), (haystack))
@@ -215,120 +223,6 @@ TEST_F(ImporterTest, RecursiveImport) {
error_collector_.text_);
}
-// TODO(sanjay): The MapField tests below more properly belong in
-// descriptor_unittest, but are more convenient to test here.
-TEST_F(ImporterTest, MapFieldValid) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " required string key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- const FileDescriptor* file = importer_.Import("map.proto");
- ASSERT_TRUE(file != NULL) << error_collector_.text_;
- EXPECT_EQ("", error_collector_.text_);
-
- // Check that Map::items points to Item::key
- const Descriptor* item_type = file->FindMessageTypeByName("Item");
- ASSERT_TRUE(item_type != NULL);
- const Descriptor* map_type = file->FindMessageTypeByName("Map");
- ASSERT_TRUE(map_type != NULL);
- const FieldDescriptor* key_field = item_type->FindFieldByName("key");
- ASSERT_TRUE(key_field != NULL);
- const FieldDescriptor* items_field = map_type->FindFieldByName("items");
- ASSERT_TRUE(items_field != NULL);
- EXPECT_EQ(items_field->experimental_map_key(), key_field);
-}
-
-TEST_F(ImporterTest, MapFieldNotRepeated) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " required string key = 1;\n"
- "}\n"
- "message Map {\n"
- " required Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("only allowed for repeated fields", error());
-}
-
-TEST_F(ImporterTest, MapFieldNotMessageType) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Map {\n"
- " repeated int32 items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("only allowed for fields with a message type", error());
-}
-
-TEST_F(ImporterTest, MapFieldTypeNotFound) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Map {\n"
- " repeated Unknown items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("not defined", error());
-}
-
-TEST_F(ImporterTest, MapFieldKeyNotFound) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " required string key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"badkey\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("Could not find field", error());
-}
-
-TEST_F(ImporterTest, MapFieldKeyRepeated) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " repeated string key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("must not name a repeated field", error());
-}
-
-TEST_F(ImporterTest, MapFieldKeyNotScalar) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message ItemKey { }\n"
- "message Item {\n"
- " required ItemKey key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("must name a scalar or string", error());
-}
-
// ===================================================================
@@ -339,7 +233,7 @@ class DiskSourceTreeTest : public testing::Test {
dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_2");
for (int i = 0; i < dirnames_.size(); i++) {
- if (File::Exists(dirnames_[i])) {
+ if (FileExists(dirnames_[i])) {
File::DeleteRecursively(dirnames_[i], NULL, NULL);
}
GOOGLE_CHECK_OK(File::CreateDir(dirnames_[i], 0777));
diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h
index 57914450..7f1ce1f9 100644
--- a/src/google/protobuf/compiler/java/java_context.h
+++ b/src/google/protobuf/compiler/java/java_context.h
@@ -33,6 +33,9 @@
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 668377a3..0353b607 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -111,6 +111,10 @@ void EnumGenerator::Generate(io::Printer* printer) {
"$name$($index$, $number$),\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print("UNRECOGNIZED(-1, -1),\n");
+ }
+
printer->Print(
";\n"
"\n");
@@ -141,7 +145,17 @@ void EnumGenerator::Generate(io::Printer* printer) {
printer->Print(
"\n"
- "public final int getNumber() { return value; }\n"
+ "public final int getNumber() {\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ " if (index == -1) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Can't get the number of an unknown enum value.\");\n"
+ " }\n");
+ }
+ printer->Print(
+ " return value;\n"
+ "}\n"
"\n"
"public static $classname$ valueOf(int value) {\n"
" switch (value) {\n",
@@ -231,11 +245,12 @@ void EnumGenerator::Generate(io::Printer* printer) {
"index", SimpleItoa(descriptor_->index()));
}
printer->Print(
- "return $immutable_package$.$descriptor_class$.getDescriptor()\n"
+ "return $immutable_package$.$descriptor_class$.$descriptor$\n"
" .getEnumTypes().get($index$);\n",
"immutable_package", FileJavaPackage(descriptor_->file(), true),
"descriptor_class",
name_resolver_->GetDescriptorClassName(descriptor_->file()),
+ "descriptor", "getDescriptor()",
"index", SimpleItoa(descriptor_->index()));
printer->Outdent();
}
@@ -283,11 +298,18 @@ void EnumGenerator::Generate(io::Printer* printer) {
" if (desc.getType() != getDescriptor()) {\n"
" throw new java.lang.IllegalArgumentException(\n"
" \"EnumValueDescriptor is not for this type.\");\n"
- " }\n"
+ " }\n",
+ "classname", descriptor_->name());
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ " if (desc.getIndex() == -1) {\n"
+ " return UNRECOGNIZED;\n"
+ " }\n");
+ }
+ printer->Print(
" return VALUES[desc.getIndex()];\n"
"}\n"
- "\n",
- "classname", descriptor_->name());
+ "\n");
// index is only used for reflection; lite implementation does not need it
printer->Print("private final int index;\n");
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 1f0c4af0..71a2ba4b 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -65,6 +65,8 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["mutable_type"] =
name_resolver->GetMutableClassName(descriptor->enum_type());
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_number"] = SimpleItoa(
+ descriptor->default_value_enum()->number());
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
@@ -95,7 +97,8 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["clear_has_field_bit_builder"] = "";
(*variables)["is_field_present_message"] =
- (*variables)["name"] + "_ != " + (*variables)["default"];
+ (*variables)["name"] + "_ != " +
+ (*variables)["default"] + ".getNumber()";
}
// For repated builders, one bit is used for whether the array is immutable.
@@ -114,6 +117,12 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
GenerateSetBitToLocal(messageBitIndex);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+ } else {
+ (*variables)["unknown"] = (*variables)["default"];
+ }
}
} // namespace
@@ -150,6 +159,11 @@ GenerateInterfaceMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$boolean has$capitalized_name$();\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value();\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$();\n");
@@ -158,7 +172,7 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void ImmutableEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $type$ $name$_;\n");
+ "private int $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
if (SupportFieldPresence(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
@@ -167,17 +181,25 @@ GenerateMembers(io::Printer* printer) const {
" return $get_has_field_bit_message$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return $name$_;\n"
+ "}\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " return $name$_;\n"
+ " $type$ result = $type$.valueOf($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
"}\n");
}
void ImmutableEnumFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $type$ $name$_ = $default$;\n");
+ "private int $name$_ = $default_number$;\n");
if (SupportFieldPresence(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -185,10 +207,25 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return $get_has_field_bit_builder$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return $name$_;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+ " $name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " return $name$_;\n"
+ " $type$ result = $type$.valueOf($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -197,7 +234,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" $set_has_field_bit_builder$\n"
- " $name$_ = value;\n"
+ " $name$_ = value.getNumber();\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -205,7 +242,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $clear_has_field_bit_builder$\n"
- " $name$_ = $default$;\n"
+ " $name$_ = $default_number$;\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -218,13 +255,13 @@ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
void ImmutableEnumFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_ = $default$;\n");
+ printer->Print(variables_, "$name$_ = $default_number$;\n");
}
void ImmutableEnumFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$_ = $default$;\n"
+ "$name$_ = $default_number$;\n"
"$clear_has_field_bit_builder$\n");
}
@@ -235,11 +272,13 @@ GenerateMergingCode(io::Printer* printer) const {
"if (other.has$capitalized_name$()) {\n"
" set$capitalized_name$(other.get$capitalized_name$());\n"
"}\n");
- } else {
+ } else if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- "if (other.get$capitalized_name$() != $default$) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "if (other.$name$_ != $default_number$) {\n"
+ " set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
"}\n");
+ } else {
+ GOOGLE_LOG(FATAL) << "Can't reach here.";
}
}
@@ -257,23 +296,26 @@ GenerateBuildingCode(io::Printer* printer) const {
void ImmutableEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
- "if (value == null) {\n");
- if (UseUnknownFieldSet(descriptor_->containing_type())) {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = rawValue;\n");
} else {
printer->Print(variables_,
- " unknownFieldsCodedOutput.writeRawVarint32(tag);\n"
- " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = rawValue;\n"
+ "}\n");
}
- printer->Print(variables_,
- "} else {\n"
- " $set_has_field_bit_message$\n"
- " $name$_ = value;\n"
- "}\n");
}
void ImmutableEnumFieldGenerator::
@@ -285,7 +327,7 @@ void ImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.writeEnum($number$, $name$_.getNumber());\n"
+ " output.writeEnum($number$, $name$_);\n"
"}\n");
}
@@ -294,23 +336,21 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeEnumSize($number$, $name$_.getNumber());\n"
+ " .computeEnumSize($number$, $name$_);\n"
"}\n");
}
void ImmutableEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
- "result = result &&\n"
- " (get$capitalized_name$() == other.get$capitalized_name$());\n");
+ "result = result && $name$_ == other.$name$_;\n");
}
void ImmutableEnumFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"hash = (37 * hash) + $constant_name$;\n"
- "hash = (53 * hash) + com.google.protobuf.Internal.hashEnum(\n"
- " get$capitalized_name$());\n");
+ "hash = (53 * hash) + $name$_;\n");
}
string ImmutableEnumFieldGenerator::GetBoxedType() const {
@@ -344,11 +384,22 @@ GenerateMembers(io::Printer* printer) const {
" return $has_oneof_case_message$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return (java.lang.Integer) $oneof_name$_;\n"
+ " }\n"
+ " return $default_number$;\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"
+ " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
" }\n"
" return $default$;\n"
"}\n");
@@ -363,11 +414,30 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return $has_oneof_case_message$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ((java.lang.Integer) $oneof_name$_).intValue();\n"
+ " }\n"
+ " return $default_number$;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\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 $type$ get$capitalized_name$() {\n"
" if ($has_oneof_case_message$) {\n"
- " return ($type$) $oneof_name$_;\n"
+ " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
" }\n"
" return $default$;\n"
"}\n");
@@ -378,7 +448,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" $set_oneof_case_message$;\n"
- " $oneof_name$_ = value;\n"
+ " $oneof_name$_ = value.getNumber();\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -404,36 +474,44 @@ GenerateBuildingCode(io::Printer* printer) const {
void ImmutableEnumOneofFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "set$capitalized_name$(other.get$capitalized_name$());\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
+ } else {
+ 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())) {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = rawValue;\n");
} else {
printer->Print(variables_,
- " unknownFieldsCodedOutput.writeRawVarint32(tag);\n"
- " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = rawValue;\n"
+ "}\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"
+ " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
"}\n");
}
@@ -442,10 +520,36 @@ 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"
+ " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
"}\n");
}
+void ImmutableEnumOneofFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$Value()\n"
+ " == other.get$capitalized_name$Value();\n");
+ } else {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+ }
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$Value();\n");
+ } else {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
+ }
+}
+
// ===================================================================
RepeatedImmutableEnumFieldGenerator::
@@ -482,17 +586,36 @@ GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$(int index);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value(int index);\n");
+ }
}
void RepeatedImmutableEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.util.List<$type$> $name$_;\n");
+ "private java.util.List<java.lang.Integer> $name$_;\n"
+ "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$> $name$_converter_ =\n"
+ " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$>() {\n"
+ " public $type$ convert(java.lang.Integer from) {\n"
+ " $type$ result = $type$.valueOf(from);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " };\n");
PrintExtraFieldInfo(variables_, printer);
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
- " return $name$_;\n" // note: unmodifiable list
+ " return new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -502,8 +625,21 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
- " return $name$_.get(index);\n"
+ " return $name$_converter_.convert($name$_.get(index));\n"
"}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList() {\n"
+ " return $name$_;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ }
if (descriptor_->options().packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
@@ -524,12 +660,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
// memory allocations. Note, immutable is a strong guarantee here -- not
// just that the list cannot be modified via the reference but that the
// list can never be modified.
- "private java.util.List<$type$> $name$_ =\n"
+ "private java.util.List<java.lang.Integer> $name$_ =\n"
" java.util.Collections.emptyList();\n"
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$get_mutable_bit_builder$) {\n"
- " $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
" $set_mutable_bit_builder$;\n"
" }\n"
"}\n");
@@ -541,7 +677,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
// has been built, thus mutating the message which is supposed to be
// immutable.
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
- " return java.util.Collections.unmodifiableList($name$_);\n"
+ " return new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -551,7 +688,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
- " return $name$_.get(index);\n"
+ " return $name$_converter_.convert($name$_.get(index));\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -561,7 +698,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" ensure$capitalized_name$IsMutable();\n"
- " $name$_.set(index, value);\n"
+ " $name$_.set(index, value.getNumber());\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -572,7 +709,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" ensure$capitalized_name$IsMutable();\n"
- " $name$_.add(value);\n"
+ " $name$_.add(value.getNumber());\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -581,8 +718,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<? extends $type$> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
- " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
- " values, $name$_);\n"
+ " for ($type$ value : values) {\n"
+ " $name$_.add(value.getNumber());\n"
+ " }\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -594,6 +732,48 @@ GenerateBuilderMembers(io::Printer* printer) const {
" $on_changed$\n"
" return this;\n"
"}\n");
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList() {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(\n"
+ " int index, int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+ " java.lang.Iterable<java.lang.Integer> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for (int value : values) {\n"
+ " $name$_.add(value);\n"
+ " }\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ }
}
void RepeatedImmutableEnumFieldGenerator::
@@ -648,26 +828,32 @@ GenerateBuildingCode(io::Printer* printer) const {
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 (value == null) {\n");
- if (UseUnknownFieldSet(descriptor_->containing_type())) {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
+ "$name$_.add(rawValue);\n");
} else {
printer->Print(variables_,
- " unknownFieldsCodedOutput.writeRawVarint32(tag);\n"
- " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " $set_mutable_bit_parser$;\n"
+ " }\n"
+ " $name$_.add(rawValue);\n"
+ "}\n");
}
- printer->Print(variables_,
- " } else {\n"
- " if (!$get_mutable_bit_parser$) {\n"
- " $name$_ = new java.util.ArrayList<$type$>();\n"
- " $set_mutable_bit_parser$;\n"
- " }\n"
- " $name$_.add(value);\n"
- "}\n");
}
void RepeatedImmutableEnumFieldGenerator::
@@ -705,12 +891,12 @@ GenerateSerializationCode(io::Printer* printer) const {
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
"}\n"
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeEnumNoTag($name$_.get(i).getNumber());\n"
+ " output.writeEnumNoTag($name$_.get(i));\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeEnum($number$, $name$_.get(i).getNumber());\n"
+ " output.writeEnum($number$, $name$_.get(i));\n"
"}\n");
}
}
@@ -725,7 +911,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
" dataSize += com.google.protobuf.CodedOutputStream\n"
- " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
+ " .computeEnumSizeNoTag($name$_.get(i));\n"
"}\n");
printer->Print(
"size += dataSize;\n");
@@ -754,8 +940,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
void RepeatedImmutableEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
- "result = result && get$capitalized_name$List()\n"
- " .equals(other.get$capitalized_name$List());\n");
+ "result = result && $name$_.equals(other.$name$_);\n");
}
void RepeatedImmutableEnumFieldGenerator::
@@ -763,8 +948,7 @@ GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"if (get$capitalized_name$Count() > 0) {\n"
" hash = (37 * hash) + $constant_name$;\n"
- " hash = (53 * hash) + com.google.protobuf.Internal.hashEnumList(\n"
- " get$capitalized_name$List());\n"
+ " hash = (53 * hash) + $name$_.hashCode();\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index 6a9535aa..b8ff7343 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -106,6 +106,8 @@ class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator);
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index d7b0f3fc..49635bb4 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -35,12 +35,16 @@
#include <google/protobuf/compiler/java/java_field.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#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_map_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>
@@ -48,6 +52,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -61,12 +66,17 @@ ImmutableFieldGenerator* MakeImmutableGenerator(
if (field->is_repeated()) {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
- if (IsLazy(field)) {
- return new RepeatedImmutableLazyMessageFieldGenerator(
+ if (IsMapEntry(field->message_type())) {
+ return new ImmutableMapFieldGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
- return new RepeatedImmutableMessageFieldGenerator(
- field, messageBitIndex, builderBitIndex, context);
+ if (IsLazy(field)) {
+ return new RepeatedImmutableLazyMessageFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new RepeatedImmutableMessageFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
}
case JAVATYPE_ENUM:
return new RepeatedImmutableEnumFieldGenerator(
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index db339d5b..5bc5634e 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -37,6 +37,9 @@
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 231b1445..1ac945cd 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -35,6 +35,9 @@
#include <google/protobuf/compiler/java/java_file.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum.h>
@@ -180,29 +183,6 @@ 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;
}
@@ -323,6 +303,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
SharedCodeGenerator shared_code_generator(file_);
shared_code_generator.GenerateDescriptors(printer);
+
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->GenerateStaticVariableInitializers(printer);
}
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index c805b9a6..0b2230a0 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index c3a47e3e..a743ce22 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -35,6 +35,9 @@
#include <google/protobuf/compiler/java/java_generator.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_file.h>
#include <google/protobuf/compiler/java/java_generator_factory.h>
@@ -99,10 +102,14 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
vector<string> all_files;
+
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) {
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 3efd7edb..23685385 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -306,6 +306,26 @@ JavaType GetJavaType(const FieldDescriptor* field) {
return JAVATYPE_INT;
}
+const char* PrimitiveTypeName(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return "int";
+ case JAVATYPE_LONG : return "long";
+ case JAVATYPE_FLOAT : return "float";
+ case JAVATYPE_DOUBLE : return "double";
+ case JAVATYPE_BOOLEAN: return "boolean";
+ case JAVATYPE_STRING : return "java.lang.String";
+ case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
+ case JAVATYPE_ENUM : return NULL;
+ case JAVATYPE_MESSAGE: return NULL;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
const char* BoxedPrimitiveTypeName(JavaType type) {
switch (type) {
case JAVATYPE_INT : return "java.lang.Integer";
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 93f23a93..2707fa0a 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -149,6 +149,8 @@ enum JavaType {
JavaType GetJavaType(const FieldDescriptor* field);
+const char* PrimitiveTypeName(JavaType type);
+
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
// types.
@@ -168,13 +170,6 @@ inline string ImmutableDefaultValue(const FieldDescriptor* field,
}
bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
-// Does this message class use UnknownFieldSet?
-// Otherwise, unknown fields will be stored in a ByteString object
-inline bool UseUnknownFieldSet(const Descriptor* descriptor) {
- return descriptor->file()->options().optimize_for() !=
- FileOptions::LITE_RUNTIME;
-}
-
// Does this message class have generated parsing, serialization, and other
// standard methods for which reflection-based fallback implementations exist?
inline bool HasGeneratedMethods(const Descriptor* descriptor) {
@@ -308,12 +303,27 @@ 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;
+ return descriptor->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet
+// but in the message and can be queried using additional getters that return
+// ints.
+inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) {
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
}
// Check whether a mesasge has repeated fields.
bool HasRepeatedFields(const Descriptor* descriptor);
+inline bool IsMapEntry(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+inline bool PreserveUnknownFields(const Descriptor* descriptor) {
+ return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
new file mode 100644
index 00000000..2986f51f
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -0,0 +1,455 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/java/java_map_field.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>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("value");
+}
+
+string TypeName(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver,
+ bool boxed) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ return name_resolver->GetImmutableClassName(field->message_type());
+ } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+ return name_resolver->GetImmutableClassName(field->enum_type());
+ } else {
+ return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
+ : PrimitiveTypeName(GetJavaType(field));
+ }
+}
+
+string WireType(const FieldDescriptor* field) {
+ return "com.google.protobuf.WireFormat.FieldType." +
+ string(FieldTypeName(field->type()));
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ const FieldDescriptor* key = KeyField(descriptor);
+ const FieldDescriptor* value = ValueField(descriptor);
+ (*variables)["key_type"] = TypeName(key, name_resolver, false);
+ (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+ (*variables)["key_wire_type"] = WireType(key);
+ (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+ if (GetJavaType(value) == JAVATYPE_ENUM) {
+ // We store enums as Integers internally.
+ (*variables)["value_type"] = "int";
+ (*variables)["boxed_value_type"] = "java.lang.Integer";
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver) + ".getNumber()";
+
+ (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ // Map unknown values to a special UNRECOGNIZED value if supported.
+ (*variables)["unrecognized_value"] =
+ (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+ } else {
+ // Map unknown values to the default value if we don't have UNRECOGNIZED.
+ (*variables)["unrecognized_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ } else {
+ (*variables)["value_type"] = TypeName(value, name_resolver, false);
+ (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ (*variables)["type_parameters"] =
+ (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ // For repeated fields, one bit is used for whether the array is immutable
+ // in the parsing constructor.
+ (*variables)["get_mutable_bit_parser"] =
+ GenerateGetBitMutableLocal(builderBitIndex);
+ (*variables)["set_mutable_bit_parser"] =
+ GenerateSetBitMutableLocal(builderBitIndex);
+
+ if (HasDescriptorMethods(descriptor->file())) {
+ (*variables)["lite"] = "";
+ (*variables)["map_field_parameter"] = (*variables)["name"] + "DefaultEntry";
+ (*variables)["descriptor"] =
+ name_resolver->GetImmutableClassName(descriptor->file()) +
+ ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
+ "_descriptor, ";
+ } else {
+ (*variables)["lite"] = "Lite";
+ (*variables)["map_field_parameter"] = "";
+ (*variables)["descriptor"] = "";
+ }
+}
+
+} // namespace
+
+ImmutableMapFieldGenerator::
+ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableMapFieldGenerator::
+~ImmutableMapFieldGenerator() {}
+
+int ImmutableMapFieldGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const {
+ return 1;
+}
+
+void ImmutableMapFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$();\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "get$capitalized_name$Value();\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "get$capitalized_name$();\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private static final com.google.protobuf.MapEntry$lite$<\n"
+ " $type_parameters$> $name$DefaultEntry =\n"
+ " com.google.protobuf.MapEntry$lite$\n"
+ " .<$type_parameters$>newDefaultInstance(\n"
+ " $descriptor$\n"
+ " $key_wire_type$,\n"
+ " $key_default_value$,\n"
+ " $value_wire_type$,\n"
+ " $value_default_value$);\n");
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.MapField$lite$<\n"
+ " $type_parameters$> $name$_ =\n"
+ " com.google.protobuf.MapField$lite$.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ "\n");
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "private static final\n"
+ "com.google.protobuf.Internal.MapAdapter.Converter<\n"
+ " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
+ " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
+ " $value_enum_type$.internalGetValueMap(),\n"
+ " $unrecognized_value$);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "get$capitalized_name$Value() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " $name$_.getMap(), $name$ValueConverter);\n"
+ "}\n");
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.MapField$lite$<\n"
+ " $type_parameters$> $name$_ =\n"
+ " com.google.protobuf.MapField$lite$.newMapField(\n"
+ " $map_field_parameter$);\n"
+ "\n");
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " $name$_.getMap(), $name$ValueConverter);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " $on_changed$\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " $name$_.getMutableMap(), $name$ValueConverter);\n"
+ "}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "get$capitalized_name$Value() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "getMutable$capitalized_name$Value() {\n"
+ " $on_changed$\n"
+ " return $name$_.getMutableMap();\n"
+ "}\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " $on_changed$\n"
+ " return $name$_.getMutableMap();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "$name$_.clear();\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "$name$_.mergeFrom(other.$name$_);\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ // We do a copy of the map field to ensure that the built result is
+ // immutable. Implementation of this copy() method can do copy-on-write
+ // to defer this copy until further modifications are made on the field.
+ "result.$name$_ = $name$_.copy();\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+ " $map_field_parameter$);\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n");
+ if (!SupportUnknownEnumValue(descriptor_->file()) &&
+ GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.ByteString bytes = input.readBytes();\n"
+ "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ "$name$ = $name$DefaultEntry.getParserForType().parseFrom(bytes);\n");
+ printer->Print(
+ variables_,
+ "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+ " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
+ "} else {\n"
+ " $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ "$name$ = input.readMessage(\n"
+ " $name$DefaultEntry.getParserForType(), extensionRegistry);\n"
+ "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // Nothing to do here.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : $name$_.getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " output.writeMessage($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : $name$_.getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeMessageSize($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "result = result && $name$_.equals(other.$name$_);\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!$name$_.getMap().isEmpty()) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + $name$_.hashCode();\n"
+ "}\n");
+}
+
+string ImmutableMapFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
new file mode 100644
index 00000000..80a94f45
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -0,0 +1,82 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit ImmutableMapFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMapFieldGenerator();
+
+ // implements ImmutableFieldGenerator ---------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
+ void GenerateBuilderClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateBuildingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 8aa89ac7..dd1ad6a6 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -38,6 +38,9 @@
#include <google/protobuf/stubs/hash.h>
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/compiler/java/java_context.h>
@@ -264,60 +267,36 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
descriptor_->containing_type() == NULL &&
MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+ map<string, string> variables;
+ variables["static"] = is_own_file ? " " : " static ";
+ variables["classname"] = descriptor_->name();
+ variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+ variables["lite"] = HasDescriptorMethods(descriptor_) ? "" : "Lite";
+
WriteMessageDocComment(printer, descriptor_);
// The builder_type stores the super type name of the nested Builder class.
string builder_type;
if (descriptor_->extension_range_count() > 0) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
- " $classname$> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
- name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
- " $classname$> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
- name_resolver_->GetImmutableClassName(descriptor_));
- }
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage<\n"
+ " $classname$> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_),
+ variables["lite"]);
} else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
- } else {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessageLite implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
- }
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessage$lite$ implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessage$0.Builder",
+ variables["lite"]);
}
printer->Indent();
// Using builder_type, instead of Builder, prevents the Builder class from
@@ -328,16 +307,22 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"// Use $classname$.newBuilder() to construct.\n"
"private $classname$($buildertype$ builder) {\n"
" super(builder);\n"
- "$set_unknown_fields$\n"
"}\n",
"classname", descriptor_->name(),
- "buildertype", builder_type,
- "set_unknown_fields",
- " this.unknownFields = builder.getUnknownFields();");
+ "buildertype", builder_type);
printer->Print(
- // Used when constructing the default instance, which cannot be initialized
- // immediately because it may cyclically refer to other default instances.
- "private $classname$(boolean noInit) {$set_default_unknown_fields$}\n"
+ "private $classname$() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n"
"\n"
"private static final $classname$ defaultInstance;\n"
"public static $classname$ getDefaultInstance() {\n"
@@ -349,23 +334,22 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"}\n"
"\n",
"classname", descriptor_->name(),
- "set_default_unknown_fields", UseUnknownFieldSet(descriptor_)
- ? " this.unknownFields ="
- " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); "
- : " this.unknownFields = com.google.protobuf.ByteString.EMPTY;");
+ "lite", variables["lite"]);
- if (UseUnknownFieldSet(descriptor_)) {
+ if (HasDescriptorMethods(descriptor_)) {
printer->Print(
- "private final com.google.protobuf.UnknownFieldSet unknownFields;\n"
- ""
- "@java.lang.Override\n"
- "public final com.google.protobuf.UnknownFieldSet\n"
- " getUnknownFields() {\n"
- " return this.unknownFields;\n"
- "}\n");
- } else {
+ "@java.lang.Override\n"
+ "public final com.google.protobuf.UnknownFieldSet\n"
+ "getUnknownFields() {\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ " return this.unknownFields;\n");
+ } else {
+ printer->Print(
+ " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
+ }
printer->Print(
- "private final com.google.protobuf.ByteString unknownFields;\n");
+ "}\n");
}
if (HasGeneratedMethods(descriptor_)) {
@@ -382,6 +366,8 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // Don't generate Java classes for map entry messages.
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
ImmutableMessageGenerator messageGenerator(
descriptor_->nested_type(i), context_);
messageGenerator.GenerateInterface(printer);
@@ -480,20 +466,6 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
- // Called by the constructor, except in the case of the default instance,
- // in which case this is called by static init code later on.
- printer->Print("private void initFields() {\n");
- printer->Indent();
- for (int i = 0; i < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(descriptor_->field(i))
- .GenerateInitializationCode(printer);
- }
- }
-
- printer->Outdent();
- printer->Print("}\n");
-
if (HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer, MEMOIZE);
GenerateMessageSerializationMethods(printer);
@@ -512,8 +484,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Print(
"\n"
"static {\n"
- " defaultInstance = new $classname$(true);\n"
- " defaultInstance.initFields();\n"
+ " defaultInstance = new $classname$();\n"
"}\n"
"\n"
"// @@protoc_insertion_point(class_scope:$full_name$)\n",
@@ -593,17 +564,15 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
}
- if (UseUnknownFieldSet(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()) {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()
+ && HasDescriptorMethods(descriptor_)) {
printer->Print(
- "getUnknownFields().writeAsMessageSetTo(output);\n");
+ "unknownFields.writeAsMessageSetTo(output);\n");
} else {
printer->Print(
- "getUnknownFields().writeTo(output);\n");
+ "unknownFields.writeTo(output);\n");
}
- } else {
- printer->Print(
- "output.writeRawBytes(unknownFields);\n");
}
printer->Outdent();
@@ -632,17 +601,15 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
}
- if (UseUnknownFieldSet(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()) {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()
+ && HasDescriptorMethods(descriptor_)) {
printer->Print(
- "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
+ "size += unknownFields.getSerializedSizeAsMessageSet();\n");
} else {
printer->Print(
- "size += getUnknownFields().getSerializedSize();\n");
+ "size += unknownFields.getSerializedSize();\n");
}
- } else {
- printer->Print(
- "size += unknownFields.size();\n");
}
printer->Outdent();
@@ -653,13 +620,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
"\n");
printer->Print(
- "private static final long serialVersionUID = 0L;\n"
- "@java.lang.Override\n"
- "protected java.lang.Object writeReplace()\n"
- " throws java.io.ObjectStreamException {\n"
- " return super.writeReplace();\n"
- "}\n"
- "\n");
+ "private static final long serialVersionUID = 0L;\n");
}
void ImmutableMessageGenerator::
@@ -740,7 +701,7 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
printer->Print(
- "public static Builder newBuilder() { return Builder.create(); }\n"
+ "public static Builder newBuilder() { return new Builder(); }\n"
"public Builder newBuilderForType() { return newBuilder(); }\n"
"public static Builder newBuilder($classname$ prototype) {\n"
" return newBuilder().mergeFrom(prototype);\n"
@@ -809,7 +770,6 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
if (HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer, DONT_MEMOIZE);
- GenerateBuilderParsingMethods(printer);
}
// oneof
@@ -864,6 +824,20 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
.GenerateBuilderMembers(printer);
}
+ if (!PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "public final Builder setUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return this;\n"
+ "}\n"
+ "\n"
+ "public final Builder mergeUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
printer->Print(
"\n"
"// @@protoc_insertion_point(builder_scope:$full_name$)\n",
@@ -886,6 +860,41 @@ GenerateDescriptorMethods(io::Printer* printer) {
"fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
}
+ vector<const FieldDescriptor*> map_fields;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ map_fields.push_back(field);
+ }
+ }
+ if (!map_fields.empty()) {
+ printer->Print(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return $name$_;\n",
+ "number", SimpleItoa(field->number()),
+ "name", info->name);
+ }
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+ }
printer->Print(
"protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
" internalGetFieldAccessorTable() {\n"
@@ -949,13 +958,8 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
}
printer->Print(
- "private static Builder create() {\n"
- " return new Builder();\n"
- "}\n"
- "\n"
"public Builder clear() {\n"
- " super.clear();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ " super.clear();\n");
printer->Indent();
@@ -979,12 +983,8 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
printer->Print(
" return this;\n"
"}\n"
- "\n"
- "public Builder clone() {\n"
- " return create().mergeFrom(buildPartial());\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "\n");
+
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
"public com.google.protobuf.Descriptors.Descriptor\n"
@@ -1153,13 +1153,13 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
" this.mergeExtensionFields(other);\n");
}
- if (UseUnknownFieldSet(descriptor_)) {
+ if (PreserveUnknownFields(descriptor_)) {
printer->Print(
- " this.mergeUnknownFields(other.getUnknownFields());\n");
- } else {
- printer->Print(
- " setUnknownFields(\n"
- " getUnknownFields().concat(other.unknownFields));\n");
+ " this.mergeUnknownFields(other.unknownFields);\n");
+ }
+
+ if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(" onChanged();\n");
}
printer->Print(
@@ -1171,31 +1171,6 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
// ===================================================================
-void ImmutableMessageGenerator::
-GenerateBuilderParsingMethods(io::Printer* printer) {
- printer->Print(
- "public Builder mergeFrom(\n"
- " com.google.protobuf.CodedInputStream input,\n"
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
- " throws java.io.IOException {\n"
- " $classname$ parsedMessage = null;\n"
- " try {\n"
- " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
- " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
- " throw e;\n"
- " } finally {\n"
- " if (parsedMessage != null) {\n"
- " mergeFrom(parsedMessage);\n"
- " }\n"
- " }\n"
- " return this;\n"
- "}\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-}
-
-// ===================================================================
-
void ImmutableMessageGenerator::GenerateIsInitialized(
io::Printer* printer, UseMemoization useMemoization) {
bool memoization = useMemoization == MEMOIZE;
@@ -1256,15 +1231,26 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
break;
case FieldDescriptor::LABEL_OPTIONAL:
+ if (!SupportFieldPresence(descriptor_->file()) &&
+ field->containing_oneof() != NULL) {
+ const OneofDescriptor* oneof = field->containing_oneof();
+ const OneofGeneratorInfo* oneof_info =
+ context_->GetOneofGeneratorInfo(oneof);
+ printer->Print(
+ "if ($oneof_name$Case_ == $field_number$) {\n",
+ "oneof_name", oneof_info->name,
+ "field_number", SimpleItoa(field->number()));
+ } else {
+ printer->Print(
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ }
printer->Print(
- "if (has$name$()) {\n"
" if (!get$name$().isInitialized()) {\n"
" $memoize$\n"
" return false;\n"
" }\n"
"}\n",
- "type", name_resolver_->GetImmutableClassName(
- field->message_type()),
"name", info->capitalized_name,
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
break;
@@ -1358,10 +1344,14 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
"}\n");
}
}
- if (HasDescriptorMethods(descriptor_)) {
+ if (PreserveUnknownFields(descriptor_)) {
+ // Always consider unknown fields for equality. This will sometimes return
+ // false for non-canonical ordering when running in LITE_RUNTIME but it's
+ // the best we can do.
printer->Print(
- "result = result &&\n"
- " getUnknownFields().equals(other.getUnknownFields());\n");
+ "result = result && unknownFields.equals(other.unknownFields);\n");
+ }
+ if (HasDescriptorMethods(descriptor_)) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"result = result &&\n"
@@ -1421,13 +1411,8 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
}
}
- 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) + unknownFields.hashCode();\n");
printer->Print(
"memoizedHashCode = hash;\n"
"return hash;\n");
@@ -1468,7 +1453,7 @@ GenerateParsingConstructor(io::Printer* printer) {
// Initialize all fields to default.
printer->Print(
- "initFields();\n");
+ "this();\n");
// Use builder bits to track mutable repeated fields.
int totalBuilderBits = 0;
@@ -1483,17 +1468,16 @@ GenerateParsingConstructor(io::Printer* printer) {
"bit_field_name", GetBitFieldName(i));
}
- 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");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
+ } else {
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
+ }
}
printer->Print(
@@ -1513,16 +1497,41 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Print(
"case 0:\n" // zero signals EOF / limit reached
" done = true;\n"
- " break;\n"
- "default: {\n"
- " if (!parseUnknownField(input,$unknown_fields$\n"
- " extensionRegistry, tag)) {\n"
- " done = true;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n",
- "unknown_fields", UseUnknownFieldSet(descriptor_)
- ? " unknownFields," : " unknownFieldsCodedOutput,");
+ " break;\n");
+
+ if (PreserveUnknownFields(descriptor_)) {
+ if (!HasDescriptorMethods(descriptor_)
+ && descriptor_->extension_range_count() > 0) {
+ // Lite runtime directly invokes parseUnknownField to reduce method
+ // counts.
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n"
+ " input, unknownFields,\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(input, unknownFields,\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ }
+ } else {
+ printer->Print(
+ "default: {\n"
+ " if (!input.skipField(tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ }
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
@@ -1582,19 +1591,9 @@ GenerateParsingConstructor(io::Printer* printer) {
field_generators_.get(field).GenerateParsingDoneCode(printer);
}
- // Make unknown fields immutable.
- 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");
+ if (PreserveUnknownFields(descriptor_)) {
+ // Make unknown fields immutable.
+ printer->Print("this.unknownFields = unknownFields.build();\n");
}
// Make extensions immutable.
@@ -1611,7 +1610,7 @@ GenerateParsingConstructor(io::Printer* printer) {
// ===================================================================
void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
printer->Print(
- "public static com.google.protobuf.Parser<$classname$> PARSER =\n"
+ "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
" new com.google.protobuf.AbstractParser<$classname$>() {\n",
"classname", descriptor_->name());
printer->Indent();
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index fece1c21..2703016e 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -118,7 +118,6 @@ class ImmutableMessageGenerator : public MessageGenerator {
void GenerateBuilder(io::Printer* printer);
void GenerateCommonBuilderMethods(io::Printer* printer);
void GenerateDescriptorMethods(io::Printer* printer);
- void GenerateBuilderParsingMethods(io::Printer* printer);
void GenerateIsInitialized(io::Printer* printer,
UseMemoization useMemoization);
void GenerateEqualsAndHashCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index e681314e..538f1248 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -179,7 +179,7 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " return $name$_;\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
@@ -187,7 +187,7 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public $type$OrBuilder "
"get$capitalized_name$OrBuilder() {\n"
- " return $name$_;\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
}
} else {
@@ -257,14 +257,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
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");
- }
+ printer->Print(variables_,
+ "private $type$ $name$_ = null;\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
printer->Print(variables_,
@@ -296,13 +290,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public $type$ get$capitalized_name$()",
-
- support_field_presence
- ? "return $name$_;\n"
- : "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
-
+ "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
"return $name$Builder_.getMessage();\n",
-
NULL);
// Field.Builder setField(Field value)
@@ -342,6 +331,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
support_field_presence
? "if ($get_has_field_bit_builder$ &&\n"
+ " $name$_ != null &&\n"
" $name$_ != $type$.getDefaultInstance()) {\n"
" $name$_ =\n"
" $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
@@ -367,11 +357,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder clear$capitalized_name$()",
- support_field_presence
- ? "$name$_ = $type$.getDefaultInstance();\n"
- "$on_changed$\n"
- : "$name$_ = null;\n"
- "$on_changed$\n",
+ "$name$_ = null;\n"
+ "$on_changed$\n",
support_field_presence
? "$name$Builder_.clear();\n"
@@ -394,16 +381,9 @@ 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");
- 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_,
+ " } else {\n"
+ " return $name$_ == null ?\n"
+ " $type$.getDefaultInstance() : $name$_;\n"
" }\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -434,17 +414,13 @@ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
void ImmutableMessageFieldGenerator::
-GenerateInitializationCode(io::Printer* printer) const {
- if (SupportFieldPresence(descriptor_->file())) {
- printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
- }
-}
+GenerateInitializationCode(io::Printer* printer) const {}
void ImmutableMessageFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
if (SupportFieldPresence(descriptor_->file())) {
PrintNestedBuilderCondition(printer,
- "$name$_ = $type$.getDefaultInstance();\n",
+ "$name$_ = null;\n",
"$name$Builder_.clear();\n");
printer->Print(variables_, "$clear_has_field_bit_builder$\n");
@@ -514,7 +490,7 @@ void ImmutableMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.write$group_or_message$($number$, $name$_);\n"
+ " output.write$group_or_message$($number$, get$capitalized_name$());\n"
"}\n");
}
@@ -523,7 +499,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .compute$group_or_message$Size($number$, $name$_);\n"
+ " .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index c4d6995d..45aa8ffe 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -35,6 +35,9 @@
// worth.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 6713d29a..e331d7a4 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -55,26 +55,6 @@ using internal::WireFormatLite;
namespace {
-const char* PrimitiveTypeName(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return "int";
- case JAVATYPE_LONG : return "long";
- case JAVATYPE_FLOAT : return "float";
- case JAVATYPE_DOUBLE : return "double";
- case JAVATYPE_BOOLEAN: return "boolean";
- case JAVATYPE_STRING : return "java.lang.String";
- case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
- case JAVATYPE_ENUM : return NULL;
- case JAVATYPE_MESSAGE: return NULL;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
-}
-
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
int messageBitIndex,
int builderBitIndex,
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index ea77f792..f8723f2a 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -33,6 +33,9 @@
#include <google/protobuf/compiler/java/java_shared_code_generator.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_name_resolver.h>
@@ -176,7 +179,8 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
// Invoke internalBuildGeneratedFileFrom() to build the file.
printer->Print(
"com.google.protobuf.Descriptors.FileDescriptor\n"
- " .internalBuildGeneratedFileFrom(descriptorData,\n"
+ " .internalBuildGeneratedFileFrom(descriptorData,\n");
+ printer->Print(
" new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
for (int i = 0; i < dependencies.size(); i++) {
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h
index 1bb2f3dc..fdbe2ce8 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.h
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
@@ -68,6 +71,7 @@ class SharedCodeGenerator {
void Generate(GeneratorContext* generator_context,
vector<string>* file_list);
+
void GenerateDescriptors(io::Printer* printer);
private:
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 8889a744..1c9302af 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -407,6 +407,15 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_has_field_bit_message$\n"
"$name$_ = s;\n");
+ } else if (!HasDescriptorMethods(descriptor_->file())) {
+ // Lite runtime should attempt to reduce allocations by attempting to
+ // construct the string directly from the input stream buffer. This avoids
+ // spurious intermediary ByteString allocations, cutting overall allocations
+ // in half.
+ printer->Print(variables_,
+ "String s = input.readString();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = s;\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -659,6 +668,15 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_oneof_case_message$;\n"
"$oneof_name$_ = s;\n}\n");
+ } else if (!HasDescriptorMethods(descriptor_->file())) {
+ // Lite runtime should attempt to reduce allocations by attempting to
+ // construct the string directly from the input stream buffer. This avoids
+ // spurious intermediary ByteString allocations, cutting overall allocations
+ // in half.
+ printer->Print(variables_,
+ "String s = input.readString();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = s;\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -923,6 +941,13 @@ GenerateParsingCode(io::Printer* printer) const {
if (CheckUtf8(descriptor_)) {
printer->Print(variables_,
"String s = input.readStringRequireUtf8();\n");
+ } else if (!HasDescriptorMethods(descriptor_->file())) {
+ // Lite runtime should attempt to reduce allocations by attempting to
+ // construct the string directly from the input stream buffer. This avoids
+ // spurious intermediary ByteString allocations, cutting overall allocations
+ // in half.
+ printer->Print(variables_,
+ "String s = input.readString();\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n");
@@ -932,7 +957,7 @@ GenerateParsingCode(io::Printer* printer) const {
" $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
" $set_mutable_bit_parser$;\n"
"}\n");
- if (CheckUtf8(descriptor_)) {
+ if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
printer->Print(variables_,
"$name$_.add(s);\n");
} else {
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 916b0ccd..70373c8e 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -33,6 +33,9 @@
#include <google/protobuf/compiler/mock_code_generator.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/testing/file.h>
#include <google/protobuf/descriptor.pb.h>
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 474a8f80..0ed80d54 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -84,6 +84,32 @@ TypeNameMap MakeTypeNameTable() {
const TypeNameMap kTypeNames = MakeTypeNameTable();
+// Camel-case the field name and append "Entry" for generated map entry name.
+// e.g. map<KeyType, ValueType> foo_map => FooMapEntry
+string MapEntryName(const string& field_name) {
+ string result;
+ static const char kSuffix[] = "Entry";
+ result.reserve(field_name.size() + sizeof(kSuffix));
+ bool cap_next = true;
+ for (int i = 0; i < field_name.size(); ++i) {
+ if (field_name[i] == '_') {
+ cap_next = true;
+ } else if (cap_next) {
+ // Note: Do not use ctype.h due to locales.
+ if ('a' <= field_name[i] && field_name[i] <= 'z') {
+ result.push_back(field_name[i] - 'a' + 'A');
+ } else {
+ result.push_back(field_name[i]);
+ }
+ cap_next = false;
+ } else {
+ result.push_back(field_name[i]);
+ }
+ }
+ result.append(kSuffix);
+ return result;
+}
+
} // anonymous namespace
// Makes code slightly more readable. The meaning of "DO(foo)" is
@@ -439,6 +465,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
// identifier.
return false;
}
+ // Store the syntax into the file.
+ if (file != NULL) file->set_syntax(syntax_identifier_);
} else if (!stop_after_syntax_identifier_) {
syntax_identifier_ = "proto2";
}
@@ -467,7 +495,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
}
bool Parser::ParseSyntaxIdentifier() {
- DO(Consume("syntax", "File must begin with 'syntax = \"proto2\";'."));
+ DO(Consume(
+ "syntax",
+ "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
DO(Consume("="));
io::Tokenizer::Token syntax_token = input_->current();
string syntax;
@@ -476,10 +506,11 @@ bool Parser::ParseSyntaxIdentifier() {
syntax_identifier_ = syntax;
- if (syntax != "proto2" && !stop_after_syntax_identifier_) {
+ if (syntax != "proto2" && syntax != "proto3" &&
+ !stop_after_syntax_identifier_) {
AddError(syntax_token.line, syntax_token.column,
"Unrecognized syntax identifier \"" + syntax + "\". This parser "
- "only recognizes \"proto2\".");
+ "only recognizes \"proto2\" and \"proto3\".");
return false;
}
@@ -673,8 +704,9 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
LocationRecorder location(field_location,
FieldDescriptorProto::kLabelFieldNumber);
FieldDescriptorProto::Label label;
- DO(ParseLabel(&label, containing_file));
- field->set_label(label);
+ if (ParseLabel(&label, containing_file)) {
+ field->set_label(label);
+ }
}
return ParseMessageFieldNoLabel(field, messages, parent_location,
@@ -690,20 +722,75 @@ bool Parser::ParseMessageFieldNoLabel(
int location_field_number_for_nested_type,
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file) {
+ MapField map_field;
// Parse type.
{
LocationRecorder location(field_location); // add path later
location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE);
+ bool type_parsed = false;
FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
string type_name;
- DO(ParseType(&type, &type_name));
- if (type_name.empty()) {
- location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
- field->set_type(type);
- } else {
+
+ // Special case map field. We only treat the field as a map field if the
+ // field type name starts with the word "map" with a following "<".
+ if (TryConsume("map")) {
+ if (LookingAt("<")) {
+ map_field.is_map_field = true;
+ } else {
+ // False positive
+ type_parsed = true;
+ type_name = "map";
+ }
+ }
+ if (map_field.is_map_field) {
+ if (field->has_oneof_index()) {
+ AddError("Map fields are not allowed in oneofs.");
+ return false;
+ }
+ if (field->has_label()) {
+ AddError(
+ "Field labels (required/optional/repeated) are not allowed on "
+ "map fields.");
+ return false;
+ }
+ if (field->has_extendee()) {
+ AddError("Map fields are not allowed to be extensions.");
+ return false;
+ }
+ field->set_label(FieldDescriptorProto::LABEL_REPEATED);
+ DO(Consume("<"));
+ DO(ParseType(&map_field.key_type, &map_field.key_type_name));
+ DO(Consume(","));
+ DO(ParseType(&map_field.value_type, &map_field.value_type_name));
+ DO(Consume(">"));
+ // Defer setting of the type name of the map field until the
+ // field name is parsed. Add the source location though.
location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
- field->set_type_name(type_name);
+ } else {
+ // Handle the case where no explicit label is given for a non-map field.
+ if (!field->has_label() && DefaultToOptionalFields()) {
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ }
+ if (!field->has_label()) {
+ AddError("Expected \"required\", \"optional\", or \"repeated\".");
+ // We can actually reasonably recover here by just assuming the user
+ // forgot the label altogether.
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ }
+
+ // Handle the case where the actual type is a message or enum named "map",
+ // which we already consumed in the code above.
+ if (!type_parsed) {
+ DO(ParseType(&type, &type_name));
+ }
+ if (type_name.empty()) {
+ location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
+ field->set_type(type);
+ } else {
+ location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+ field->set_type_name(type_name);
+ }
}
}
@@ -781,9 +868,42 @@ bool Parser::ParseMessageFieldNoLabel(
DO(ConsumeEndOfDeclaration(";", &field_location));
}
+ // Create a map entry type if this is a map field.
+ if (map_field.is_map_field) {
+ GenerateMapEntry(map_field, field, messages);
+ }
+
return true;
}
+void Parser::GenerateMapEntry(const MapField& map_field,
+ FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages) {
+ DescriptorProto* entry = messages->Add();
+ string entry_name = MapEntryName(field->name());
+ field->set_type_name(entry_name);
+ entry->set_name(entry_name);
+ entry->mutable_options()->set_map_entry(true);
+ FieldDescriptorProto* key_field = entry->add_field();
+ key_field->set_name("key");
+ key_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ key_field->set_number(1);
+ if (map_field.key_type_name.empty()) {
+ key_field->set_type(map_field.key_type);
+ } else {
+ key_field->set_type_name(map_field.key_type_name);
+ }
+ FieldDescriptorProto* value_field = entry->add_field();
+ value_field->set_name("value");
+ value_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ value_field->set_number(2);
+ if (map_field.value_type_name.empty()) {
+ value_field->set_type(map_field.value_type);
+ } else {
+ value_field->set_type_name(map_field.value_type_name);
+ }
+}
+
bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file) {
@@ -1588,13 +1708,8 @@ bool Parser::ParseLabel(FieldDescriptorProto::Label* label,
} else if (TryConsume("required")) {
*label = FieldDescriptorProto::LABEL_REQUIRED;
return true;
- } else {
- AddError("Expected \"required\", \"optional\", or \"repeated\".");
- // We can actually reasonably recover here by just assuming the user
- // forgot the label altogether.
- *label = FieldDescriptorProto::LABEL_OPTIONAL;
- return true;
}
+ return false;
}
bool Parser::ParseType(FieldDescriptorProto::Type* type,
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index d0a2359b..a15cc705 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -403,7 +403,7 @@ class LIBPROTOBUF_EXPORT Parser {
Message* mutable_options);
// Parse "required", "optional", or "repeated" and fill in "label"
- // with the value.
+ // with the value. Returns true if shuch a label is consumed.
bool ParseLabel(FieldDescriptorProto::Label* label,
const FileDescriptorProto* containing_file);
@@ -460,6 +460,28 @@ class LIBPROTOBUF_EXPORT Parser {
// the ending brace.
bool ParseUninterpretedBlock(string* value);
+ struct MapField {
+ // Whether the field is a map field.
+ bool is_map_field;
+ // The types of the key and value if they are primitive types.
+ FieldDescriptorProto::Type key_type;
+ FieldDescriptorProto::Type value_type;
+ // Or the type names string if the types are customized types.
+ string key_type_name;
+ string value_type_name;
+
+ MapField() : is_map_field(false) {}
+ };
+ // Desugar the map syntax to generate a nested map entry message.
+ void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages);
+
+ // Whether fields without label default to optional fields.
+ bool DefaultToOptionalFields() const {
+ return syntax_identifier_ == "proto3";
+ }
+
+
// =================================================================
io::Tokenizer* input_;
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 9ec29a48..c2206ade 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -33,6 +33,9 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <algorithm>
#include <map>
@@ -250,6 +253,7 @@ TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
" required int32 foo = 1;\n"
"}\n",
+ "syntax: 'proto2' "
"message_type {"
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
@@ -265,6 +269,7 @@ TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
" required int32 foo = 1;\n"
"}\n",
+ "syntax: 'proto2' "
"message_type {"
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
@@ -500,6 +505,54 @@ TEST_F(ParseMessageTest, MultipleOneofs) {
"}");
}
+TEST_F(ParseMessageTest, Maps) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " map<int32, string> primitive_type_map = 1;\n"
+ " map<KeyType, ValueType> composite_type_map = 2;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " nested_type {"
+ " name: \"PrimitiveTypeMapEntry\""
+ " field { "
+ " name: \"key\" number: 1 label:LABEL_OPTIONAL"
+ " type:TYPE_INT32"
+ " }"
+ " field { "
+ " name: \"value\" number: 2 label:LABEL_OPTIONAL"
+ " type:TYPE_STRING"
+ " }"
+ " options { map_entry: true }"
+ " }"
+ " nested_type {"
+ " name: \"CompositeTypeMapEntry\""
+ " field { "
+ " name: \"key\" number: 1 label:LABEL_OPTIONAL"
+ " type_name: \"KeyType\""
+ " }"
+ " field { "
+ " name: \"value\" number: 2 label:LABEL_OPTIONAL"
+ " type_name: \"ValueType\""
+ " }"
+ " options { map_entry: true }"
+ " }"
+ " field {"
+ " name: \"primitive_type_map\""
+ " label: LABEL_REPEATED"
+ " type_name: \"PrimitiveTypeMapEntry\""
+ " number: 1"
+ " }"
+ " field {"
+ " name: \"composite_type_map\""
+ " label: LABEL_REPEATED"
+ " type_name: \"CompositeTypeMapEntry\""
+ " number: 2"
+ " }"
+ "}");
+}
+
TEST_F(ParseMessageTest, Group) {
ExpectParsesTo(
"message TestMessage {\n"
@@ -639,6 +692,20 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
" type_name:\"TestMessage\" extendee: \"Extendee1\" }");
}
+TEST_F(ParseMessageTest, OptionalOptionalLabelProto3) {
+ ExpectParsesTo(
+ "syntax = \"proto3\";\n"
+ "message TestMessage {\n"
+ " int32 foo = 1;\n"
+ " optional int32 bar = 2;\n"
+ "}\n",
+
+ "syntax: \"proto3\" "
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
+ " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 } }");
+}
// ===================================================================
@@ -828,9 +895,9 @@ typedef ParserTest ParseErrorTest;
TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
require_syntax_identifier_ = true;
- ExpectHasEarlyExitErrors(
- "message TestMessage {}",
- "0:0: File must begin with 'syntax = \"proto2\";'.\n");
+ ExpectHasEarlyExitErrors("message TestMessage {}",
+ "0:0: File must begin with a syntax statement, e.g. "
+ "'syntax = \"proto2\";'.\n");
EXPECT_EQ("", parser_->GetSyntaxIdentifier());
}
@@ -838,7 +905,7 @@ TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
ExpectHasEarlyExitErrors(
"syntax = \"no_such_syntax\";",
"0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser "
- "only recognizes \"proto2\".\n");
+ "only recognizes \"proto2\" and \"proto3\".\n");
EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
}
@@ -1041,6 +1108,55 @@ TEST_F(ParseErrorTest, LabelInOneof) {
"/ repeated).\n");
}
+TEST_F(ParseErrorTest, MapInOneof) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " oneof foo {\n"
+ " map<int32, int32> foo_map = 1;\n"
+ " map message_field = 2;\n" // a normal message field is OK
+ " }\n"
+ "}\n",
+ "2:7: Map fields are not allowed in oneofs.\n");
+}
+
+TEST_F(ParseErrorTest, LabelForMap) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional map<int32, int32> int_map = 1;\n"
+ " required map<int32, int32> int_map2 = 2;\n"
+ " repeated map<int32, int32> int_map3 = 3;\n"
+ " optional map map_message = 4;\n" // a normal message field is OK
+ "}\n",
+ "1:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n"
+ "2:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n"
+ "3:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n");
+}
+
+TEST_F(ParseErrorTest, MalformedMaps) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " map map_message = 1;\n" // a normal message field lacking label
+ " map<string> str_map = 2;\n"
+ " map<string,> str_map2 = 3;\n"
+ " map<,string> str_map3 = 4;\n"
+ " map<> empty_map = 5;\n"
+ " map<string,string str_map6 = 6;\n"
+ "}"
+ "extend SomeMessage {\n"
+ " map<int32, int32> int_map = 1;\n"
+ "}",
+ "1:6: Expected \"required\", \"optional\", or \"repeated\".\n"
+ "2:12: Expected \",\".\n"
+ "3:13: Expected type name.\n"
+ "4:6: Expected type name.\n"
+ "5:6: Expected type name.\n"
+ "6:20: Expected \">\".\n"
+ "8:5: Map fields are not allowed to be extensions.\n");
+}
+
TEST_F(ParseErrorTest, GroupNotCapitalized) {
ExpectHasErrors(
"message TestMessage {\n"
@@ -1413,7 +1529,7 @@ TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) {
// definitions again afoter parsing (note, however, that the order of messages
// cannot be guaranteed to be the same)
-typedef ParserTest ParseDecriptorDebugTest;
+typedef ParserTest ParseDescriptorDebugTest;
class CompareDescriptorNames {
public:
@@ -1447,7 +1563,28 @@ void SortMessages(FileDescriptorProto *file_descriptor_proto) {
sort(data, data + size, CompareDescriptorNames());
}
-TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
+// Strips the message and enum field type names for comparison purpose only.
+void StripFieldTypeName(DescriptorProto* proto) {
+ for (int i = 0; i < proto->field_size(); ++i) {
+ string type_name = proto->field(i).type_name();
+ string::size_type pos = type_name.find_last_of(".");
+ if (pos != string::npos) {
+ proto->mutable_field(i)->mutable_type_name()->assign(
+ type_name.begin() + pos + 1, type_name.end());
+ }
+ }
+ for (int i = 0; i < proto->nested_type_size(); ++i) {
+ StripFieldTypeName(proto->mutable_nested_type(i));
+ }
+}
+
+void StripFieldTypeName(FileDescriptorProto* file_proto) {
+ for (int i = 0; i < file_proto->message_type_size(); ++i) {
+ StripFieldTypeName(file_proto->mutable_message_type(i));
+ }
+}
+
+TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) {
const FileDescriptor* original_file =
protobuf_unittest::TestAllTypes::descriptor()->file();
FileDescriptorProto expected;
@@ -1499,7 +1636,7 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
EXPECT_EQ(expected.DebugString(), parsed.DebugString());
}
-TEST_F(ParseDecriptorDebugTest, TestCustomOptions) {
+TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
const FileDescriptor* original_file =
protobuf_unittest::AggregateMessage::descriptor()->file();
FileDescriptorProto expected;
@@ -1538,6 +1675,106 @@ TEST_F(ParseDecriptorDebugTest, TestCustomOptions) {
EXPECT_EQ(expected.DebugString(), parsed.DebugString());
}
+// Ensure that DebugStringWithOptions(), with |include_comments| set to true,
+// includes comments from the original parser input in all of the appropriate
+// places.
+TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
+ SetupParser(
+ "// Message comment.\n"
+ "message TestMessage1 {\n"
+ " // Field comment.\n"
+ " optional int32 foo = 1;\n"
+ "\n"
+ " // Nested-message comment.\n"
+ " message NestedMessage {\n"
+ " optional int32 bar = 1;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "// Enum comment.\n"
+ "enum MyEnumType {\n"
+ " // Enum-value comment.\n"
+ " ASDF = 1;\n"
+ "}\n"
+ "\n"
+ "// Service comment.\n"
+ "service MyService {\n"
+ " // RPC comment.\n"
+ " rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
+ "}\n");
+
+ FileDescriptorProto parsed_desc;
+ parsed_desc.set_name("foo.proto");
+ SourceLocationTable source_locations;
+ parser_->RecordSourceLocationsTo(&source_locations);
+ parser_->Parse(input_.get(), &parsed_desc);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_);
+
+ // We need to import the FileDescriptorProto to get a FileDescriptor.
+ MockValidationErrorCollector collector(source_locations, &error_collector_);
+ const FileDescriptor* descriptor =
+ pool_.BuildFileCollectingErrors(parsed_desc, &collector);
+ ASSERT_TRUE(descriptor != NULL);
+
+ DebugStringOptions debug_string_options;
+ debug_string_options.include_comments = true;
+ const string debug_string =
+ descriptor->DebugStringWithOptions(debug_string_options);
+
+ // Ensure that each of the comments appears somewhere in the DebugString(),
+ // and that these comments appear in order. We don't test the exact comment
+ // placement or formatting, because we do not want to be too fragile here.
+ const char* expected_comments[] = {
+ "Message comment.",
+ "Field comment",
+ "Nested-message comment",
+ "Enum comment",
+ "Enum-value comment",
+ "Service comment",
+ "RPC comment",
+ };
+
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
+ string::size_type found_pos = debug_string.find(expected_comments[i]);
+ ASSERT_TRUE(found_pos != string::npos);
+ }
+}
+
+TEST_F(ParseDescriptorDebugTest, TestMaps) {
+ SetupParser(
+ "syntax = \"proto3\"; "
+ "message Foo { "
+ " message Bar { } "
+ " map<int32, Bar> enum_message_map = 1; "
+ " map<string, float> primitive_map = 2; "
+ "} ");
+ FileDescriptorProto original;
+ EXPECT_TRUE(parser_->Parse(input_.get(), &original));
+ original.set_name("foo.proto");
+ const FileDescriptor* file = pool_.BuildFile(original);
+ ASSERT_TRUE(file != NULL);
+
+ // Make sure the debug string uses map syntax and does not have the auto
+ // generated entry.
+ string debug_string = file->DebugString();
+ EXPECT_TRUE(debug_string.find("map<") != string::npos);
+ EXPECT_TRUE(debug_string.find("option map_entry") == string::npos);
+ EXPECT_TRUE(debug_string.find("MapEntry") == string::npos);
+
+ // Make sure the descriptor debug string is parsable.
+ FileDescriptorProto parsed;
+ SetupParser(debug_string.c_str());
+ parsed.set_name("foo.proto");
+ ASSERT_TRUE(parser_->Parse(input_.get(), &parsed));
+
+ original.clear_source_code_info();
+ parsed.clear_source_code_info();
+ StripFieldTypeName(&original);
+ StripFieldTypeName(&parsed);
+ EXPECT_EQ(original.DebugString(), parsed.DebugString());
+}
+
// ===================================================================
// SourceCodeInfo tests.
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index b5cd01b5..efa64f3d 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -53,11 +53,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorRequest::default_instance_,
CodeGeneratorRequest_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(CodeGeneratorRequest));
+ sizeof(CodeGeneratorRequest),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_));
CodeGeneratorResponse_descriptor_ = file->message_type(1);
static const int CodeGeneratorResponse_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
@@ -69,11 +70,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorResponse::default_instance_,
CodeGeneratorResponse_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(CodeGeneratorResponse));
+ sizeof(CodeGeneratorResponse),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_));
CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
static const int CodeGeneratorResponse_File_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
@@ -86,11 +88,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorResponse_File::default_instance_,
CodeGeneratorResponse_File_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(CodeGeneratorResponse_File));
+ sizeof(CodeGeneratorResponse_File),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_));
}
namespace {
@@ -169,16 +172,27 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorRequest::CodeGeneratorRequest()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
}
+CodeGeneratorRequest::CodeGeneratorRequest(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ file_to_generate_(arena),
+ proto_file_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest)
+}
+
void CodeGeneratorRequest::InitAsDefaultInstance() {
}
CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
@@ -187,7 +201,7 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
void CodeGeneratorRequest::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -197,13 +211,21 @@ CodeGeneratorRequest::~CodeGeneratorRequest() {
}
void CodeGeneratorRequest::SharedDtor() {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete parameter_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ parameter_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void CodeGeneratorRequest::ArenaDtor(void* object) {
+ CodeGeneratorRequest* _this = reinterpret_cast< CodeGeneratorRequest* >(object);
+ (void)_this;
+}
+void CodeGeneratorRequest::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void CodeGeneratorRequest::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -221,20 +243,20 @@ const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
-CodeGeneratorRequest* CodeGeneratorRequest::New() const {
- return new CodeGeneratorRequest;
+CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<CodeGeneratorRequest>(arena);
}
void CodeGeneratorRequest::Clear() {
if (has_parameter()) {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_->clear();
- }
+ parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
file_to_generate_.Clear();
proto_file_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool CodeGeneratorRequest::MergePartialFromCodedStream(
@@ -257,7 +279,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
this->file_to_generate(this->file_to_generate_size() - 1).data(),
this->file_to_generate(this->file_to_generate_size() - 1).length(),
::google::protobuf::internal::WireFormat::PARSE,
- "file_to_generate");
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
} else {
goto handle_unusual;
}
@@ -275,7 +297,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->parameter().data(), this->parameter().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "parameter");
+ "google.protobuf.compiler.CodeGeneratorRequest.parameter");
} else {
goto handle_unusual;
}
@@ -327,7 +349,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->file_to_generate(i).data(), this->file_to_generate(i).length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "file_to_generate");
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->file_to_generate(i), output);
}
@@ -337,7 +359,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->parameter().data(), this->parameter().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "parameter");
+ "google.protobuf.compiler.CodeGeneratorRequest.parameter");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->parameter(), output);
}
@@ -348,7 +370,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
15, this->proto_file(i), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -363,7 +385,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->file_to_generate(i).data(), this->file_to_generate(i).length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "file_to_generate");
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
target = ::google::protobuf::internal::WireFormatLite::
WriteStringToArray(1, this->file_to_generate(i), target);
}
@@ -373,7 +395,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->parameter().data(), this->parameter().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "parameter");
+ "google.protobuf.compiler.CodeGeneratorRequest.parameter");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->parameter(), target);
@@ -386,7 +408,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
15, this->proto_file(i), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -397,15 +419,13 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
int CodeGeneratorRequest::ByteSize() const {
int total_size = 0;
- if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
- // optional string parameter = 2;
- if (has_parameter()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::StringSize(
- this->parameter());
- }
-
+ // optional string parameter = 2;
+ if (has_parameter()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->parameter());
}
+
// repeated string file_to_generate = 1;
total_size += 1 * this->file_to_generate_size();
for (int i = 0; i < this->file_to_generate_size(); i++) {
@@ -421,7 +441,7 @@ int CodeGeneratorRequest::ByteSize() const {
this->proto_file(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -453,7 +473,9 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
set_parameter(from.parameter());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) {
@@ -475,15 +497,29 @@ bool CodeGeneratorRequest::IsInitialized() const {
}
void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
- if (other != this) {
- file_to_generate_.Swap(&other->file_to_generate_);
- std::swap(parameter_, other->parameter_);
- proto_file_.Swap(&other->proto_file_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ CodeGeneratorRequest temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void CodeGeneratorRequest::UnsafeArenaSwap(CodeGeneratorRequest* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
+ file_to_generate_.UnsafeArenaSwap(&other->file_to_generate_);
+ parameter_.Swap(&other->parameter_);
+ proto_file_.UnsafeArenaSwap(&other->proto_file_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -503,16 +539,25 @@ const int CodeGeneratorResponse_File::kContentFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse_File::CodeGeneratorResponse_File()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
}
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+}
+
void CodeGeneratorResponse_File::InitAsDefaultInstance() {
}
CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
@@ -521,9 +566,9 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon
void CodeGeneratorResponse_File::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- 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());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -533,19 +578,23 @@ CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
}
void CodeGeneratorResponse_File::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
- }
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete insertion_point_;
- }
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete content_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ insertion_point_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ content_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void CodeGeneratorResponse_File::ArenaDtor(void* object) {
+ CodeGeneratorResponse_File* _this = reinterpret_cast< CodeGeneratorResponse_File* >(object);
+ (void)_this;
+}
+void CodeGeneratorResponse_File::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void CodeGeneratorResponse_File::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -563,30 +612,26 @@ const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance()
CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
-CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const {
- return new CodeGeneratorResponse_File;
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse_File>(arena);
}
void CodeGeneratorResponse_File::Clear() {
if (_has_bits_[0 / 32] & 7) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_insertion_point()) {
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_->clear();
- }
+ insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_content()) {
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_->clear();
- }
+ content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
@@ -607,7 +652,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.name");
} else {
goto handle_unusual;
}
@@ -624,7 +669,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->insertion_point().data(), this->insertion_point().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "insertion_point");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
} else {
goto handle_unusual;
}
@@ -641,7 +686,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->content().data(), this->content().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "content");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.content");
} else {
goto handle_unusual;
}
@@ -679,7 +724,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -689,7 +734,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->insertion_point().data(), this->insertion_point().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "insertion_point");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->insertion_point(), output);
}
@@ -699,12 +744,12 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->content().data(), this->content().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "content");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.content");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
15, this->content(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -719,7 +764,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -730,7 +775,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->insertion_point().data(), this->insertion_point().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "insertion_point");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->insertion_point(), target);
@@ -741,13 +786,13 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->content().data(), this->content().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "content");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.content");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
15, this->content(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -758,7 +803,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
int CodeGeneratorResponse_File::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 7) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -781,7 +826,7 @@ int CodeGeneratorResponse_File::ByteSize() const {
}
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -817,7 +862,9 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro
set_content(from.content());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) {
@@ -838,15 +885,29 @@ bool CodeGeneratorResponse_File::IsInitialized() const {
}
void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- std::swap(insertion_point_, other->insertion_point_);
- std::swap(content_, other->content_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ CodeGeneratorResponse_File temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void CodeGeneratorResponse_File::UnsafeArenaSwap(CodeGeneratorResponse_File* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
+ name_.Swap(&other->name_);
+ insertion_point_.Swap(&other->insertion_point_);
+ content_.Swap(&other->content_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -865,16 +926,26 @@ const int CodeGeneratorResponse::kFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse::CodeGeneratorResponse()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
+CodeGeneratorResponse::CodeGeneratorResponse(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ file_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse)
+}
+
void CodeGeneratorResponse::InitAsDefaultInstance() {
}
CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
@@ -883,7 +954,7 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
void CodeGeneratorResponse::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -893,13 +964,21 @@ CodeGeneratorResponse::~CodeGeneratorResponse() {
}
void CodeGeneratorResponse::SharedDtor() {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete error_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ error_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void CodeGeneratorResponse::ArenaDtor(void* object) {
+ CodeGeneratorResponse* _this = reinterpret_cast< CodeGeneratorResponse* >(object);
+ (void)_this;
+}
+void CodeGeneratorResponse::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void CodeGeneratorResponse::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -917,19 +996,19 @@ const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
-CodeGeneratorResponse* CodeGeneratorResponse::New() const {
- return new CodeGeneratorResponse;
+CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse>(arena);
}
void CodeGeneratorResponse::Clear() {
if (has_error()) {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_->clear();
- }
+ error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
file_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool CodeGeneratorResponse::MergePartialFromCodedStream(
@@ -950,7 +1029,7 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->error().data(), this->error().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "error");
+ "google.protobuf.compiler.CodeGeneratorResponse.error");
} else {
goto handle_unusual;
}
@@ -1002,7 +1081,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->error().data(), this->error().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "error");
+ "google.protobuf.compiler.CodeGeneratorResponse.error");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->error(), output);
}
@@ -1013,7 +1092,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
15, this->file(i), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -1028,7 +1107,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->error().data(), this->error().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "error");
+ "google.protobuf.compiler.CodeGeneratorResponse.error");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->error(), target);
@@ -1041,7 +1120,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
15, this->file(i), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -1052,15 +1131,13 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
int CodeGeneratorResponse::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // optional string error = 1;
- if (has_error()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::StringSize(
- this->error());
- }
-
+ // optional string error = 1;
+ if (has_error()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->error());
}
+
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
total_size += 1 * this->file_size();
for (int i = 0; i < this->file_size(); i++) {
@@ -1069,7 +1146,7 @@ int CodeGeneratorResponse::ByteSize() const {
this->file(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -1100,7 +1177,9 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
set_error(from.error());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) {
@@ -1121,14 +1200,28 @@ bool CodeGeneratorResponse::IsInitialized() const {
}
void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
- if (other != this) {
- std::swap(error_, other->error_);
- file_.Swap(&other->file_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ CodeGeneratorResponse temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void CodeGeneratorResponse::UnsafeArenaSwap(CodeGeneratorResponse* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
+ error_.Swap(&other->error_);
+ file_.UnsafeArenaSwap(&other->file_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 567b30ef..636992a6 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -5,6 +5,7 @@
#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
#include <string>
+#include <stdint.h>
#include <google/protobuf/stubs/common.h>
@@ -19,7 +20,10 @@
#error regenerate this file with a newer version of protoc.
#endif
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
@@ -55,21 +59,28 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorRequest& default_instance();
+ void UnsafeArenaSwap(CodeGeneratorRequest* other);
void Swap(CodeGeneratorRequest* other);
// implements Message ----------------------------------------------
- CodeGeneratorRequest* New() const;
+ inline CodeGeneratorRequest* New() const { return New(NULL); }
+
+ CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const CodeGeneratorRequest& from);
@@ -88,7 +99,21 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(CodeGeneratorRequest* other);
+ protected:
+ explicit CodeGeneratorRequest(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -122,6 +147,9 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
inline ::std::string* mutable_parameter();
inline ::std::string* release_parameter();
inline void set_allocated_parameter(::std::string* parameter);
+ inline ::std::string* unsafe_arena_release_parameter();
+ inline void unsafe_arena_set_allocated_parameter(
+ ::std::string* parameter);
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
inline int proto_file_size() const;
@@ -140,12 +168,14 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
inline void set_has_parameter();
inline void clear_has_parameter();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
- ::std::string* parameter_;
+ ::google::protobuf::internal::ArenaStringPtr parameter_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
@@ -169,21 +199,28 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse_File& default_instance();
+ void UnsafeArenaSwap(CodeGeneratorResponse_File* other);
void Swap(CodeGeneratorResponse_File* other);
// implements Message ----------------------------------------------
- CodeGeneratorResponse_File* New() const;
+ inline CodeGeneratorResponse_File* New() const { return New(NULL); }
+
+ CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const CodeGeneratorResponse_File& from);
@@ -202,7 +239,21 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(CodeGeneratorResponse_File* other);
+ protected:
+ explicit CodeGeneratorResponse_File(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -220,6 +271,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// optional string insertion_point = 2;
inline bool has_insertion_point() const;
@@ -232,6 +286,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline ::std::string* mutable_insertion_point();
inline ::std::string* release_insertion_point();
inline void set_allocated_insertion_point(::std::string* insertion_point);
+ inline ::std::string* unsafe_arena_release_insertion_point();
+ inline void unsafe_arena_set_allocated_insertion_point(
+ ::std::string* insertion_point);
// optional string content = 15;
inline bool has_content() const;
@@ -244,6 +301,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline ::std::string* mutable_content();
inline ::std::string* release_content();
inline void set_allocated_content(::std::string* content);
+ inline ::std::string* unsafe_arena_release_content();
+ inline void unsafe_arena_set_allocated_content(
+ ::std::string* content);
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
private:
@@ -254,13 +314,15 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline void set_has_content();
inline void clear_has_content();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
- ::std::string* insertion_point_;
- ::std::string* content_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::internal::ArenaStringPtr insertion_point_;
+ ::google::protobuf::internal::ArenaStringPtr content_;
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
@@ -283,21 +345,28 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse& default_instance();
+ void UnsafeArenaSwap(CodeGeneratorResponse* other);
void Swap(CodeGeneratorResponse* other);
// implements Message ----------------------------------------------
- CodeGeneratorResponse* New() const;
+ inline CodeGeneratorResponse* New() const { return New(NULL); }
+
+ CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const CodeGeneratorResponse& from);
@@ -316,7 +385,21 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(CodeGeneratorResponse* other);
+ protected:
+ explicit CodeGeneratorResponse(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -336,6 +419,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
inline ::std::string* mutable_error();
inline ::std::string* release_error();
inline void set_allocated_error(::std::string* error);
+ inline ::std::string* unsafe_arena_release_error();
+ inline void unsafe_arena_set_allocated_error(
+ ::std::string* error);
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
inline int file_size() const;
@@ -354,11 +440,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
inline void set_has_error();
inline void clear_has_error();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* error_;
+ ::google::protobuf::internal::ArenaStringPtr error_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
@@ -439,68 +527,67 @@ inline void CodeGeneratorRequest::clear_has_parameter() {
_has_bits_[0] &= ~0x00000002u;
}
inline void CodeGeneratorRequest::clear_parameter() {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_->clear();
- }
+ parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_parameter();
}
inline const ::std::string& CodeGeneratorRequest::parameter() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
- return *parameter_;
+ return parameter_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
set_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
- parameter_->assign(value);
+ parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
- parameter_->assign(value);
+ parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
-inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+inline void CodeGeneratorRequest::set_parameter(const char* value,
+ size_t size) {
set_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
- parameter_->assign(reinterpret_cast<const char*>(value), size);
+ parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
- return parameter_;
+ return parameter_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorRequest::release_parameter() {
clear_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = parameter_;
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return parameter_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorRequest::unsafe_arena_release_parameter() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_parameter();
+ return parameter_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete parameter_;
+ if (parameter != NULL) {
+ set_has_parameter();
+ } else {
+ clear_has_parameter();
}
- if (parameter) {
+ parameter_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+inline void CodeGeneratorRequest::unsafe_arena_set_allocated_parameter(
+ ::std::string* parameter) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (parameter != NULL) {
set_has_parameter();
- parameter_ = parameter;
} else {
clear_has_parameter();
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_parameter();
+ parameter_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ parameter, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
@@ -549,68 +636,67 @@ inline void CodeGeneratorResponse_File::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void CodeGeneratorResponse_File::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& CodeGeneratorResponse_File::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
-inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+inline void CodeGeneratorResponse_File::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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse_File::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
@@ -625,68 +711,67 @@ 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::GetEmptyStringAlreadyInited()) {
- insertion_point_->clear();
- }
+ insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return insertion_point_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
set_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
- insertion_point_->assign(value);
+ insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
- insertion_point_->assign(value);
+ insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@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) {
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value,
+ size_t size) {
set_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
- insertion_point_->assign(reinterpret_cast<const char*>(value), size);
+ insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
- return insertion_point_;
+ return insertion_point_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
clear_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = insertion_point_;
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return insertion_point_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_insertion_point() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_insertion_point();
+ return insertion_point_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete insertion_point_;
+ if (insertion_point != NULL) {
+ set_has_insertion_point();
+ } else {
+ clear_has_insertion_point();
}
- if (insertion_point) {
+ insertion_point_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_insertion_point(
+ ::std::string* insertion_point) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (insertion_point != NULL) {
set_has_insertion_point();
- insertion_point_ = insertion_point;
} else {
clear_has_insertion_point();
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_insertion_point();
+ insertion_point_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ insertion_point, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
@@ -701,68 +786,67 @@ inline void CodeGeneratorResponse_File::clear_has_content() {
_has_bits_[0] &= ~0x00000004u;
}
inline void CodeGeneratorResponse_File::clear_content() {
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_->clear();
- }
+ content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_content();
}
inline const ::std::string& CodeGeneratorResponse_File::content() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
- return *content_;
+ return content_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
set_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
- content_->assign(value);
+ content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
- content_->assign(value);
+ content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
-inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+inline void CodeGeneratorResponse_File::set_content(const char* value,
+ size_t size) {
set_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
- content_->assign(reinterpret_cast<const char*>(value), size);
+ content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
- return content_;
+ return content_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse_File::release_content() {
clear_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = content_;
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return content_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_content() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_content();
+ return content_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete content_;
+ if (content != NULL) {
+ set_has_content();
+ } else {
+ clear_has_content();
}
- if (content) {
+ content_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_content(
+ ::std::string* content) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (content != NULL) {
set_has_content();
- content_ = content;
} else {
clear_has_content();
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_content();
+ content_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ content, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
@@ -781,68 +865,67 @@ inline void CodeGeneratorResponse::clear_has_error() {
_has_bits_[0] &= ~0x00000001u;
}
inline void CodeGeneratorResponse::clear_error() {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_->clear();
- }
+ error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_error();
}
inline const ::std::string& CodeGeneratorResponse::error() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
- return *error_;
+ return error_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
set_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
- error_->assign(value);
+ error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
- error_->assign(value);
+ error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
}
-inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+inline void CodeGeneratorResponse::set_error(const char* value,
+ size_t size) {
set_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
- error_->assign(reinterpret_cast<const char*>(value), size);
+ error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
- return error_;
+ return error_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse::release_error() {
clear_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = error_;
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return error_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse::unsafe_arena_release_error() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_error();
+ return error_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete error_;
+ if (error != NULL) {
+ set_has_error();
+ } else {
+ clear_has_error();
}
- if (error) {
+ error_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+inline void CodeGeneratorResponse::unsafe_arena_set_allocated_error(
+ ::std::string* error) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (error != NULL) {
set_has_error();
- error_ = error;
} else {
clear_has_error();
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_error();
+ error_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ error, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
}
@@ -888,8 +971,8 @@ namespace google {
namespace protobuf {
-} // namespace google
} // namespace protobuf
+} // namespace google
#endif // SWIG
// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index b65379d7..e627289b 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -44,6 +44,7 @@
// plugin should be named "protoc-gen-$NAME", and will then be used when the
// flag "--${NAME}_out" is passed to protoc.
+syntax = "proto2";
package google.protobuf.compiler;
option java_package = "com.google.protobuf.compiler";
option java_outer_classname = "PluginProtos";
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 15e05da9..d72ca207 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -44,11 +44,15 @@
// performance-minded Python code leverage the fast C++ implementation
// directly.
+#include <google/protobuf/stubs/hash.h>
#include <limits>
#include <map>
-#include <utility>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
+#include <utility>
#include <vector>
#include <google/protobuf/compiler/python/python_generator.h>
@@ -69,6 +73,41 @@ namespace python {
namespace {
+const char* const kKeywordList[] = {
+ "and", "as", "break", "class", "continue", "def", "elif", "else", "except",
+ "False", "for", "from", "if", "import", "not", "or", "raise", "return",
+ "True", "try", "with", "while", "yield"
+};
+
+hash_set<string> MakeKeywordsMap() {
+ hash_set<string> result;
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); ++i) {
+ result.insert(kKeywordList[i]);
+ }
+ return result;
+}
+
+hash_set<string>* keywords_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(keywords_once_);
+
+void InitKeywords() {
+ keywords_ = new hash_set<string>();
+ *keywords_ = MakeKeywordsMap();
+}
+
+hash_set<string>& GetKeywords() {
+ ::google::protobuf::GoogleOnceInit(&keywords_once_, &InitKeywords);
+ return *keywords_;
+}
+
+string FieldName(const FieldDescriptor& field) {
+ string result = field.name();
+ if (GetKeywords().count(result) > 0) {
+ result.append("_");
+ }
+ return result;
+}
+
// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
// suffix stripped.
// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
@@ -88,6 +127,37 @@ string ModuleName(const string& filename) {
}
+// Returns the alias we assign to the module of the given .proto filename
+// when importing. See testPackageInitializationImport in
+// google/protobuf/python/reflection_test.py
+// to see why we need the alias.
+string ModuleAlias(const string& filename) {
+ string module_name = ModuleName(filename);
+ // We can't have dots in the module name, so we replace each with _dot_.
+ // But that could lead to a collision between a.b and a_dot_b, so we also
+ // duplicate each underscore.
+ GlobalReplaceSubstring("_", "__", &module_name);
+ GlobalReplaceSubstring(".", "_dot_", &module_name);
+ return module_name;
+}
+
+
+// Returns an import statement of form "from X.Y.Z import T" for the given
+// .proto filename.
+string ModuleImportStatement(const string& filename) {
+ string module_name = ModuleName(filename);
+ int last_dot_pos = module_name.rfind('.');
+ if (last_dot_pos == string::npos) {
+ // NOTE(petya): this is not tested as it would require a protocol buffer
+ // outside of any package, and I don't think that is easily achievable.
+ return "import " + module_name;
+ } else {
+ return "from " + module_name.substr(0, last_dot_pos) + " import " +
+ module_name.substr(last_dot_pos + 1);
+ }
+}
+
+
// Returns the name of all containing types for descriptor,
// in order from outermost to innermost, followed by descriptor's
// own name. Each name is separated by |separator|.
@@ -309,9 +379,12 @@ bool Generator::Generate(const FileDescriptor* file,
// Prints Python imports for all modules imported by |file|.
void Generator::PrintImports() const {
for (int i = 0; i < file_->dependency_count(); ++i) {
- string module_name = ModuleName(file_->dependency(i)->name());
- printer_->Print("import $module$\n", "module",
- module_name);
+ const string& filename = file_->dependency(i)->name();
+ string import_statement = ModuleImportStatement(filename);
+ string module_alias = ModuleAlias(filename);
+ printer_->Print("$statement$ as $alias$\n", "statement",
+ import_statement, "alias", module_alias);
+ CopyPublicDependenciesAliases(module_alias, file_->dependency(i));
}
printer_->Print("\n");
@@ -342,8 +415,9 @@ void Generator::PrintFileDescriptor() const {
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);
+ string module_alias = ModuleAlias(file_->dependency(i)->name());
+ printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+ module_alias);
}
printer_->Print("]");
}
@@ -457,7 +531,7 @@ void Generator::PrintTopLevelExtensions() const {
printer_->Print("$constant_name$ = $number$\n",
"constant_name", constant_name,
"number", SimpleItoa(extension_field.number()));
- printer_->Print("$name$ = ", "name", extension_field.name());
+ printer_->Print("$name$ = ", "name", FieldName(extension_field));
PrintFieldDescriptor(extension_field, is_extension);
printer_->Print("\n");
}
@@ -804,7 +878,7 @@ void Generator::AddExtensionToFileDescriptor(
const FieldDescriptor& descriptor) const {
map<string, string> m;
m["descriptor_name"] = kDescriptorKey;
- m["field_name"] = descriptor.name();
+ m["field_name"] = FieldName(descriptor);
const char file_descriptor_template[] =
"$descriptor_name$.extensions_by_name['$field_name$'] = "
"$field_name$\n";
@@ -857,12 +931,12 @@ string Generator::FieldReferencingExpression(
GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
<< file_->name();
if (!containing_type) {
- return field.name();
+ return FieldName(field);
}
return strings::Substitute(
"$0.$1['$2']",
ModuleLevelDescriptorName(*containing_type),
- python_dict_name, field.name());
+ python_dict_name, FieldName(field));
}
// Prints containing_type for nested descriptors or enum descriptors.
@@ -991,7 +1065,7 @@ void Generator::PrintFieldDescriptor(
string options_string;
field.options().SerializeToString(&options_string);
map<string, string> m;
- m["name"] = field.name();
+ m["name"] = FieldName(field);
m["full_name"] = field.full_name();
m["index"] = SimpleItoa(field.index());
m["number"] = SimpleItoa(field.number());
@@ -1084,7 +1158,7 @@ string Generator::ModuleLevelDescriptorName(
// We now have the name relative to its own module. Also qualify with
// the module name iff this descriptor is from a different .proto file.
if (descriptor.file() != file_) {
- name = ModuleName(descriptor.file()->name()) + "." + name;
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
}
return name;
}
@@ -1096,7 +1170,7 @@ string Generator::ModuleLevelDescriptorName(
string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const {
string name = NamePrefixedWithNestedTypes(descriptor, ".");
if (descriptor.file() != file_) {
- name = ModuleName(descriptor.file()->name()) + "." + name;
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
}
return name;
}
@@ -1109,7 +1183,7 @@ string Generator::ModuleLevelServiceDescriptorName(
UpperString(&name);
name = "_" + name;
if (descriptor.file() != file_) {
- name = ModuleName(descriptor.file()->name()) + "." + name;
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
}
return name;
}
@@ -1211,7 +1285,7 @@ void Generator::FixOptionsForField(
if (field.is_extension()) {
if (field.extension_scope() == NULL) {
// Top level extensions.
- field_name = field.name();
+ field_name = FieldName(field);
} else {
field_name = FieldReferencingExpression(
field.extension_scope(), field, "extensions_by_name");
@@ -1256,6 +1330,18 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
}
}
+// If a dependency forwards other files through public dependencies, let's
+// copy over the corresponding module aliases.
+void Generator::CopyPublicDependenciesAliases(
+ const string& copy_from, const FileDescriptor* file) const {
+ for (int i = 0; i < file->public_dependency_count(); ++i) {
+ string module_alias = ModuleAlias(file->public_dependency(i)->name());
+ printer_->Print("$alias$ = $copy_from$.$alias$\n", "alias", module_alias,
+ "copy_from", copy_from);
+ CopyPublicDependenciesAliases(copy_from, file->public_dependency(i));
+ }
+}
+
} // namespace python
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index f86e9ea2..7e8f58e5 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -148,6 +148,9 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
void FixOptionsForMessage(const Descriptor& descriptor) const;
+ void CopyPublicDependenciesAliases(
+ const string& copy_from, const FileDescriptor* file) const;
+
// Very coarse-grained lock to ensure that Generate() is reentrant.
// Guards file_, printer_ and file_descriptor_serialized_.
mutable Mutex mutex_;
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index 09dbc654..24c2f971 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -35,6 +35,9 @@
// worth.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 21dda598..ab8691fd 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -54,6 +54,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map_util.h>
@@ -134,6 +135,17 @@ const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
"repeated", // LABEL_REPEATED
};
+const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
+ switch (syntax) {
+ case SYNTAX_PROTO2:
+ return "proto2";
+ case SYNTAX_PROTO3:
+ return "proto3";
+ case SYNTAX_UNKNOWN:
+ return "unknown";
+ }
+}
+
static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
#ifndef _MSC_VER // MSVC doesn't need these and won't even accept them.
@@ -144,8 +156,8 @@ const int FieldDescriptor::kLastReservedNumber;
namespace {
-string ToCamelCase(const string& input) {
- bool capitalize_next = false;
+string ToCamelCase(const string& input, bool lower_first) {
+ bool capitalize_next = !lower_first;
string result;
result.reserve(input.size());
@@ -166,8 +178,8 @@ string ToCamelCase(const string& input) {
}
// Lower-case the first letter.
- if (!result.empty() && 'A' <= result[0] && result[0] <= 'Z') {
- result[0] = result[0] - 'A' + 'a';
+ if (lower_first && !result.empty() && 'A' <= result[0] && result[0] <= 'Z') {
+ result[0] = result[0] - 'A' + 'a';
}
return result;
@@ -327,6 +339,31 @@ typedef hash_map<EnumIntPair, const EnumValueDescriptor*,
typedef map<DescriptorIntPair, const FieldDescriptor*>
ExtensionsGroupedByDescriptorMap;
typedef hash_map<string, const SourceCodeInfo_Location*> LocationsByPathMap;
+
+set<string>* allowed_proto3_extendees_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(allowed_proto3_extendees_init_);
+
+void InitAllowedProto3Extendee() {
+ allowed_proto3_extendees_ = new set<string>;
+ allowed_proto3_extendees_->insert("google.protobuf.FileOptions");
+ allowed_proto3_extendees_->insert("google.protobuf.MessageOptions");
+ allowed_proto3_extendees_->insert("google.protobuf.FieldOptions");
+ allowed_proto3_extendees_->insert("google.protobuf.EnumOptions");
+ allowed_proto3_extendees_->insert("google.protobuf.EnumValueOptions");
+ allowed_proto3_extendees_->insert("google.protobuf.ServiceOptions");
+ allowed_proto3_extendees_->insert("google.protobuf.MethodOptions");
+}
+
+// Checks whether the extendee type is allowed in proto3.
+// Only extensions to descriptor options are allowed. We use name comparison
+// instead of comparing the descriptor directly because the extensions may be
+// defined in a different pool.
+bool AllowedExtendeeInProto3(const string& name) {
+ ::google::protobuf::GoogleOnceInit(&allowed_proto3_extendees_init_, &InitAllowedProto3Extendee);
+ return allowed_proto3_extendees_->find(name) !=
+ allowed_proto3_extendees_->end();
+}
+
} // anonymous namespace
// ===================================================================
@@ -532,6 +569,9 @@ class FileDescriptorTables {
const void* parent, const string& camelcase_name) const;
inline const EnumValueDescriptor* FindEnumValueByNumber(
const EnumDescriptor* parent, int number) const;
+ // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
+ inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
+ const EnumDescriptor* parent, int number) const;
// -----------------------------------------------------------------
// Adding items.
@@ -567,10 +607,16 @@ class FileDescriptorTables {
FieldsByNameMap fields_by_camelcase_name_;
FieldsByNumberMap fields_by_number_; // Not including extensions.
EnumValuesByNumberMap enum_values_by_number_;
+ mutable EnumValuesByNumberMap unknown_enum_values_by_number_
+ GOOGLE_GUARDED_BY(unknown_enum_values_mu_);
// Populated on first request to save space, hence constness games.
mutable GoogleOnceDynamic locations_by_path_once_;
mutable LocationsByPathMap locations_by_path_;
+
+ // Mutex to protect the unknown-enum-value map due to dynamic
+ // EnumValueDescriptor creation on unknown values.
+ mutable Mutex unknown_enum_values_mu_;
};
DescriptorPool::Tables::Tables()
@@ -600,7 +646,8 @@ FileDescriptorTables::FileDescriptorTables()
fields_by_lowercase_name_(3),
fields_by_camelcase_name_(3),
fields_by_number_(3),
- enum_values_by_number_(3) {
+ enum_values_by_number_(3),
+ unknown_enum_values_by_number_(3) {
}
FileDescriptorTables::~FileDescriptorTables() {}
@@ -749,6 +796,60 @@ inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number));
}
+inline const EnumValueDescriptor*
+FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
+ const EnumDescriptor* parent, int number) const {
+ // First try, with map of compiled-in values.
+ {
+ const EnumValueDescriptor* desc = FindPtrOrNull(
+ enum_values_by_number_, make_pair(parent, number));
+ if (desc != NULL) {
+ return desc;
+ }
+ }
+ // Second try, with reader lock held on unknown enum values: common case.
+ {
+ ReaderMutexLock l(&unknown_enum_values_mu_);
+ const EnumValueDescriptor* desc = FindPtrOrNull(
+ unknown_enum_values_by_number_, make_pair(parent, number));
+ if (desc != NULL) {
+ return desc;
+ }
+ }
+ // If not found, try again with writer lock held, and create new descriptor if
+ // necessary.
+ {
+ WriterMutexLock l(&unknown_enum_values_mu_);
+ const EnumValueDescriptor* desc = FindPtrOrNull(
+ unknown_enum_values_by_number_, make_pair(parent, number));
+ if (desc != NULL) {
+ return desc;
+ }
+
+ // Create an EnumValueDescriptor dynamically. We don't insert it into the
+ // EnumDescriptor (it's not a part of the enum as originally defined), but
+ // we do insert it into the table so that we can return the same pointer
+ // later.
+ string enum_value_name = StringPrintf(
+ "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number);
+ DescriptorPool::Tables* tables =
+ const_cast<DescriptorPool::Tables*>(DescriptorPool::generated_pool()->
+ tables_.get());
+ EnumValueDescriptor* result = tables->Allocate<EnumValueDescriptor>();
+ result->name_ = tables->AllocateString(enum_value_name);
+ result->full_name_ = tables->AllocateString(parent->full_name() +
+ "." + enum_value_name);
+ result->number_ = number;
+ result->type_ = parent;
+ result->options_ = &EnumValueOptions::default_instance();
+ InsertIfNotPresent(&unknown_enum_values_by_number_,
+ make_pair(parent, number),
+ result);
+ return result;
+ }
+}
+
+
inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
const Descriptor* extendee, int number) {
return FindPtrOrNull(extensions_, make_pair(extendee, number));
@@ -1311,6 +1412,11 @@ EnumDescriptor::FindValueByNumber(int key) const {
return file()->tables_->FindEnumValueByNumber(this, key);
}
+const EnumValueDescriptor*
+EnumDescriptor::FindValueByNumberCreatingIfUnknown(int key) const {
+ return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
+}
+
const MethodDescriptor*
ServiceDescriptor::FindMethodByName(const string& key) const {
Symbol result =
@@ -1562,6 +1668,8 @@ string FieldDescriptor::DefaultValueAsString(bool quote_string_type) const {
void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
proto->set_name(name());
if (!package().empty()) proto->set_package(package());
+ // TODO(liujisi): Also populate when syntax="proto2".
+ if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax()));
for (int i = 0; i < dependency_count(); i++) {
proto->add_dependency(dependency(i)->name());
@@ -1594,7 +1702,8 @@ void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
}
void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
- if (source_code_info_ != &SourceCodeInfo::default_instance()) {
+ if (source_code_info_ &&
+ source_code_info_ != &SourceCodeInfo::default_instance()) {
proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
}
}
@@ -1802,10 +1911,67 @@ bool FormatLineOptions(int depth, const Message &options, string *output) {
return !all_options.empty();
}
+template<typename DescType>
+class SourceLocationCommentPrinter {
+ public:
+ SourceLocationCommentPrinter(const DescType* desc,
+ const string& prefix,
+ const DebugStringOptions& options)
+ : options_(options), prefix_(prefix) {
+ // Perform the SourceLocation lookup only if we're including user comments,
+ // because the lookup is fairly expensive.
+ have_source_loc_ = options.include_comments &&
+ desc->GetSourceLocation(&source_loc_);
+ }
+ void AddPreComment(string* output) {
+ if (have_source_loc_ && source_loc_.leading_comments.size() > 0) {
+ *output += FormatComment(source_loc_.leading_comments);
+ }
+ }
+ void AddPostComment(string* output) {
+ if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
+ *output += FormatComment(source_loc_.trailing_comments);
+ }
+ }
+
+ // Format comment such that each line becomes a full-line C++-style comment in
+ // the DebugString() output.
+ string FormatComment(const string& comment_text) {
+ string stripped_comment = comment_text;
+ StripWhitespace(&stripped_comment);
+ vector<string> lines = Split(stripped_comment, "\n");
+ string output;
+ for (int i = 0; i < lines.size(); ++i) {
+ const string& line = lines[i];
+ strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
+ }
+ return output;
+ }
+
+ private:
+ const DescType* desc_;
+ bool have_source_loc_;
+ SourceLocation source_loc_;
+ DebugStringOptions options_;
+ string prefix_;
+};
+
} // anonymous namespace
string FileDescriptor::DebugString() const {
- string contents = "syntax = \"proto2\";\n\n";
+ DebugStringOptions options; // default options
+ return DebugStringWithOptions(options);
+}
+
+string FileDescriptor::DebugStringWithOptions(
+ const DebugStringOptions& debug_string_options) const {
+ string contents;
+ strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
+ SyntaxName(syntax()));
+
+ SourceLocationCommentPrinter<FileDescriptor>
+ comment_printer(this, "", debug_string_options);
+ comment_printer.AddPreComment(&contents);
set<int> public_dependencies;
set<int> weak_dependencies;
@@ -1836,7 +2002,7 @@ string FileDescriptor::DebugString() const {
}
for (int i = 0; i < enum_type_count(); i++) {
- enum_type(i)->DebugString(0, &contents);
+ enum_type(i)->DebugString(0, &contents, debug_string_options);
contents.append("\n");
}
@@ -1851,15 +2017,14 @@ string FileDescriptor::DebugString() const {
for (int i = 0; i < message_type_count(); i++) {
if (groups.count(message_type(i)) == 0) {
- strings::SubstituteAndAppend(&contents, "message $0",
- message_type(i)->name());
- message_type(i)->DebugString(0, &contents);
+ message_type(i)->DebugString(0, &contents, debug_string_options,
+ /* include_opening_clause */ true);
contents.append("\n");
}
}
for (int i = 0; i < service_count(); i++) {
- service(i)->DebugString(&contents);
+ service(i)->DebugString(&contents, debug_string_options);
contents.append("\n");
}
@@ -1871,23 +2036,46 @@ string FileDescriptor::DebugString() const {
strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
containing_type->full_name());
}
- extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents);
+ extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents,
+ debug_string_options);
}
if (extension_count() > 0) contents.append("}\n\n");
+ comment_printer.AddPostComment(&contents);
+
return contents;
}
string Descriptor::DebugString() const {
+ DebugStringOptions options; // default options
+ return DebugStringWithOptions(options);
+}
+
+string Descriptor::DebugStringWithOptions(
+ const DebugStringOptions& options) const {
string contents;
- strings::SubstituteAndAppend(&contents, "message $0", name());
- DebugString(0, &contents);
+ DebugString(0, &contents, options, /* include_opening_clause */ true);
return contents;
}
-void Descriptor::DebugString(int depth, string *contents) const {
+void Descriptor::DebugString(int depth, string *contents,
+ const DebugStringOptions&
+ debug_string_options,
+ bool include_opening_clause) const {
+ if (options().map_entry()) {
+ // Do not generate debug string for auto-generated map-entry type.
+ return;
+ }
string prefix(depth * 2, ' ');
++depth;
+
+ SourceLocationCommentPrinter<Descriptor>
+ comment_printer(this, prefix, debug_string_options);
+ comment_printer.AddPreComment(contents);
+
+ if (include_opening_clause) {
+ strings::SubstituteAndAppend(contents, "$0message $1", prefix, name());
+ }
contents->append(" {\n");
FormatLineOptions(depth, options(), contents);
@@ -1909,20 +2097,21 @@ void Descriptor::DebugString(int depth, string *contents) const {
for (int i = 0; i < nested_type_count(); i++) {
if (groups.count(nested_type(i)) == 0) {
- strings::SubstituteAndAppend(contents, "$0 message $1",
- prefix, nested_type(i)->name());
- nested_type(i)->DebugString(depth, contents);
+ nested_type(i)->DebugString(depth, contents, debug_string_options,
+ /* include_opening_clause */ true);
}
}
for (int i = 0; i < enum_type_count(); i++) {
- enum_type(i)->DebugString(depth, contents);
+ enum_type(i)->DebugString(depth, contents, debug_string_options);
}
for (int i = 0; i < field_count(); i++) {
if (field(i)->containing_oneof() == NULL) {
- field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents);
+ field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents,
+ debug_string_options);
} 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);
+ field(i)->containing_oneof()->DebugString(depth, contents,
+ debug_string_options);
}
}
@@ -1943,15 +2132,23 @@ void Descriptor::DebugString(int depth, string *contents) const {
prefix, containing_type->full_name());
}
extension(i)->DebugString(
- depth + 1, FieldDescriptor::PRINT_LABEL, contents);
+ depth + 1, FieldDescriptor::PRINT_LABEL, contents,
+ debug_string_options);
}
if (extension_count() > 0)
strings::SubstituteAndAppend(contents, "$0 }\n", prefix);
strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+ comment_printer.AddPostComment(contents);
}
string FieldDescriptor::DebugString() const {
+ DebugStringOptions options; // default options
+ return DebugStringWithOptions(options);
+}
+
+string FieldDescriptor::DebugStringWithOptions(
+ const DebugStringOptions& debug_string_options) const {
string contents;
int depth = 0;
if (is_extension()) {
@@ -1959,35 +2156,55 @@ string FieldDescriptor::DebugString() const {
containing_type()->full_name());
depth = 1;
}
- DebugString(depth, PRINT_LABEL, &contents);
+ DebugString(depth, PRINT_LABEL, &contents, debug_string_options);
if (is_extension()) {
contents.append("}\n");
}
return contents;
}
+// The field type string used in FieldDescriptor::DebugString()
+string FieldDescriptor::FieldTypeNameDebugString() const {
+ switch(type()) {
+ case TYPE_MESSAGE:
+ return "." + message_type()->full_name();
+ case TYPE_ENUM:
+ return "." + enum_type()->full_name();
+ default:
+ return kTypeToName[type()];
+ }
+}
+
void FieldDescriptor::DebugString(int depth,
PrintLabelFlag print_label_flag,
- string *contents) const {
+ string *contents,
+ const DebugStringOptions&
+ debug_string_options) const {
string prefix(depth * 2, ' ');
string field_type;
- switch (type()) {
- case TYPE_MESSAGE:
- field_type = "." + message_type()->full_name();
- break;
- case TYPE_ENUM:
- field_type = "." + enum_type()->full_name();
- break;
- default:
- field_type = kTypeToName[type()];
+
+ // Special case map fields.
+ bool is_map = false;
+ if (type() == TYPE_MESSAGE && message_type()->options().map_entry()) {
+ is_map = true;
+ strings::SubstituteAndAppend(
+ &field_type, "map<$0, $1>",
+ message_type()->field(0)->FieldTypeNameDebugString(),
+ message_type()->field(1)->FieldTypeNameDebugString());
+ } else {
+ field_type = FieldTypeNameDebugString();
}
string label;
- if (print_label_flag == PRINT_LABEL) {
+ if (print_label_flag == PRINT_LABEL && !is_map) {
label = kLabelToName[this->label()];
label.push_back(' ');
}
+ SourceLocationCommentPrinter<FieldDescriptor>
+ comment_printer(this, prefix, debug_string_options);
+ comment_printer.AddPreComment(contents);
+
strings::SubstituteAndAppend(contents, "$0$1$2 $3 = $4",
prefix,
label,
@@ -2015,57 +2232,101 @@ void FieldDescriptor::DebugString(int depth,
}
if (type() == TYPE_GROUP) {
- message_type()->DebugString(depth, contents);
+ message_type()->DebugString(depth, contents, debug_string_options,
+ /* include_opening_clause */ false);
} else {
contents->append(";\n");
}
+
+ comment_printer.AddPostComment(contents);
}
string OneofDescriptor::DebugString() const {
+ DebugStringOptions options; // default values
+ return DebugStringWithOptions(options);
+}
+
+string OneofDescriptor::DebugStringWithOptions(
+ const DebugStringOptions& options) const {
string contents;
- DebugString(0, &contents);
+ DebugString(0, &contents, options);
return contents;
}
-void OneofDescriptor::DebugString(int depth, string* contents) const {
+void OneofDescriptor::DebugString(int depth, string* contents,
+ const DebugStringOptions&
+ debug_string_options) const {
string prefix(depth * 2, ' ');
++depth;
+ SourceLocationCommentPrinter<OneofDescriptor>
+ comment_printer(this, prefix, debug_string_options);
+ comment_printer.AddPreComment(contents);
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);
+ field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents,
+ debug_string_options);
}
strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+ comment_printer.AddPostComment(contents);
}
string EnumDescriptor::DebugString() const {
+ DebugStringOptions options; // default values
+ return DebugStringWithOptions(options);
+}
+
+string EnumDescriptor::DebugStringWithOptions(
+ const DebugStringOptions& options) const {
string contents;
- DebugString(0, &contents);
+ DebugString(0, &contents, options);
return contents;
}
-void EnumDescriptor::DebugString(int depth, string *contents) const {
+void EnumDescriptor::DebugString(int depth, string *contents,
+ const DebugStringOptions&
+ debug_string_options) const {
string prefix(depth * 2, ' ');
++depth;
+
+ SourceLocationCommentPrinter<EnumDescriptor>
+ comment_printer(this, prefix, debug_string_options);
+ comment_printer.AddPreComment(contents);
+
strings::SubstituteAndAppend(contents, "$0enum $1 {\n",
prefix, name());
FormatLineOptions(depth, options(), contents);
for (int i = 0; i < value_count(); i++) {
- value(i)->DebugString(depth, contents);
+ value(i)->DebugString(depth, contents, debug_string_options);
}
strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+
+ comment_printer.AddPostComment(contents);
}
string EnumValueDescriptor::DebugString() const {
+ DebugStringOptions options; // default values
+ return DebugStringWithOptions(options);
+}
+
+string EnumValueDescriptor::DebugStringWithOptions(
+ const DebugStringOptions& options) const {
string contents;
- DebugString(0, &contents);
+ DebugString(0, &contents, options);
return contents;
}
-void EnumValueDescriptor::DebugString(int depth, string *contents) const {
+void EnumValueDescriptor::DebugString(int depth, string *contents,
+ const DebugStringOptions&
+ debug_string_options) const {
string prefix(depth * 2, ' ');
+
+ SourceLocationCommentPrinter<EnumValueDescriptor>
+ comment_printer(this, prefix, debug_string_options);
+ comment_printer.AddPreComment(contents);
+
strings::SubstituteAndAppend(contents, "$0$1 = $2",
prefix, name(), number());
@@ -2074,35 +2335,64 @@ void EnumValueDescriptor::DebugString(int depth, string *contents) const {
strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
}
contents->append(";\n");
+
+ comment_printer.AddPostComment(contents);
}
string ServiceDescriptor::DebugString() const {
+ DebugStringOptions options; // default values
+ return DebugStringWithOptions(options);
+}
+
+string ServiceDescriptor::DebugStringWithOptions(
+ const DebugStringOptions& options) const {
string contents;
- DebugString(&contents);
+ DebugString(&contents, options);
return contents;
}
-void ServiceDescriptor::DebugString(string *contents) const {
+void ServiceDescriptor::DebugString(string *contents,
+ const DebugStringOptions&
+ debug_string_options) const {
+ SourceLocationCommentPrinter<ServiceDescriptor>
+ comment_printer(this, /* prefix */ "", debug_string_options);
+ comment_printer.AddPreComment(contents);
+
strings::SubstituteAndAppend(contents, "service $0 {\n", name());
FormatLineOptions(1, options(), contents);
for (int i = 0; i < method_count(); i++) {
- method(i)->DebugString(1, contents);
+ method(i)->DebugString(1, contents, debug_string_options);
}
contents->append("}\n");
+
+ comment_printer.AddPostComment(contents);
}
string MethodDescriptor::DebugString() const {
+ DebugStringOptions options; // default values
+ return DebugStringWithOptions(options);
+}
+
+string MethodDescriptor::DebugStringWithOptions(
+ const DebugStringOptions& options) const {
string contents;
- DebugString(0, &contents);
+ DebugString(0, &contents, options);
return contents;
}
-void MethodDescriptor::DebugString(int depth, string *contents) const {
+void MethodDescriptor::DebugString(int depth, string *contents,
+ const DebugStringOptions&
+ debug_string_options) const {
string prefix(depth * 2, ' ');
++depth;
+
+ SourceLocationCommentPrinter<MethodDescriptor>
+ comment_printer(this, prefix, debug_string_options);
+ comment_printer.AddPreComment(contents);
+
strings::SubstituteAndAppend(contents, "$0rpc $1(.$2) returns (.$3)",
prefix, name(),
input_type()->full_name(),
@@ -2115,6 +2405,8 @@ void MethodDescriptor::DebugString(int depth, string *contents) const {
} else {
contents->append(";\n");
}
+
+ comment_printer.AddPostComment(contents);
}
@@ -2142,6 +2434,11 @@ bool FileDescriptor::GetSourceLocation(const vector<int>& path,
return false;
}
+bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
+ vector<int> path; // empty path for root FileDescriptor
+ return GetSourceLocation(path, out_location);
+}
+
bool FieldDescriptor::is_packed() const {
return is_packable() && (options_ != NULL) && options_->packed();
}
@@ -2409,7 +2706,7 @@ class DescriptorBuilder {
// Creates a placeholder file. Never returns NULL. This is used when an
// import is not found and AllowUnknownDependencies() is enabled.
- const FileDescriptor* NewPlaceholderFile(const string& name);
+ FileDescriptor* NewPlaceholderFile(const string& name);
// Calls tables_->AddSymbol() and records an error if it fails. Returns
// true if successful or false if failed, though most callers can ignore
@@ -2667,9 +2964,24 @@ class DescriptorBuilder {
const ServiceDescriptorProto& proto);
void ValidateMethodOptions(MethodDescriptor* method,
const MethodDescriptorProto& proto);
-
- void ValidateMapKey(FieldDescriptor* field,
- const FieldDescriptorProto& proto);
+ void ValidateProto3(FileDescriptor* file,
+ const FileDescriptorProto& proto);
+ void ValidateProto3Message(Descriptor* message,
+ const DescriptorProto& proto);
+ void ValidateProto3Field(FieldDescriptor* field,
+ const FieldDescriptorProto& proto);
+ void ValidateProto3Enum(EnumDescriptor* enm,
+ const EnumDescriptorProto& proto);
+
+ // Returns true if the map entry message is compatible with the
+ // auto-generated entry message from map fields syntax.
+ bool ValidateMapEntry(FieldDescriptor* field,
+ const FieldDescriptorProto& proto);
+
+ // Recursively detects naming conflicts with map entry types for a
+ // better error message.
+ void DetectMapConflicts(const Descriptor* message,
+ const DescriptorProto& proto);
};
@@ -2992,19 +3304,9 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name,
}
// Create the placeholders.
- FileDescriptor* placeholder_file = tables_->Allocate<FileDescriptor>();
- memset(placeholder_file, 0, sizeof(*placeholder_file));
-
- placeholder_file->source_code_info_ = &SourceCodeInfo::default_instance();
-
- placeholder_file->name_ =
- tables_->AllocateString(*placeholder_full_name + ".placeholder.proto");
+ FileDescriptor* placeholder_file = NewPlaceholderFile(
+ *placeholder_full_name + ".placeholder.proto");
placeholder_file->package_ = placeholder_package;
- placeholder_file->pool_ = pool_;
- placeholder_file->options_ = &FileOptions::default_instance();
- placeholder_file->tables_ = &FileDescriptorTables::kEmpty;
- placeholder_file->is_placeholder_ = true;
- // All other fields are zero or NULL.
if (placeholder_type == PLACEHOLDER_ENUM) {
placeholder_file->enum_type_count_ = 1;
@@ -3068,7 +3370,7 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name,
}
}
-const FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
+FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
const string& name) {
FileDescriptor* placeholder = tables_->Allocate<FileDescriptor>();
memset(placeholder, 0, sizeof(*placeholder));
@@ -3078,7 +3380,9 @@ const FileDescriptor* DescriptorBuilder::NewPlaceholderFile(
placeholder->pool_ = pool_;
placeholder->options_ = &FileOptions::default_instance();
placeholder->tables_ = &FileDescriptorTables::kEmpty;
+ placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
placeholder->is_placeholder_ = true;
+ placeholder->syntax_ = FileDescriptor::SYNTAX_PROTO2;
// All other fields are zero or NULL.
return placeholder;
@@ -3363,6 +3667,19 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
"Missing field: FileDescriptorProto.name.");
}
+ // TODO(liujisi): Report error when the syntax is empty after all the protos
+ // have added the syntax statement.
+ if (proto.syntax().empty() || proto.syntax() == "proto2") {
+ file_->syntax_ = FileDescriptor::SYNTAX_PROTO2;
+ } else if (proto.syntax() == "proto3") {
+ file_->syntax_ = FileDescriptor::SYNTAX_PROTO3;
+ } else {
+ file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
+ AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
+ "Unrecognized syntax: " + proto.syntax());
+ }
+
+
result->name_ = tables_->AllocateString(proto.name());
if (proto.has_package()) {
result->package_ = tables_->AllocateString(proto.package());
@@ -3506,6 +3823,14 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
ValidateFileOptions(result, proto);
}
+ // Additional naming conflict check for map entry types. Only need to check
+ // this if there are already errors.
+ if (had_errors_) {
+ for (int i = 0; i < proto.message_type_size(); ++i) {
+ DetectMapConflicts(result->message_type(i), proto.message_type(i));
+ }
+ }
+
if (!unused_dependency_.empty()) {
LogUnusedDependency(result);
@@ -3621,7 +3946,9 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
// Don't bother with the above optimization for camel-case names since
// .proto files that follow the guide shouldn't be using names in this
// format, so the optimization wouldn't help much.
- result->camelcase_name_ = tables_->AllocateString(ToCamelCase(proto.name()));
+ result->camelcase_name_ =
+ tables_->AllocateString(ToCamelCase(proto.name(),
+ /* lower_first = */ true));
// Some compilers do not allow static_cast directly between two enum types,
// so we must cast to int first.
@@ -3646,7 +3973,6 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
// Some of these may be filled in when cross-linking.
result->containing_type_ = NULL;
result->extension_scope_ = NULL;
- result->experimental_map_key_ = NULL;
result->message_type_ = NULL;
result->enum_type_ = NULL;
@@ -4472,8 +4798,98 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
}
}
}
+ if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ ValidateProto3(file, proto);
+ }
}
+void DescriptorBuilder::ValidateProto3(
+ FileDescriptor* file, const FileDescriptorProto& proto) {
+ for (int i = 0; i < file->extension_count(); ++i) {
+ ValidateProto3Field(file->extensions_ + i, proto.extension(i));
+ }
+ for (int i = 0; i < file->message_type_count(); ++i) {
+ ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
+ }
+ for (int i = 0; i < file->enum_type_count(); ++i) {
+ ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
+ }
+ if (IsLite(file)) {
+ AddError(file->name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "Lite runtime is not supported in proto3.");
+ }
+}
+
+void DescriptorBuilder::ValidateProto3Message(
+ Descriptor* message, const DescriptorProto& proto) {
+ for (int i = 0; i < message->nested_type_count(); ++i) {
+ ValidateProto3Message(message->nested_types_ + i,
+ proto.nested_type(i));
+ }
+ for (int i = 0; i < message->enum_type_count(); ++i) {
+ ValidateProto3Enum(message->enum_types_ + i,
+ proto.enum_type(i));
+ }
+ for (int i = 0; i < message->field_count(); ++i) {
+ ValidateProto3Field(message->fields_ + i, proto.field(i));
+ }
+ for (int i = 0; i < message->extension_count(); ++i) {
+ ValidateProto3Field(message->extensions_ +i, proto.extension(i));
+ }
+ if (message->extension_range_count() > 0) {
+ AddError(message->full_name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "Extension ranges are not allowed in proto3.");
+ }
+ if (message->options().message_set_wire_format()) {
+ // Using MessageSet doesn't make sense since we disallow extensions.
+ AddError(message->full_name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "MessageSet is not supported in proto3.");
+ }
+}
+
+void DescriptorBuilder::ValidateProto3Field(
+ FieldDescriptor* field, const FieldDescriptorProto& proto) {
+ if (field->is_extension() &&
+ !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
+ AddError(field->full_name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "Extensions in proto3 are only allowed for defining options.");
+ }
+ if (field->is_required()) {
+ AddError(field->full_name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "Required fields are not allowed in proto3.");
+ }
+ if (field->has_default_value()) {
+ AddError(
+ field->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
+ "Explicit default values are not allowed in proto3.");
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+ field->enum_type() &&
+ field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3) {
+ // Proto3 messages can only use Proto3 enum types; otherwise we can't
+ // guarantee that the default value is zero.
+ AddError(field->full_name(), proto,
+ DescriptorPool::ErrorCollector::TYPE,
+ "Enum type \"" + field->enum_type()->full_name() +
+ "\" is not a proto3 enum, but is used in \"" +
+ field->containing_type()->full_name() +
+ "\" which is a proto3 message type.");
+ }
+}
+
+void DescriptorBuilder::ValidateProto3Enum(
+ EnumDescriptor* enm, const EnumDescriptorProto& proto) {
+ if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
+ AddError(
+ enm->full_name(), proto, DescriptorPool::ErrorCollector::OTHER,
+ "The first enum value must be zero in proto3.");
+ }
+}
void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
const DescriptorProto& proto) {
@@ -4499,10 +4915,6 @@ void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
const FieldDescriptorProto& proto) {
- if (field->options().has_experimental_map_key()) {
- ValidateMapKey(field, proto);
- }
-
// Only message type fields may be lazy.
if (field->options().lazy()) {
if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
@@ -4551,6 +4963,17 @@ void DescriptorBuilder::ValidateFieldOptions(FieldDescriptor* field,
"a lite type, but the reverse is allowed.");
}
+ // Validate map types.
+ if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ field->message_type()->options().map_entry()) {
+ if (!ValidateMapEntry(field, proto)) {
+ AddError(field->full_name(), proto,
+ DescriptorPool::ErrorCollector::OTHER,
+ "map_entry should not be set explicitly. Use map<KeyType, "
+ "ValueType> instead.");
+ }
+ }
+
}
void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
@@ -4608,57 +5031,127 @@ void DescriptorBuilder::ValidateMethodOptions(MethodDescriptor* /* method */,
// Nothing to do so far.
}
-void DescriptorBuilder::ValidateMapKey(FieldDescriptor* field,
- const FieldDescriptorProto& proto) {
- if (!field->is_repeated()) {
- AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
- "map type is only allowed for repeated fields.");
- return;
+bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
+ const FieldDescriptorProto& proto) {
+ const Descriptor* message = field->message_type();
+ if (// Must not contain extensions, extension range or nested message or
+ // enums
+ message->extension_count() != 0 ||
+ field->label() != FieldDescriptor::LABEL_REPEATED ||
+ message->extension_range_count() != 0 ||
+ message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
+ // Must contain exactly two fields
+ message->field_count() != 2 ||
+ // Field name and message name must match
+ message->name() != ToCamelCase(field->name(), false) + "Entry" ||
+ // Entry message must be in the same containing type of the field.
+ field->containing_type() != message->containing_type()) {
+ return false;
}
- if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
- AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
- "map type is only allowed for fields with a message type.");
- return;
+ const FieldDescriptor* key = message->field(0);
+ const FieldDescriptor* value = message->field(1);
+ if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
+ key->name() != "key") {
+ return false;
+ }
+ if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
+ value->number() != 2 || value->name() != "value") {
+ return false;
}
- const Descriptor* item_type = field->message_type();
- if (item_type == NULL) {
- AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
- "Could not find field type.");
- return;
+ // Check key types are legal.
+ switch (key->type()) {
+ case FieldDescriptor::TYPE_ENUM:
+ AddError(
+ field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+ "Key in map fields cannot be enum types.");
+ break;
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_BYTES:
+ AddError(
+ field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+ "Key in map fields cannot be float/double, bytes or message types.");
+ break;
+ case FieldDescriptor::TYPE_BOOL:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_FIXED64:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_SFIXED64:
+ // Legal cases
+ break;
+ // Do not add a default, so that the compiler will complian when new types
+ // are added.
}
- // Find the field in item_type named by "experimental_map_key"
- const string& key_name = field->options().experimental_map_key();
- const Symbol key_symbol = LookupSymbol(
- key_name,
- // We append ".key_name" to the containing type's name since
- // LookupSymbol() searches for peers of the supplied name, not
- // children of the supplied name.
- item_type->full_name() + "." + key_name);
+ return true;
+}
- if (key_symbol.IsNull() || key_symbol.field_descriptor->is_extension()) {
- AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
- "Could not find field named \"" + key_name + "\" in type \"" +
- item_type->full_name() + "\".");
- return;
+void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
+ const DescriptorProto& proto) {
+ map<string, const Descriptor*> seen_types;
+ for (int i = 0; i < message->nested_type_count(); ++i) {
+ const Descriptor* nested = message->nested_type(i);
+ pair<map<string, const Descriptor*>::iterator, bool> result =
+ seen_types.insert(make_pair(nested->name(), nested));
+ if (!result.second) {
+ if (result.first->second->options().map_entry() ||
+ nested->options().map_entry()) {
+ AddError(message->full_name(), proto,
+ DescriptorPool::ErrorCollector::NAME,
+ "Expanded map entry type " + nested->name() +
+ " conflicts with an existing nested message type.");
+ }
+ }
+ // Recursively test on the nested types.
+ DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
+ }
+ // Check for conflicted field names.
+ for (int i = 0; i < message->field_count(); ++i) {
+ const FieldDescriptor* field = message->field(i);
+ map<string, const Descriptor*>::iterator iter =
+ seen_types.find(field->name());
+ if (iter != seen_types.end() && iter->second->options().map_entry()) {
+ AddError(message->full_name(), proto,
+ DescriptorPool::ErrorCollector::NAME,
+ "Expanded map entry type " + iter->second->name() +
+ " conflicts with an existing field.");
+ }
}
- const FieldDescriptor* key_field = key_symbol.field_descriptor;
-
- if (key_field->is_repeated()) {
- AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
- "map_key must not name a repeated field.");
- return;
+ // Check for conflicted enum names.
+ for (int i = 0; i < message->enum_type_count(); ++i) {
+ const EnumDescriptor* enum_desc = message->enum_type(i);
+ map<string, const Descriptor*>::iterator iter =
+ seen_types.find(enum_desc->name());
+ if (iter != seen_types.end() && iter->second->options().map_entry()) {
+ AddError(message->full_name(), proto,
+ DescriptorPool::ErrorCollector::NAME,
+ "Expanded map entry type " + iter->second->name() +
+ " conflicts with an existing enum type.");
+ }
}
-
- if (key_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
- "map key must name a scalar or string field.");
- return;
+ // Check for conflicted oneof names.
+ for (int i = 0; i < message->oneof_decl_count(); ++i) {
+ const OneofDescriptor* oneof_desc = message->oneof_decl(i);
+ map<string, const Descriptor*>::iterator iter =
+ seen_types.find(oneof_desc->name());
+ if (iter != seen_types.end() && iter->second->options().map_entry()) {
+ AddError(message->full_name(), proto,
+ DescriptorPool::ErrorCollector::NAME,
+ "Expanded map entry type " + iter->second->name() +
+ " conflicts with an existing oneof type.");
+ }
}
-
- field->experimental_map_key_ = key_field;
}
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 68013f8e..b7ea756c 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -104,6 +104,11 @@ class FileDescriptorTables;
// Defined in unknown_field_set.h.
class UnknownField;
+// Defined in generated_message_reflection.h.
+namespace internal {
+ class GeneratedMessageReflection;
+}
+
// NB, all indices are zero-based.
struct SourceLocation {
int start_line;
@@ -118,6 +123,20 @@ struct SourceLocation {
string trailing_comments;
};
+// Options when generating machine-parsable output from a descriptor with
+// DebugString().
+struct DebugStringOptions {
+ // include original user comments as recorded in SourceLocation entries. N.B.
+ // that this must be |false| by default: several other pieces of code (for
+ // example, the C++ code generation for fields in the proto compiler) rely on
+ // DebugString() output being unobstructed by user comments.
+ bool include_comments;
+
+ DebugStringOptions()
+ : include_comments(false)
+ {}
+};
+
// Describes a type of protocol message, or a particular group within a
// message. To obtain the Descriptor for a given message object, call
// Message::GetDescriptor(). Generated message classes also have a
@@ -162,6 +181,10 @@ class LIBPROTOBUF_EXPORT Descriptor {
// will be suitable for re-parsing.
string DebugString() const;
+ // Similar to DebugString(), but additionally takes options (e.g.,
+ // include original user comments in output).
+ string DebugStringWithOptions(const DebugStringOptions& options) 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.
@@ -282,8 +305,12 @@ class LIBPROTOBUF_EXPORT Descriptor {
typedef MessageOptions OptionsType;
// Internal version of DebugString; controls the level of indenting for
- // correct depth
- void DebugString(int depth, string *contents) const;
+ // correct depth. Takes |options| to control debug-string options, and
+ // |include_opening_clause| to indicate whether the "message ... " part of the
+ // clause has already been generated (this varies depending on context).
+ void DebugString(int depth, string *contents,
+ const DebugStringOptions& options,
+ bool include_opening_clause) const;
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
@@ -513,12 +540,6 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// returns null.
const EnumDescriptor* enum_type() const;
- // EXPERIMENTAL; DO NOT USE.
- // If this field is a map field, experimental_map_key() is the field
- // that is the key for this map.
- // experimental_map_key()->containing_type() is the same as message_type().
- const FieldDescriptor* experimental_map_key() const;
-
// Get the FieldOptions for this field. This includes things listed in
// square brackets after the field definition. E.g., the field:
// optional string text = 1 [ctype=CORD];
@@ -533,6 +554,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+ // See Descriptor::DebugStringWithOptions().
+ string DebugStringWithOptions(const DebugStringOptions& options) const;
+
// Helper method to get the CppType for a particular Type.
static CppType TypeToCppType(Type type);
@@ -558,13 +582,16 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// See Descriptor::DebugString().
enum PrintLabelFlag { PRINT_LABEL, OMIT_LABEL };
void DebugString(int depth, PrintLabelFlag print_label_flag,
- string* contents) const;
+ string* contents, const DebugStringOptions& options) const;
// formats the default value appropriately and returns it as a string.
// Must have a default value to call this. If quote_string_type is true, then
// types of CPPTYPE_STRING whill be surrounded by quotes and CEscaped.
string DefaultValueAsString(bool quote_string_type) const;
+ // Helper function that returns the field type name for DebugString.
+ string FieldTypeNameDebugString() 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;
@@ -584,7 +611,6 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
const Descriptor* extension_scope_;
const Descriptor* message_type_;
const EnumDescriptor* enum_type_;
- const FieldDescriptor* experimental_map_key_;
const FieldOptions* options_;
// IMPORTANT: If you add a new field, make sure to search for all instances
// of Allocate<FieldDescriptor>() and AllocateArray<FieldDescriptor>() in
@@ -645,6 +671,9 @@ class LIBPROTOBUF_EXPORT OneofDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+ // See Descriptor::DebugStringWithOptions().
+ string DebugStringWithOptions(const DebugStringOptions& options) const;
+
// Source Location ---------------------------------------------------
// Updates |*out_location| to the source location of the complete
@@ -654,7 +683,8 @@ class LIBPROTOBUF_EXPORT OneofDescriptor {
private:
// See Descriptor::DebugString().
- void DebugString(int depth, string* contents) const;
+ void DebugString(int depth, string* contents,
+ const DebugStringOptions& options) const;
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
@@ -723,6 +753,10 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+ // See Descriptor::DebugStringWithOptions().
+ string DebugStringWithOptions(const DebugStringOptions& options) 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.
@@ -738,8 +772,21 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
private:
typedef EnumOptions OptionsType;
+ // Looks up a value by number. If the value does not exist, dynamically
+ // creates a new EnumValueDescriptor for that value, assuming that it was
+ // unknown. If a new descriptor is created, this is done in a thread-safe way,
+ // and future calls will return the same value descriptor pointer.
+ //
+ // This is private but is used by GeneratedMessageReflection (which is
+ // friended below) to return a valid EnumValueDescriptor from GetEnum() when
+ // this feature is enabled.
+ const EnumValueDescriptor*
+ FindValueByNumberCreatingIfUnknown(int number) const;
+
+
// See Descriptor::DebugString().
- void DebugString(int depth, string *contents) const;
+ void DebugString(int depth, string *contents,
+ const DebugStringOptions& options) const;
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
@@ -769,6 +816,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
friend class FieldDescriptor;
friend class EnumValueDescriptor;
friend class FileDescriptor;
+ friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
};
@@ -806,6 +854,10 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+ // See Descriptor::DebugStringWithOptions().
+ string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+
// Source Location ---------------------------------------------------
// Updates |*out_location| to the source location of the complete
@@ -817,7 +869,8 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
typedef EnumValueOptions OptionsType;
// See Descriptor::DebugString().
- void DebugString(int depth, string *contents) const;
+ void DebugString(int depth, string *contents,
+ const DebugStringOptions& options) const;
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
@@ -836,6 +889,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
EnumValueDescriptor() {}
friend class DescriptorBuilder;
friend class EnumDescriptor;
+ friend class FileDescriptorTables;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor);
};
@@ -876,6 +930,10 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+ // See Descriptor::DebugStringWithOptions().
+ string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+
// Source Location ---------------------------------------------------
// Updates |*out_location| to the source location of the complete
@@ -887,7 +945,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor {
typedef ServiceOptions OptionsType;
// See Descriptor::DebugString().
- void DebugString(string *contents) const;
+ void DebugString(string *contents, const DebugStringOptions& options) const;
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
@@ -945,6 +1003,10 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+ // See Descriptor::DebugStringWithOptions().
+ string DebugStringWithOptions(const DebugStringOptions& options) const;
+
+
// Source Location ---------------------------------------------------
// Updates |*out_location| to the source location of the complete
@@ -956,7 +1018,8 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
typedef MethodOptions OptionsType;
// See Descriptor::DebugString().
- void DebugString(int depth, string *contents) const;
+ void DebugString(int depth, string *contents,
+ const DebugStringOptions& options) const;
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
@@ -1052,6 +1115,15 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
// message.
const FileOptions& options() const;
+ // Syntax of this file.
+ enum Syntax {
+ SYNTAX_UNKNOWN = 0,
+ SYNTAX_PROTO2 = 2,
+ SYNTAX_PROTO3 = 3,
+ };
+ Syntax syntax() const;
+ static const char* SyntaxName(Syntax syntax);
+
// Find a top-level message type by name. Returns NULL if not found.
const Descriptor* FindMessageTypeByName(const string& name) const;
// Find a top-level enum type by name. Returns NULL if not found.
@@ -1082,11 +1154,18 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
// See Descriptor::DebugString().
string DebugString() const;
+ // See Descriptor::DebugStringWithOptions().
+ string DebugStringWithOptions(const DebugStringOptions& options) 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;
+ // Updates |*out_location| to the source location of the complete extent of
+ // this file declaration (namely, the empty path).
+ bool GetSourceLocation(SourceLocation* out_location) const;
+
private:
// Source Location ---------------------------------------------------
@@ -1116,6 +1195,7 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
int service_count_;
ServiceDescriptor* services_;
int extension_count_;
+ Syntax syntax_;
bool is_placeholder_;
FieldDescriptor* extensions_;
const FileOptions* options_;
@@ -1394,6 +1474,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
friend class ServiceDescriptor;
friend class FileDescriptor;
friend class DescriptorBuilder;
+ friend class FileDescriptorTables;
// Return true if the given name is a sub-symbol of any non-package
// descriptor that already exists in the descriptor pool. (The full
@@ -1494,8 +1575,6 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, index_in_oneof, int)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, extension_scope, const Descriptor*)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, message_type, const Descriptor*)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*)
-PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, experimental_map_key,
- const FieldDescriptor*)
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FieldDescriptor, FieldOptions)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, has_default_value, bool)
PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_int32 , int32 )
@@ -1679,6 +1758,10 @@ inline const FileDescriptor* FileDescriptor::weak_dependency(
return dependencies_[weak_dependencies_[index]];
}
+inline FileDescriptor::Syntax FileDescriptor::syntax() const {
+ return syntax_;
+}
+
// 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 {
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index c3aa2fb6..4fe01ce3 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -108,13 +108,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
FileDescriptorSet::default_instance_,
FileDescriptorSet_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(FileDescriptorSet));
+ sizeof(FileDescriptorSet),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_));
FileDescriptorProto_descriptor_ = file->message_type(1);
- static const int FileDescriptorProto_offsets_[11] = {
+ static const int FileDescriptorProto_offsets_[12] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_),
@@ -126,6 +127,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, syntax_),
};
FileDescriptorProto_reflection_ =
new ::google::protobuf::internal::GeneratedMessageReflection(
@@ -133,11 +135,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
FileDescriptorProto::default_instance_,
FileDescriptorProto_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(FileDescriptorProto));
+ sizeof(FileDescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_));
DescriptorProto_descriptor_ = file->message_type(2);
static const int DescriptorProto_offsets_[8] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_),
@@ -155,11 +158,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
DescriptorProto::default_instance_,
DescriptorProto_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(DescriptorProto));
+ sizeof(DescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, _internal_metadata_));
DescriptorProto_ExtensionRange_descriptor_ = DescriptorProto_descriptor_->nested_type(0);
static const int DescriptorProto_ExtensionRange_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_),
@@ -171,11 +175,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
DescriptorProto_ExtensionRange::default_instance_,
DescriptorProto_ExtensionRange_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(DescriptorProto_ExtensionRange));
+ sizeof(DescriptorProto_ExtensionRange),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_));
FieldDescriptorProto_descriptor_ = file->message_type(3);
static const int FieldDescriptorProto_offsets_[9] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
@@ -194,11 +199,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
FieldDescriptorProto::default_instance_,
FieldDescriptorProto_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(FieldDescriptorProto));
+ sizeof(FieldDescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_));
FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0);
FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1);
OneofDescriptorProto_descriptor_ = file->message_type(4);
@@ -211,11 +217,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
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,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(OneofDescriptorProto));
+ sizeof(OneofDescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _internal_metadata_));
EnumDescriptorProto_descriptor_ = file->message_type(5);
static const int EnumDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_),
@@ -228,11 +235,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
EnumDescriptorProto::default_instance_,
EnumDescriptorProto_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(EnumDescriptorProto));
+ sizeof(EnumDescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, _internal_metadata_));
EnumValueDescriptorProto_descriptor_ = file->message_type(6);
static const int EnumValueDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_),
@@ -245,11 +253,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
EnumValueDescriptorProto::default_instance_,
EnumValueDescriptorProto_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(EnumValueDescriptorProto));
+ sizeof(EnumValueDescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, _internal_metadata_));
ServiceDescriptorProto_descriptor_ = file->message_type(7);
static const int ServiceDescriptorProto_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_),
@@ -262,11 +271,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
ServiceDescriptorProto::default_instance_,
ServiceDescriptorProto_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(ServiceDescriptorProto));
+ sizeof(ServiceDescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, _internal_metadata_));
MethodDescriptorProto_descriptor_ = file->message_type(8);
static const int MethodDescriptorProto_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_),
@@ -280,11 +290,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
MethodDescriptorProto::default_instance_,
MethodDescriptorProto_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(MethodDescriptorProto));
+ sizeof(MethodDescriptorProto),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_));
FileOptions_descriptor_ = file->message_type(9);
static const int FileOptions_offsets_[12] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
@@ -306,17 +317,19 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
FileOptions::default_instance_,
FileOptions_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _unknown_fields_),
+ -1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(FileOptions));
+ sizeof(FileOptions),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, _internal_metadata_));
FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0);
MessageOptions_descriptor_ = file->message_type(10);
- static const int MessageOptions_offsets_[4] = {
+ static const int MessageOptions_offsets_[5] = {
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, map_entry_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_),
};
MessageOptions_reflection_ =
@@ -325,18 +338,18 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
MessageOptions::default_instance_,
MessageOptions_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _unknown_fields_),
+ -1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(MessageOptions));
+ sizeof(MessageOptions),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_));
FieldOptions_descriptor_ = file->message_type(11);
- static const int FieldOptions_offsets_[7] = {
+ static const int FieldOptions_offsets_[6] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, experimental_map_key_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_),
};
@@ -346,11 +359,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
FieldOptions::default_instance_,
FieldOptions_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _unknown_fields_),
+ -1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(FieldOptions));
+ sizeof(FieldOptions),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_));
FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
EnumOptions_descriptor_ = file->message_type(12);
static const int EnumOptions_offsets_[3] = {
@@ -364,11 +378,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
EnumOptions::default_instance_,
EnumOptions_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _unknown_fields_),
+ -1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(EnumOptions));
+ sizeof(EnumOptions),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, _internal_metadata_));
EnumValueOptions_descriptor_ = file->message_type(13);
static const int EnumValueOptions_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, deprecated_),
@@ -380,11 +395,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
EnumValueOptions::default_instance_,
EnumValueOptions_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _unknown_fields_),
+ -1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(EnumValueOptions));
+ sizeof(EnumValueOptions),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, _internal_metadata_));
ServiceOptions_descriptor_ = file->message_type(14);
static const int ServiceOptions_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, deprecated_),
@@ -396,11 +412,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
ServiceOptions::default_instance_,
ServiceOptions_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _unknown_fields_),
+ -1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(ServiceOptions));
+ sizeof(ServiceOptions),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, _internal_metadata_));
MethodOptions_descriptor_ = file->message_type(15);
static const int MethodOptions_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, deprecated_),
@@ -412,11 +429,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
MethodOptions::default_instance_,
MethodOptions_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _unknown_fields_),
+ -1,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _extensions_),
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(MethodOptions));
+ sizeof(MethodOptions),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, _internal_metadata_));
UninterpretedOption_descriptor_ = file->message_type(16);
static const int UninterpretedOption_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_),
@@ -433,11 +451,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
UninterpretedOption::default_instance_,
UninterpretedOption_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(UninterpretedOption));
+ sizeof(UninterpretedOption),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, _internal_metadata_));
UninterpretedOption_NamePart_descriptor_ = UninterpretedOption_descriptor_->nested_type(0);
static const int UninterpretedOption_NamePart_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, name_part_),
@@ -449,11 +468,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
UninterpretedOption_NamePart::default_instance_,
UninterpretedOption_NamePart_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(UninterpretedOption_NamePart));
+ sizeof(UninterpretedOption_NamePart),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption_NamePart, _internal_metadata_));
SourceCodeInfo_descriptor_ = file->message_type(17);
static const int SourceCodeInfo_offsets_[1] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_),
@@ -464,11 +484,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
SourceCodeInfo::default_instance_,
SourceCodeInfo_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(SourceCodeInfo));
+ sizeof(SourceCodeInfo),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_));
SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
static const int SourceCodeInfo_Location_offsets_[4] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
@@ -482,11 +503,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
SourceCodeInfo_Location::default_instance_,
SourceCodeInfo_Location_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(SourceCodeInfo_Location));
+ sizeof(SourceCodeInfo_Location),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _internal_metadata_));
}
namespace {
@@ -600,7 +622,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"\n google/protobuf/descriptor.proto\022\017goog"
"le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
"\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
- "roto\"\313\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
+ "roto\"\333\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
"(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
"\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen"
"dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog"
@@ -611,104 +633,104 @@ 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\"\344\003\n\017Descripto"
- "rProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.go"
- "ogle.protobuf.FieldDescriptorProto\0228\n\tex"
- "tension\030\006 \003(\0132%.google.protobuf.FieldDes"
- "criptorProto\0225\n\013nested_type\030\003 \003(\0132 .goog"
- "le.protobuf.DescriptorProto\0227\n\tenum_type"
- "\030\004 \003(\0132$.google.protobuf.EnumDescriptorP"
- "roto\022H\n\017extension_range\030\005 \003(\0132/.google.p"
- "rotobuf.DescriptorProto.ExtensionRange\0229"
- "\n\noneof_decl\030\010 \003(\0132%.google.protobuf.One"
- "ofDescriptorProto\0220\n\007options\030\007 \001(\0132\037.goo"
- "gle.protobuf.MessageOptions\032,\n\016Extension"
- "Range\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024Fi"
- "eldDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006numb"
- "er\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobu"
- "f.FieldDescriptorProto.Label\0228\n\004type\030\005 \001"
- "(\0162*.google.protobuf.FieldDescriptorProt"
- "o.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 "
- "\001(\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_inde"
- "x\030\t \001(\005\022.\n\007options\030\010 \001(\0132\035.google.protob"
- "uf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020"
- "\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYP"
- "E_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED"
- "64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n"
- "\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_M"
- "ESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020"
- "\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rT"
- "YPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_"
- "SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n"
- "\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n"
- "\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023"
- "EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005val"
- "ue\030\002 \003(\0132).google.protobuf.EnumValueDesc"
- "riptorProto\022-\n\007options\030\003 \001(\0132\034.google.pr"
- "otobuf.EnumOptions\"l\n\030EnumValueDescripto"
- "rProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007"
- "options\030\003 \001(\0132!.google.protobuf.EnumValu"
- "eOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004n"
- "ame\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.proto"
- "buf.MethodDescriptorProto\0220\n\007options\030\003 \001"
- "(\0132\037.google.protobuf.ServiceOptions\"\177\n\025M"
- "ethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\nin"
- "put_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007o"
- "ptions\030\004 \001(\0132\036.google.protobuf.MethodOpt"
- "ions\"\253\004\n\013FileOptions\022\024\n\014java_package\030\001 \001"
- "(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023java"
- "_multiple_files\030\n \001(\010:\005false\022,\n\035java_gen"
- "erate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026ja"
- "va_string_check_utf8\030\033 \001(\010:\005false\022F\n\014opt"
- "imize_for\030\t \001(\0162).google.protobuf.FileOp"
- "tions.OptimizeMode:\005SPEED\022\022\n\ngo_package\030"
- "\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fals"
- "e\022$\n\025java_generic_services\030\021 \001(\010:\005false\022"
- "\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n\nd"
- "eprecated\030\027 \001(\010:\005false\022C\n\024uninterpreted_"
- "option\030\347\007 \003(\0132$.google.protobuf.Uninterp"
- "retedOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r"
- "\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200"
- "\200\002\"\323\001\n\016MessageOptions\022&\n\027message_set_wir"
- "e_format\030\001 \001(\010:\005false\022.\n\037no_standard_des"
- "criptor_accessor\030\002 \001(\010:\005false\022\031\n\ndepreca"
- "ted\030\003 \001(\010:\005false\022C\n\024uninterpreted_option"
- "\030\347\007 \003(\0132$.google.protobuf.UninterpretedO"
- "ption*\t\010\350\007\020\200\200\200\200\002\"\276\002\n\014FieldOptions\022:\n\005cty"
- "pe\030\001 \001(\0162#.google.protobuf.FieldOptions."
- "CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 "
- "\001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n"
- "\024experimental_map_key\030\t \001(\t\022\023\n\004weak\030\n \001("
- "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
- "$.google.protobuf.UninterpretedOption\"/\n"
- "\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_P"
- "IECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013all"
- "ow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fals"
- "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl"
- "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200"
- "\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001("
- "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
- "$.google.protobuf.UninterpretedOption*\t\010"
- "\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated"
- "\030! \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007"
+ "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001"
+ "(\t\"\344\003\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
+ "field\030\002 \003(\0132%.google.protobuf.FieldDescr"
+ "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p"
+ "rotobuf.FieldDescriptorProto\0225\n\013nested_t"
+ "ype\030\003 \003(\0132 .google.protobuf.DescriptorPr"
+ "oto\0227\n\tenum_type\030\004 \003(\0132$.google.protobuf"
+ ".EnumDescriptorProto\022H\n\017extension_range\030"
+ "\005 \003(\0132/.google.protobuf.DescriptorProto."
+ "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo"
+ "gle.protobuf.OneofDescriptorProto\0220\n\007opt"
+ "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti"
+ "ons\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003"
+ "end\030\002 \001(\005\"\251\005\n\024FieldDescriptorProto\022\014\n\004na"
+ "me\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162"
+ "+.google.protobuf.FieldDescriptorProto.L"
+ "abel\0228\n\004type\030\005 \001(\0162*.google.protobuf.Fie"
+ "ldDescriptorProto.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_index\030\t \001(\005\022.\n\007options\030\010 \001(\013"
+ "2\035.google.protobuf.FieldOptions\"\266\002\n\004Type"
+ "\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYP"
+ "E_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32"
+ "\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r"
+ "\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_G"
+ "ROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014"
+ "\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE"
+ "_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_S"
+ "INT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LAB"
+ "EL_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LAB"
+ "EL_REPEATED\020\003\"$\n\024OneofDescriptorProto\022\014\n"
+ "\004name\030\001 \001(\t\"\214\001\n\023EnumDescriptorProto\022\014\n\004n"
+ "ame\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).google.protob"
+ "uf.EnumValueDescriptorProto\022-\n\007options\030\003"
+ " \001(\0132\034.google.protobuf.EnumOptions\"l\n\030En"
+ "umValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006"
+ "number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.p"
+ "rotobuf.EnumValueOptions\"\220\001\n\026ServiceDesc"
+ "riptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003("
+ "\0132&.google.protobuf.MethodDescriptorProt"
+ "o\0220\n\007options\030\003 \001(\0132\037.google.protobuf.Ser"
+ "viceOptions\"\177\n\025MethodDescriptorProto\022\014\n\004"
+ "name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output"
+ "_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.pr"
+ "otobuf.MethodOptions\"\253\004\n\013FileOptions\022\024\n\014"
+ "java_package\030\001 \001(\t\022\034\n\024java_outer_classna"
+ "me\030\010 \001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005f"
+ "alse\022,\n\035java_generate_equals_and_hash\030\024 "
+ "\001(\010:\005false\022%\n\026java_string_check_utf8\030\033 \001"
+ "(\010:\005false\022F\n\014optimize_for\030\t \001(\0162).google"
+ ".protobuf.FileOptions.OptimizeMode:\005SPEE"
+ "D\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_generic_serv"
+ "ices\030\020 \001(\010:\005false\022$\n\025java_generic_servic"
+ "es\030\021 \001(\010:\005false\022\"\n\023py_generic_services\030\022"
+ " \001(\010:\005false\022\031\n\ndeprecated\030\027 \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\"\346\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\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_"
+ "entry\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003"
+ "(\0132$.google.protobuf.UninterpretedOption"
+ "*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005ctype\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:\005"
+ "false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak"
+ "\030\n \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);
+ "on\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STR"
+ "ING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023"
+ "\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:"
+ "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+ "google.protobuf.UninterpretedOption*\t\010\350\007"
+ "\020\200\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated"
+ "\030\001 \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\"{\n\016ServiceOptions\022\031\n\ndepre"
+ "cated\030! \001(\010:\005false\022C\n\024uninterpreted_opti"
+ "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
+ "dOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\nd"
+ "eprecated\030! \001(\010:\005false\022C\n\024uninterpreted_"
+ "option\030\347\007 \003(\0132$.google.protobuf.Uninterp"
+ "retedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterpreted"
+ "Option\022;\n\004name\030\002 \003(\0132-.google.protobuf.U"
+ "ninterpretedOption.NamePart\022\030\n\020identifie"
+ "r_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\017agg"
+ "regate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_p"
+ "art\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\261\001\n\016Sour"
+ "ceCodeInfo\022:\n\010location\030\001 \003(\0132(.google.pr"
+ "otobuf.SourceCodeInfo.Location\032c\n\010Locati"
+ "on\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_com"
+ "ments\030\004 \001(\tB)\n\023com.google.protobufB\020Desc"
+ "riptorProtosH\001", 4454);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -770,16 +792,26 @@ const int FileDescriptorSet::kFileFieldNumber;
#endif // !_MSC_VER
FileDescriptorSet::FileDescriptorSet()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet)
}
+FileDescriptorSet::FileDescriptorSet(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ file_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorSet)
+}
+
void FileDescriptorSet::InitAsDefaultInstance() {
}
FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet)
@@ -796,10 +828,20 @@ FileDescriptorSet::~FileDescriptorSet() {
}
void FileDescriptorSet::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void FileDescriptorSet::ArenaDtor(void* object) {
+ FileDescriptorSet* _this = reinterpret_cast< FileDescriptorSet* >(object);
+ (void)_this;
+}
+void FileDescriptorSet::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void FileDescriptorSet::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -817,14 +859,16 @@ const FileDescriptorSet& FileDescriptorSet::default_instance() {
FileDescriptorSet* FileDescriptorSet::default_instance_ = NULL;
-FileDescriptorSet* FileDescriptorSet::New() const {
- return new FileDescriptorSet;
+FileDescriptorSet* FileDescriptorSet::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<FileDescriptorSet>(arena);
}
void FileDescriptorSet::Clear() {
file_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool FileDescriptorSet::MergePartialFromCodedStream(
@@ -882,7 +926,7 @@ void FileDescriptorSet::SerializeWithCachedSizes(
1, this->file(i), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -899,7 +943,7 @@ void FileDescriptorSet::SerializeWithCachedSizes(
1, this->file(i), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -918,7 +962,7 @@ int FileDescriptorSet::ByteSize() const {
this->file(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -944,7 +988,9 @@ void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) {
void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) {
GOOGLE_CHECK_NE(&from, this);
file_.MergeFrom(from.file_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void FileDescriptorSet::CopyFrom(const ::google::protobuf::Message& from) {
@@ -966,13 +1012,27 @@ bool FileDescriptorSet::IsInitialized() const {
}
void FileDescriptorSet::Swap(FileDescriptorSet* other) {
- if (other != this) {
- file_.Swap(&other->file_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ FileDescriptorSet temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void FileDescriptorSet::UnsafeArenaSwap(FileDescriptorSet* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
+ file_.UnsafeArenaSwap(&other->file_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata FileDescriptorSet::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -997,21 +1057,38 @@ const int FileDescriptorProto::kServiceFieldNumber;
const int FileDescriptorProto::kExtensionFieldNumber;
const int FileDescriptorProto::kOptionsFieldNumber;
const int FileDescriptorProto::kSourceCodeInfoFieldNumber;
+const int FileDescriptorProto::kSyntaxFieldNumber;
#endif // !_MSC_VER
FileDescriptorProto::FileDescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto)
}
+FileDescriptorProto::FileDescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ dependency_(arena),
+ public_dependency_(arena),
+ weak_dependency_(arena),
+ message_type_(arena),
+ enum_type_(arena),
+ service_(arena),
+ extension_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.FileDescriptorProto)
+}
+
void FileDescriptorProto::InitAsDefaultInstance() {
options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance());
source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(&::google::protobuf::SourceCodeInfo::default_instance());
}
FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto)
@@ -1020,10 +1097,11 @@ FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from)
void FileDescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
options_ = NULL;
source_code_info_ = NULL;
+ syntax_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -1033,18 +1111,25 @@ FileDescriptorProto::~FileDescriptorProto() {
}
void FileDescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
- }
- if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete package_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ package_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ syntax_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
delete options_;
delete source_code_info_;
}
}
+void FileDescriptorProto::ArenaDtor(void* object) {
+ FileDescriptorProto* _this = reinterpret_cast< FileDescriptorProto* >(object);
+ (void)_this;
+}
+void FileDescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void FileDescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -1062,30 +1147,29 @@ const FileDescriptorProto& FileDescriptorProto::default_instance() {
FileDescriptorProto* FileDescriptorProto::default_instance_ = NULL;
-FileDescriptorProto* FileDescriptorProto::New() const {
- return new FileDescriptorProto;
+FileDescriptorProto* FileDescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<FileDescriptorProto>(arena);
}
void FileDescriptorProto::Clear() {
if (_has_bits_[0 / 32] & 3) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_package()) {
- if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- package_->clear();
- }
+ package_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
}
- if (_has_bits_[8 / 32] & 1536) {
+ if (_has_bits_[8 / 32] & 3584) {
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
}
if (has_source_code_info()) {
if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
}
+ if (has_syntax()) {
+ syntax_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ }
}
dependency_.Clear();
public_dependency_.Clear();
@@ -1095,7 +1179,9 @@ void FileDescriptorProto::Clear() {
service_.Clear();
extension_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool FileDescriptorProto::MergePartialFromCodedStream(
@@ -1116,7 +1202,7 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.FileDescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -1133,7 +1219,7 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->package().data(), this->package().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "package");
+ "google.protobuf.FileDescriptorProto.package");
} else {
goto handle_unusual;
}
@@ -1151,7 +1237,7 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
this->dependency(this->dependency_size() - 1).data(),
this->dependency(this->dependency_size() - 1).length(),
::google::protobuf::internal::WireFormat::PARSE,
- "dependency");
+ "google.protobuf.FileDescriptorProto.dependency");
} else {
goto handle_unusual;
}
@@ -1276,6 +1362,23 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
goto handle_unusual;
}
if (input->ExpectTag(88)) goto parse_weak_dependency;
+ if (input->ExpectTag(98)) goto parse_syntax;
+ break;
+ }
+
+ // optional string syntax = 12;
+ case 12: {
+ if (tag == 98) {
+ parse_syntax:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_syntax()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->syntax().data(), this->syntax().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.FileDescriptorProto.syntax");
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1310,7 +1413,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.FileDescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -1320,7 +1423,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->package().data(), this->package().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "package");
+ "google.protobuf.FileDescriptorProto.package");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->package(), output);
}
@@ -1330,7 +1433,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->dependency(i).data(), this->dependency(i).length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "dependency");
+ "google.protobuf.FileDescriptorProto.dependency");
::google::protobuf::internal::WireFormatLite::WriteString(
3, this->dependency(i), output);
}
@@ -1383,7 +1486,17 @@ void FileDescriptorProto::SerializeWithCachedSizes(
11, this->weak_dependency(i), output);
}
- if (!unknown_fields().empty()) {
+ // optional string syntax = 12;
+ if (has_syntax()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->syntax().data(), this->syntax().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileDescriptorProto.syntax");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 12, this->syntax(), output);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -1398,7 +1511,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.FileDescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -1409,7 +1522,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->package().data(), this->package().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "package");
+ "google.protobuf.FileDescriptorProto.package");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->package(), target);
@@ -1420,7 +1533,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->dependency(i).data(), this->dependency(i).length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "dependency");
+ "google.protobuf.FileDescriptorProto.dependency");
target = ::google::protobuf::internal::WireFormatLite::
WriteStringToArray(3, this->dependency(i), target);
}
@@ -1479,7 +1592,18 @@ void FileDescriptorProto::SerializeWithCachedSizes(
WriteInt32ToArray(11, this->weak_dependency(i), target);
}
- if (!unknown_fields().empty()) {
+ // optional string syntax = 12;
+ if (has_syntax()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->syntax().data(), this->syntax().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileDescriptorProto.syntax");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 12, this->syntax(), target);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -1490,7 +1614,7 @@ void FileDescriptorProto::SerializeWithCachedSizes(
int FileDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 3) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -1506,7 +1630,7 @@ int FileDescriptorProto::ByteSize() const {
}
}
- if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) {
+ if (_has_bits_[9 / 32] & 3584) {
// optional .google.protobuf.FileOptions options = 8;
if (has_options()) {
total_size += 1 +
@@ -1521,6 +1645,13 @@ int FileDescriptorProto::ByteSize() const {
this->source_code_info());
}
+ // optional string syntax = 12;
+ if (has_syntax()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->syntax());
+ }
+
}
// repeated string dependency = 3;
total_size += 1 * this->dependency_size();
@@ -1581,7 +1712,7 @@ int FileDescriptorProto::ByteSize() const {
this->extension(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -1628,8 +1759,13 @@ void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
if (from.has_source_code_info()) {
mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info());
}
+ if (from.has_syntax()) {
+ set_syntax(from.syntax());
+ }
+ }
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
}
void FileDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -1657,22 +1793,37 @@ bool FileDescriptorProto::IsInitialized() const {
}
void FileDescriptorProto::Swap(FileDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- std::swap(package_, other->package_);
- dependency_.Swap(&other->dependency_);
- public_dependency_.Swap(&other->public_dependency_);
- weak_dependency_.Swap(&other->weak_dependency_);
- message_type_.Swap(&other->message_type_);
- enum_type_.Swap(&other->enum_type_);
- service_.Swap(&other->service_);
- extension_.Swap(&other->extension_);
- std::swap(options_, other->options_);
- std::swap(source_code_info_, other->source_code_info_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- }
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ FileDescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
+ }
+}
+void FileDescriptorProto::UnsafeArenaSwap(FileDescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
+ name_.Swap(&other->name_);
+ package_.Swap(&other->package_);
+ dependency_.UnsafeArenaSwap(&other->dependency_);
+ public_dependency_.UnsafeArenaSwap(&other->public_dependency_);
+ weak_dependency_.UnsafeArenaSwap(&other->weak_dependency_);
+ message_type_.UnsafeArenaSwap(&other->message_type_);
+ enum_type_.UnsafeArenaSwap(&other->enum_type_);
+ service_.UnsafeArenaSwap(&other->service_);
+ extension_.UnsafeArenaSwap(&other->extension_);
+ std::swap(options_, other->options_);
+ std::swap(source_code_info_, other->source_code_info_);
+ syntax_.Swap(&other->syntax_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata FileDescriptorProto::GetMetadata() const {
@@ -1692,16 +1843,25 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber;
#endif // !_MSC_VER
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange)
}
+DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ExtensionRange)
+}
+
void DescriptorProto_ExtensionRange::InitAsDefaultInstance() {
}
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange)
@@ -1720,10 +1880,20 @@ DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() {
}
void DescriptorProto_ExtensionRange::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void DescriptorProto_ExtensionRange::ArenaDtor(void* object) {
+ DescriptorProto_ExtensionRange* _this = reinterpret_cast< DescriptorProto_ExtensionRange* >(object);
+ (void)_this;
+}
+void DescriptorProto_ExtensionRange::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void DescriptorProto_ExtensionRange::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -1741,8 +1911,8 @@ const DescriptorProto_ExtensionRange& DescriptorProto_ExtensionRange::default_in
DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::default_instance_ = NULL;
-DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New() const {
- return new DescriptorProto_ExtensionRange;
+DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<DescriptorProto_ExtensionRange>(arena);
}
void DescriptorProto_ExtensionRange::Clear() {
@@ -1762,7 +1932,9 @@ void DescriptorProto_ExtensionRange::Clear() {
#undef ZR_
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream(
@@ -1839,7 +2011,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -1859,7 +2031,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -1870,7 +2042,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes(
int DescriptorProto_ExtensionRange::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 3) {
// optional int32 start = 1;
if (has_start()) {
total_size += 1 +
@@ -1886,7 +2058,7 @@ int DescriptorProto_ExtensionRange::ByteSize() const {
}
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -1919,7 +2091,9 @@ void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRa
set_end(from.end());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void DescriptorProto_ExtensionRange::CopyFrom(const ::google::protobuf::Message& from) {
@@ -1940,14 +2114,28 @@ bool DescriptorProto_ExtensionRange::IsInitialized() const {
}
void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) {
- if (other != this) {
- std::swap(start_, other->start_);
- std::swap(end_, other->end_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ DescriptorProto_ExtensionRange temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void DescriptorProto_ExtensionRange::UnsafeArenaSwap(DescriptorProto_ExtensionRange* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange* other) {
+ std::swap(start_, other->start_);
+ std::swap(end_, other->end_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata DescriptorProto_ExtensionRange::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -1972,17 +2160,32 @@ const int DescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
DescriptorProto::DescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto)
}
+DescriptorProto::DescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ field_(arena),
+ extension_(arena),
+ nested_type_(arena),
+ enum_type_(arena),
+ extension_range_(arena),
+ oneof_decl_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto)
+}
+
void DescriptorProto::InitAsDefaultInstance() {
options_ = const_cast< ::google::protobuf::MessageOptions*>(&::google::protobuf::MessageOptions::default_instance());
}
DescriptorProto::DescriptorProto(const DescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto)
@@ -1991,7 +2194,7 @@ DescriptorProto::DescriptorProto(const DescriptorProto& from)
void DescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -2002,14 +2205,22 @@ DescriptorProto::~DescriptorProto() {
}
void DescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
delete options_;
}
}
+void DescriptorProto::ArenaDtor(void* object) {
+ DescriptorProto* _this = reinterpret_cast< DescriptorProto* >(object);
+ (void)_this;
+}
+void DescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void DescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -2027,16 +2238,14 @@ const DescriptorProto& DescriptorProto::default_instance() {
DescriptorProto* DescriptorProto::default_instance_ = NULL;
-DescriptorProto* DescriptorProto::New() const {
- return new DescriptorProto;
+DescriptorProto* DescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<DescriptorProto>(arena);
}
void DescriptorProto::Clear() {
if (_has_bits_[0 / 32] & 129) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
@@ -2049,7 +2258,9 @@ void DescriptorProto::Clear() {
extension_range_.Clear();
oneof_decl_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool DescriptorProto::MergePartialFromCodedStream(
@@ -2070,7 +2281,7 @@ bool DescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.DescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -2205,7 +2416,7 @@ void DescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.DescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -2252,7 +2463,7 @@ void DescriptorProto::SerializeWithCachedSizes(
8, this->oneof_decl(i), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -2267,7 +2478,7 @@ void DescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.DescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -2322,7 +2533,7 @@ void DescriptorProto::SerializeWithCachedSizes(
8, this->oneof_decl(i), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -2333,7 +2544,7 @@ void DescriptorProto::SerializeWithCachedSizes(
int DescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 129) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -2397,7 +2608,7 @@ int DescriptorProto::ByteSize() const {
this->oneof_decl(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -2436,7 +2647,9 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) {
mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void DescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -2464,19 +2677,33 @@ bool DescriptorProto::IsInitialized() const {
}
void DescriptorProto::Swap(DescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- field_.Swap(&other->field_);
- extension_.Swap(&other->extension_);
- 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_);
- std::swap(_cached_size_, other->_cached_size_);
- }
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ DescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
+ }
+}
+void DescriptorProto::UnsafeArenaSwap(DescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void DescriptorProto::InternalSwap(DescriptorProto* other) {
+ name_.Swap(&other->name_);
+ field_.UnsafeArenaSwap(&other->field_);
+ extension_.UnsafeArenaSwap(&other->extension_);
+ nested_type_.UnsafeArenaSwap(&other->nested_type_);
+ enum_type_.UnsafeArenaSwap(&other->enum_type_);
+ extension_range_.UnsafeArenaSwap(&other->extension_range_);
+ oneof_decl_.UnsafeArenaSwap(&other->oneof_decl_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata DescriptorProto::GetMetadata() const {
@@ -2579,17 +2806,26 @@ const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FieldDescriptorProto::FieldDescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto)
}
+FieldDescriptorProto::FieldDescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldDescriptorProto)
+}
+
void FieldDescriptorProto::InitAsDefaultInstance() {
options_ = const_cast< ::google::protobuf::FieldOptions*>(&::google::protobuf::FieldOptions::default_instance());
}
FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto)
@@ -2598,13 +2834,13 @@ FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from)
void FieldDescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
number_ = 0;
label_ = 1;
type_ = 1;
- 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());
+ type_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ extendee_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
oneof_index_ = 0;
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -2616,23 +2852,25 @@ FieldDescriptorProto::~FieldDescriptorProto() {
}
void FieldDescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
- }
- if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete type_name_;
- }
- if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete extendee_;
- }
- if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete default_value_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ type_name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ extendee_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ default_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
delete options_;
}
}
+void FieldDescriptorProto::ArenaDtor(void* object) {
+ FieldDescriptorProto* _this = reinterpret_cast< FieldDescriptorProto* >(object);
+ (void)_this;
+}
+void FieldDescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void FieldDescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -2650,34 +2888,26 @@ const FieldDescriptorProto& FieldDescriptorProto::default_instance() {
FieldDescriptorProto* FieldDescriptorProto::default_instance_ = NULL;
-FieldDescriptorProto* FieldDescriptorProto::New() const {
- return new FieldDescriptorProto;
+FieldDescriptorProto* FieldDescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<FieldDescriptorProto>(arena);
}
void FieldDescriptorProto::Clear() {
if (_has_bits_[0 / 32] & 255) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
number_ = 0;
label_ = 1;
type_ = 1;
if (has_type_name()) {
- if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- type_name_->clear();
- }
+ type_name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_extendee()) {
- if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- extendee_->clear();
- }
+ extendee_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_default_value()) {
- if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- default_value_->clear();
- }
+ default_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
oneof_index_ = 0;
}
@@ -2685,7 +2915,9 @@ void FieldDescriptorProto::Clear() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool FieldDescriptorProto::MergePartialFromCodedStream(
@@ -2706,7 +2938,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.FieldDescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -2723,7 +2955,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->extendee().data(), this->extendee().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "extendee");
+ "google.protobuf.FieldDescriptorProto.extendee");
} else {
goto handle_unusual;
}
@@ -2795,7 +3027,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->type_name().data(), this->type_name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "type_name");
+ "google.protobuf.FieldDescriptorProto.type_name");
} else {
goto handle_unusual;
}
@@ -2812,7 +3044,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->default_value().data(), this->default_value().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "default_value");
+ "google.protobuf.FieldDescriptorProto.default_value");
} else {
goto handle_unusual;
}
@@ -2878,7 +3110,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.FieldDescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -2888,7 +3120,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->extendee().data(), this->extendee().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "extendee");
+ "google.protobuf.FieldDescriptorProto.extendee");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->extendee(), output);
}
@@ -2915,7 +3147,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->type_name().data(), this->type_name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "type_name");
+ "google.protobuf.FieldDescriptorProto.type_name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
6, this->type_name(), output);
}
@@ -2925,7 +3157,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->default_value().data(), this->default_value().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "default_value");
+ "google.protobuf.FieldDescriptorProto.default_value");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
7, this->default_value(), output);
}
@@ -2941,7 +3173,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->oneof_index(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -2956,7 +3188,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.FieldDescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -2967,7 +3199,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->extendee().data(), this->extendee().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "extendee");
+ "google.protobuf.FieldDescriptorProto.extendee");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->extendee(), target);
@@ -2995,7 +3227,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->type_name().data(), this->type_name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "type_name");
+ "google.protobuf.FieldDescriptorProto.type_name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
6, this->type_name(), target);
@@ -3006,7 +3238,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->default_value().data(), this->default_value().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "default_value");
+ "google.protobuf.FieldDescriptorProto.default_value");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
7, this->default_value(), target);
@@ -3024,7 +3256,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->oneof_index(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -3035,7 +3267,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes(
int FieldDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 255) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -3091,16 +3323,14 @@ int FieldDescriptorProto::ByteSize() const {
}
}
- if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
- // optional .google.protobuf.FieldOptions options = 8;
- if (has_options()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
- this->options());
- }
-
+ // optional .google.protobuf.FieldOptions options = 8;
+ if (has_options()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->options());
}
- if (!unknown_fields().empty()) {
+
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -3156,7 +3386,9 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void FieldDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -3180,20 +3412,34 @@ bool FieldDescriptorProto::IsInitialized() const {
}
void FieldDescriptorProto::Swap(FieldDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- std::swap(number_, other->number_);
- std::swap(label_, other->label_);
- std::swap(type_, other->type_);
- 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_);
- std::swap(_cached_size_, other->_cached_size_);
- }
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ FieldDescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
+ }
+}
+void FieldDescriptorProto::UnsafeArenaSwap(FieldDescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
+ name_.Swap(&other->name_);
+ std::swap(number_, other->number_);
+ std::swap(label_, other->label_);
+ std::swap(type_, other->type_);
+ type_name_.Swap(&other->type_name_);
+ extendee_.Swap(&other->extendee_);
+ default_value_.Swap(&other->default_value_);
+ std::swap(oneof_index_, other->oneof_index_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata FieldDescriptorProto::GetMetadata() const {
@@ -3212,16 +3458,25 @@ const int OneofDescriptorProto::kNameFieldNumber;
#endif // !_MSC_VER
OneofDescriptorProto::OneofDescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto)
}
+OneofDescriptorProto::OneofDescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.OneofDescriptorProto)
+}
+
void OneofDescriptorProto::InitAsDefaultInstance() {
}
OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto)
@@ -3230,7 +3485,7 @@ OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from)
void OneofDescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -3240,13 +3495,21 @@ OneofDescriptorProto::~OneofDescriptorProto() {
}
void OneofDescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void OneofDescriptorProto::ArenaDtor(void* object) {
+ OneofDescriptorProto* _this = reinterpret_cast< OneofDescriptorProto* >(object);
+ (void)_this;
+}
+void OneofDescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void OneofDescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -3264,18 +3527,18 @@ const OneofDescriptorProto& OneofDescriptorProto::default_instance() {
OneofDescriptorProto* OneofDescriptorProto::default_instance_ = NULL;
-OneofDescriptorProto* OneofDescriptorProto::New() const {
- return new OneofDescriptorProto;
+OneofDescriptorProto* OneofDescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<OneofDescriptorProto>(arena);
}
void OneofDescriptorProto::Clear() {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool OneofDescriptorProto::MergePartialFromCodedStream(
@@ -3296,7 +3559,7 @@ bool OneofDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.OneofDescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -3334,12 +3597,12 @@ void OneofDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.OneofDescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -3354,13 +3617,13 @@ void OneofDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.OneofDescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -3371,16 +3634,14 @@ void OneofDescriptorProto::SerializeWithCachedSizes(
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());
- }
-
+ // optional string name = 1;
+ if (has_name()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name());
}
- if (!unknown_fields().empty()) {
+
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -3410,7 +3671,9 @@ void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) {
set_name(from.name());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void OneofDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -3431,13 +3694,27 @@ bool OneofDescriptorProto::IsInitialized() const {
}
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_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ OneofDescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void OneofDescriptorProto::UnsafeArenaSwap(OneofDescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
+ name_.Swap(&other->name_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata OneofDescriptorProto::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -3457,17 +3734,27 @@ const int EnumDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumDescriptorProto::EnumDescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto)
}
+EnumDescriptorProto::EnumDescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ value_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto)
+}
+
void EnumDescriptorProto::InitAsDefaultInstance() {
options_ = const_cast< ::google::protobuf::EnumOptions*>(&::google::protobuf::EnumOptions::default_instance());
}
EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto)
@@ -3476,7 +3763,7 @@ EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from)
void EnumDescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -3487,14 +3774,22 @@ EnumDescriptorProto::~EnumDescriptorProto() {
}
void EnumDescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
delete options_;
}
}
+void EnumDescriptorProto::ArenaDtor(void* object) {
+ EnumDescriptorProto* _this = reinterpret_cast< EnumDescriptorProto* >(object);
+ (void)_this;
+}
+void EnumDescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void EnumDescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -3512,16 +3807,14 @@ const EnumDescriptorProto& EnumDescriptorProto::default_instance() {
EnumDescriptorProto* EnumDescriptorProto::default_instance_ = NULL;
-EnumDescriptorProto* EnumDescriptorProto::New() const {
- return new EnumDescriptorProto;
+EnumDescriptorProto* EnumDescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<EnumDescriptorProto>(arena);
}
void EnumDescriptorProto::Clear() {
if (_has_bits_[0 / 32] & 5) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
@@ -3529,7 +3822,9 @@ void EnumDescriptorProto::Clear() {
}
value_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool EnumDescriptorProto::MergePartialFromCodedStream(
@@ -3550,7 +3845,7 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.EnumDescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -3615,7 +3910,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.EnumDescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -3632,7 +3927,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
3, this->options(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -3647,7 +3942,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.EnumDescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -3667,7 +3962,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
3, this->options(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -3678,7 +3973,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes(
int EnumDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 5) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -3702,7 +3997,7 @@ int EnumDescriptorProto::ByteSize() const {
this->value(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -3736,7 +4031,9 @@ void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) {
mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void EnumDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -3761,15 +4058,29 @@ bool EnumDescriptorProto::IsInitialized() const {
}
void EnumDescriptorProto::Swap(EnumDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- value_.Swap(&other->value_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ EnumDescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void EnumDescriptorProto::UnsafeArenaSwap(EnumDescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
+ name_.Swap(&other->name_);
+ value_.UnsafeArenaSwap(&other->value_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata EnumDescriptorProto::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -3789,17 +4100,26 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumValueDescriptorProto::EnumValueDescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto)
}
+EnumValueDescriptorProto::EnumValueDescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueDescriptorProto)
+}
+
void EnumValueDescriptorProto::InitAsDefaultInstance() {
options_ = const_cast< ::google::protobuf::EnumValueOptions*>(&::google::protobuf::EnumValueOptions::default_instance());
}
EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto)
@@ -3808,7 +4128,7 @@ EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProt
void EnumValueDescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
number_ = 0;
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -3820,14 +4140,22 @@ EnumValueDescriptorProto::~EnumValueDescriptorProto() {
}
void EnumValueDescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
delete options_;
}
}
+void EnumValueDescriptorProto::ArenaDtor(void* object) {
+ EnumValueDescriptorProto* _this = reinterpret_cast< EnumValueDescriptorProto* >(object);
+ (void)_this;
+}
+void EnumValueDescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void EnumValueDescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -3845,16 +4173,14 @@ const EnumValueDescriptorProto& EnumValueDescriptorProto::default_instance() {
EnumValueDescriptorProto* EnumValueDescriptorProto::default_instance_ = NULL;
-EnumValueDescriptorProto* EnumValueDescriptorProto::New() const {
- return new EnumValueDescriptorProto;
+EnumValueDescriptorProto* EnumValueDescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<EnumValueDescriptorProto>(arena);
}
void EnumValueDescriptorProto::Clear() {
if (_has_bits_[0 / 32] & 7) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
number_ = 0;
if (has_options()) {
@@ -3862,7 +4188,9 @@ void EnumValueDescriptorProto::Clear() {
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool EnumValueDescriptorProto::MergePartialFromCodedStream(
@@ -3883,7 +4211,7 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.EnumValueDescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -3949,7 +4277,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.EnumValueDescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -3965,7 +4293,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
3, this->options(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -3980,7 +4308,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.EnumValueDescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -3998,7 +4326,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
3, this->options(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -4009,7 +4337,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes(
int EnumValueDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 7) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -4032,7 +4360,7 @@ int EnumValueDescriptorProto::ByteSize() const {
}
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -4068,7 +4396,9 @@ void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void EnumValueDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -4092,15 +4422,29 @@ bool EnumValueDescriptorProto::IsInitialized() const {
}
void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- std::swap(number_, other->number_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ EnumValueDescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void EnumValueDescriptorProto::UnsafeArenaSwap(EnumValueDescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
+ name_.Swap(&other->name_);
+ std::swap(number_, other->number_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata EnumValueDescriptorProto::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -4120,17 +4464,27 @@ const int ServiceDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
ServiceDescriptorProto::ServiceDescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto)
}
+ServiceDescriptorProto::ServiceDescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ method_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceDescriptorProto)
+}
+
void ServiceDescriptorProto::InitAsDefaultInstance() {
options_ = const_cast< ::google::protobuf::ServiceOptions*>(&::google::protobuf::ServiceOptions::default_instance());
}
ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto)
@@ -4139,7 +4493,7 @@ ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& fro
void ServiceDescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -4150,14 +4504,22 @@ ServiceDescriptorProto::~ServiceDescriptorProto() {
}
void ServiceDescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
delete options_;
}
}
+void ServiceDescriptorProto::ArenaDtor(void* object) {
+ ServiceDescriptorProto* _this = reinterpret_cast< ServiceDescriptorProto* >(object);
+ (void)_this;
+}
+void ServiceDescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void ServiceDescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -4175,16 +4537,14 @@ const ServiceDescriptorProto& ServiceDescriptorProto::default_instance() {
ServiceDescriptorProto* ServiceDescriptorProto::default_instance_ = NULL;
-ServiceDescriptorProto* ServiceDescriptorProto::New() const {
- return new ServiceDescriptorProto;
+ServiceDescriptorProto* ServiceDescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<ServiceDescriptorProto>(arena);
}
void ServiceDescriptorProto::Clear() {
if (_has_bits_[0 / 32] & 5) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
@@ -4192,7 +4552,9 @@ void ServiceDescriptorProto::Clear() {
}
method_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool ServiceDescriptorProto::MergePartialFromCodedStream(
@@ -4213,7 +4575,7 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.ServiceDescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -4278,7 +4640,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.ServiceDescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -4295,7 +4657,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
3, this->options(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -4310,7 +4672,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.ServiceDescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -4330,7 +4692,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
3, this->options(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -4341,7 +4703,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes(
int ServiceDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 5) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -4365,7 +4727,7 @@ int ServiceDescriptorProto::ByteSize() const {
this->method(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -4399,7 +4761,9 @@ void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) {
mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void ServiceDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -4424,15 +4788,29 @@ bool ServiceDescriptorProto::IsInitialized() const {
}
void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- method_.Swap(&other->method_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ ServiceDescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void ServiceDescriptorProto::UnsafeArenaSwap(ServiceDescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
+ name_.Swap(&other->name_);
+ method_.UnsafeArenaSwap(&other->method_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata ServiceDescriptorProto::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -4453,17 +4831,26 @@ const int MethodDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
MethodDescriptorProto::MethodDescriptorProto()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto)
}
+MethodDescriptorProto::MethodDescriptorProto(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodDescriptorProto)
+}
+
void MethodDescriptorProto::InitAsDefaultInstance() {
options_ = const_cast< ::google::protobuf::MethodOptions*>(&::google::protobuf::MethodOptions::default_instance());
}
MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto)
@@ -4472,9 +4859,9 @@ MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from)
void MethodDescriptorProto::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- 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());
+ name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ input_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ output_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
options_ = NULL;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -4485,20 +4872,24 @@ MethodDescriptorProto::~MethodDescriptorProto() {
}
void MethodDescriptorProto::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
- }
- if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete input_type_;
- }
- if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete output_type_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ input_type_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ output_type_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
delete options_;
}
}
+void MethodDescriptorProto::ArenaDtor(void* object) {
+ MethodDescriptorProto* _this = reinterpret_cast< MethodDescriptorProto* >(object);
+ (void)_this;
+}
+void MethodDescriptorProto::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void MethodDescriptorProto::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -4516,33 +4907,29 @@ const MethodDescriptorProto& MethodDescriptorProto::default_instance() {
MethodDescriptorProto* MethodDescriptorProto::default_instance_ = NULL;
-MethodDescriptorProto* MethodDescriptorProto::New() const {
- return new MethodDescriptorProto;
+MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<MethodDescriptorProto>(arena);
}
void MethodDescriptorProto::Clear() {
if (_has_bits_[0 / 32] & 15) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_input_type()) {
- if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- input_type_->clear();
- }
+ input_type_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_output_type()) {
- if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- output_type_->clear();
- }
+ output_type_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_options()) {
if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool MethodDescriptorProto::MergePartialFromCodedStream(
@@ -4563,7 +4950,7 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.MethodDescriptorProto.name");
} else {
goto handle_unusual;
}
@@ -4580,7 +4967,7 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->input_type().data(), this->input_type().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "input_type");
+ "google.protobuf.MethodDescriptorProto.input_type");
} else {
goto handle_unusual;
}
@@ -4597,7 +4984,7 @@ bool MethodDescriptorProto::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->output_type().data(), this->output_type().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "output_type");
+ "google.protobuf.MethodDescriptorProto.output_type");
} else {
goto handle_unusual;
}
@@ -4648,7 +5035,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.MethodDescriptorProto.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -4658,7 +5045,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->input_type().data(), this->input_type().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "input_type");
+ "google.protobuf.MethodDescriptorProto.input_type");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->input_type(), output);
}
@@ -4668,7 +5055,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->output_type().data(), this->output_type().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "output_type");
+ "google.protobuf.MethodDescriptorProto.output_type");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
3, this->output_type(), output);
}
@@ -4679,7 +5066,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
4, this->options(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -4694,7 +5081,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.MethodDescriptorProto.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -4705,7 +5092,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->input_type().data(), this->input_type().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "input_type");
+ "google.protobuf.MethodDescriptorProto.input_type");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->input_type(), target);
@@ -4716,7 +5103,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->output_type().data(), this->output_type().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "output_type");
+ "google.protobuf.MethodDescriptorProto.output_type");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
3, this->output_type(), target);
@@ -4729,7 +5116,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
4, this->options(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -4740,7 +5127,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes(
int MethodDescriptorProto::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 15) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -4770,7 +5157,7 @@ int MethodDescriptorProto::ByteSize() const {
}
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -4809,7 +5196,9 @@ void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void MethodDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) {
@@ -4833,16 +5222,30 @@ bool MethodDescriptorProto::IsInitialized() const {
}
void MethodDescriptorProto::Swap(MethodDescriptorProto* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- std::swap(input_type_, other->input_type_);
- std::swap(output_type_, other->output_type_);
- std::swap(options_, other->options_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ MethodDescriptorProto temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void MethodDescriptorProto::UnsafeArenaSwap(MethodDescriptorProto* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
+ name_.Swap(&other->name_);
+ input_type_.Swap(&other->input_type_);
+ output_type_.Swap(&other->output_type_);
+ std::swap(options_, other->options_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata MethodDescriptorProto::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -4894,16 +5297,26 @@ const int FileOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FileOptions::FileOptions()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileOptions)
}
+FileOptions::FileOptions(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _extensions_(arena), _internal_metadata_(arena),
+ uninterpreted_option_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.FileOptions)
+}
+
void FileOptions::InitAsDefaultInstance() {
}
FileOptions::FileOptions(const FileOptions& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions)
@@ -4912,13 +5325,13 @@ FileOptions::FileOptions(const FileOptions& from)
void FileOptions::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ java_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ java_outer_classname_.UnsafeSetDefault(&::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::GetEmptyStringAlreadyInited());
+ go_package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
cc_generic_services_ = false;
java_generic_services_ = false;
py_generic_services_ = false;
@@ -4932,19 +5345,23 @@ FileOptions::~FileOptions() {
}
void FileOptions::SharedDtor() {
- if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete java_package_;
- }
- if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete java_outer_classname_;
- }
- if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete go_package_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ java_package_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ java_outer_classname_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ go_package_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void FileOptions::ArenaDtor(void* object) {
+ FileOptions* _this = reinterpret_cast< FileOptions* >(object);
+ (void)_this;
+}
+void FileOptions::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void FileOptions::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -4962,8 +5379,8 @@ const FileOptions& FileOptions::default_instance() {
FileOptions* FileOptions::default_instance_ = NULL;
-FileOptions* FileOptions::New() const {
- return new FileOptions;
+FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<FileOptions>(arena);
}
void FileOptions::Clear() {
@@ -4981,20 +5398,14 @@ void FileOptions::Clear() {
if (_has_bits_[0 / 32] & 255) {
ZR_(java_multiple_files_, cc_generic_services_);
if (has_java_package()) {
- if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- java_package_->clear();
- }
+ java_package_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_java_outer_classname()) {
- if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- java_outer_classname_->clear();
- }
+ java_outer_classname_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
optimize_for_ = 1;
if (has_go_package()) {
- if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- go_package_->clear();
- }
+ go_package_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
}
ZR_(java_generic_services_, deprecated_);
@@ -5004,7 +5415,9 @@ void FileOptions::Clear() {
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool FileOptions::MergePartialFromCodedStream(
@@ -5025,7 +5438,7 @@ bool FileOptions::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->java_package().data(), this->java_package().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "java_package");
+ "google.protobuf.FileOptions.java_package");
} else {
goto handle_unusual;
}
@@ -5042,7 +5455,7 @@ bool FileOptions::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->java_outer_classname().data(), this->java_outer_classname().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "java_outer_classname");
+ "google.protobuf.FileOptions.java_outer_classname");
} else {
goto handle_unusual;
}
@@ -5094,7 +5507,7 @@ bool FileOptions::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->go_package().data(), this->go_package().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "go_package");
+ "google.protobuf.FileOptions.go_package");
} else {
goto handle_unusual;
}
@@ -5241,7 +5654,7 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->java_package().data(), this->java_package().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "java_package");
+ "google.protobuf.FileOptions.java_package");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->java_package(), output);
}
@@ -5251,7 +5664,7 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->java_outer_classname().data(), this->java_outer_classname().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "java_outer_classname");
+ "google.protobuf.FileOptions.java_outer_classname");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
8, this->java_outer_classname(), output);
}
@@ -5272,7 +5685,7 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->go_package().data(), this->go_package().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "go_package");
+ "google.protobuf.FileOptions.go_package");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
11, this->go_package(), output);
}
@@ -5317,7 +5730,7 @@ void FileOptions::SerializeWithCachedSizes(
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -5332,7 +5745,7 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->java_package().data(), this->java_package().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "java_package");
+ "google.protobuf.FileOptions.java_package");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->java_package(), target);
@@ -5343,7 +5756,7 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->java_outer_classname().data(), this->java_outer_classname().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "java_outer_classname");
+ "google.protobuf.FileOptions.java_outer_classname");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
8, this->java_outer_classname(), target);
@@ -5365,7 +5778,7 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->go_package().data(), this->go_package().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "go_package");
+ "google.protobuf.FileOptions.go_package");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
11, this->go_package(), target);
@@ -5412,7 +5825,7 @@ void FileOptions::SerializeWithCachedSizes(
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -5423,7 +5836,7 @@ void FileOptions::SerializeWithCachedSizes(
int FileOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 255) {
// optional string java_package = 1;
if (has_java_package()) {
total_size += 1 +
@@ -5472,7 +5885,7 @@ int FileOptions::ByteSize() const {
}
}
- if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) {
+ if (_has_bits_[8 / 32] & 1792) {
// optional bool java_generic_services = 17 [default = false];
if (has_java_generic_services()) {
total_size += 2 + 1;
@@ -5499,7 +5912,7 @@ int FileOptions::ByteSize() const {
total_size += _extensions_.ByteSize();
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -5563,7 +5976,9 @@ void FileOptions::MergeFrom(const FileOptions& from) {
}
}
_extensions_.MergeFrom(from._extensions_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void FileOptions::CopyFrom(const ::google::protobuf::Message& from) {
@@ -5586,24 +6001,38 @@ bool FileOptions::IsInitialized() const {
}
void FileOptions::Swap(FileOptions* other) {
- if (other != this) {
- std::swap(java_package_, other->java_package_);
- std::swap(java_outer_classname_, other->java_outer_classname_);
- std::swap(java_multiple_files_, other->java_multiple_files_);
- std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
- std::swap(java_string_check_utf8_, other->java_string_check_utf8_);
- std::swap(optimize_for_, other->optimize_for_);
- std::swap(go_package_, other->go_package_);
- std::swap(cc_generic_services_, other->cc_generic_services_);
- std::swap(java_generic_services_, other->java_generic_services_);
- std::swap(py_generic_services_, other->py_generic_services_);
- std::swap(deprecated_, other->deprecated_);
- uninterpreted_option_.Swap(&other->uninterpreted_option_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- _extensions_.Swap(&other->_extensions_);
- }
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ FileOptions temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
+ }
+}
+void FileOptions::UnsafeArenaSwap(FileOptions* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void FileOptions::InternalSwap(FileOptions* other) {
+ java_package_.Swap(&other->java_package_);
+ java_outer_classname_.Swap(&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_);
+ go_package_.Swap(&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_.UnsafeArenaSwap(&other->uninterpreted_option_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+ _extensions_.Swap(&other->_extensions_);
}
::google::protobuf::Metadata FileOptions::GetMetadata() const {
@@ -5621,20 +6050,31 @@ void FileOptions::Swap(FileOptions* other) {
const int MessageOptions::kMessageSetWireFormatFieldNumber;
const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber;
const int MessageOptions::kDeprecatedFieldNumber;
+const int MessageOptions::kMapEntryFieldNumber;
const int MessageOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MessageOptions::MessageOptions()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MessageOptions)
}
+MessageOptions::MessageOptions(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _extensions_(arena), _internal_metadata_(arena),
+ uninterpreted_option_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.MessageOptions)
+}
+
void MessageOptions::InitAsDefaultInstance() {
}
MessageOptions::MessageOptions(const MessageOptions& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions)
@@ -5645,6 +6085,7 @@ void MessageOptions::SharedCtor() {
message_set_wire_format_ = false;
no_standard_descriptor_accessor_ = false;
deprecated_ = false;
+ map_entry_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -5654,10 +6095,20 @@ MessageOptions::~MessageOptions() {
}
void MessageOptions::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void MessageOptions::ArenaDtor(void* object) {
+ MessageOptions* _this = reinterpret_cast< MessageOptions* >(object);
+ (void)_this;
+}
+void MessageOptions::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void MessageOptions::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -5675,8 +6126,8 @@ const MessageOptions& MessageOptions::default_instance() {
MessageOptions* MessageOptions::default_instance_ = NULL;
-MessageOptions* MessageOptions::New() const {
- return new MessageOptions;
+MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<MessageOptions>(arena);
}
void MessageOptions::Clear() {
@@ -5691,14 +6142,16 @@ void MessageOptions::Clear() {
::memset(&first, 0, n); \
} while (0)
- ZR_(message_set_wire_format_, deprecated_);
+ ZR_(message_set_wire_format_, map_entry_);
#undef OFFSET_OF_FIELD_
#undef ZR_
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool MessageOptions::MergePartialFromCodedStream(
@@ -5751,6 +6204,21 @@ bool MessageOptions::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(56)) goto parse_map_entry;
+ break;
+ }
+
+ // optional bool map_entry = 7;
+ case 7: {
+ if (tag == 56) {
+ parse_map_entry:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+ input, &map_entry_)));
+ set_has_map_entry();
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
@@ -5814,6 +6282,11 @@ void MessageOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output);
}
+ // optional bool map_entry = 7;
+ if (has_map_entry()) {
+ ::google::protobuf::internal::WireFormatLite::WriteBool(7, this->map_entry(), output);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
@@ -5824,7 +6297,7 @@ void MessageOptions::SerializeWithCachedSizes(
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -5849,6 +6322,11 @@ void MessageOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target);
}
+ // optional bool map_entry = 7;
+ if (has_map_entry()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(7, this->map_entry(), target);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (int i = 0; i < this->uninterpreted_option_size(); i++) {
target = ::google::protobuf::internal::WireFormatLite::
@@ -5860,7 +6338,7 @@ void MessageOptions::SerializeWithCachedSizes(
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -5871,7 +6349,7 @@ void MessageOptions::SerializeWithCachedSizes(
int MessageOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 15) {
// optional bool message_set_wire_format = 1 [default = false];
if (has_message_set_wire_format()) {
total_size += 1 + 1;
@@ -5887,6 +6365,11 @@ int MessageOptions::ByteSize() const {
total_size += 1 + 1;
}
+ // optional bool map_entry = 7;
+ if (has_map_entry()) {
+ total_size += 1 + 1;
+ }
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -5898,7 +6381,7 @@ int MessageOptions::ByteSize() const {
total_size += _extensions_.ByteSize();
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -5934,9 +6417,14 @@ void MessageOptions::MergeFrom(const MessageOptions& from) {
if (from.has_deprecated()) {
set_deprecated(from.deprecated());
}
+ if (from.has_map_entry()) {
+ set_map_entry(from.map_entry());
+ }
}
_extensions_.MergeFrom(from._extensions_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void MessageOptions::CopyFrom(const ::google::protobuf::Message& from) {
@@ -5959,17 +6447,32 @@ bool MessageOptions::IsInitialized() const {
}
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_);
- std::swap(_cached_size_, other->_cached_size_);
- _extensions_.Swap(&other->_extensions_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ MessageOptions temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void MessageOptions::UnsafeArenaSwap(MessageOptions* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void MessageOptions::InternalSwap(MessageOptions* other) {
+ 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_);
+ std::swap(map_entry_, other->map_entry_);
+ uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+ _extensions_.Swap(&other->_extensions_);
+}
::google::protobuf::Metadata MessageOptions::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -6010,35 +6513,42 @@ const int FieldOptions::kCtypeFieldNumber;
const int FieldOptions::kPackedFieldNumber;
const int FieldOptions::kLazyFieldNumber;
const int FieldOptions::kDeprecatedFieldNumber;
-const int FieldOptions::kExperimentalMapKeyFieldNumber;
const int FieldOptions::kWeakFieldNumber;
const int FieldOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FieldOptions::FieldOptions()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FieldOptions)
}
+FieldOptions::FieldOptions(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _extensions_(arena), _internal_metadata_(arena),
+ uninterpreted_option_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.FieldOptions)
+}
+
void FieldOptions::InitAsDefaultInstance() {
}
FieldOptions::FieldOptions(const FieldOptions& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
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::GetEmptyStringAlreadyInited());
weak_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -6049,13 +6559,20 @@ FieldOptions::~FieldOptions() {
}
void FieldOptions::SharedDtor() {
- if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete experimental_map_key_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
if (this != default_instance_) {
}
}
+void FieldOptions::ArenaDtor(void* object) {
+ FieldOptions* _this = reinterpret_cast< FieldOptions* >(object);
+ (void)_this;
+}
+void FieldOptions::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void FieldOptions::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -6073,8 +6590,8 @@ const FieldOptions& FieldOptions::default_instance() {
FieldOptions* FieldOptions::default_instance_ = NULL;
-FieldOptions* FieldOptions::New() const {
- return new FieldOptions;
+FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<FieldOptions>(arena);
}
void FieldOptions::Clear() {
@@ -6089,13 +6606,8 @@ void FieldOptions::Clear() {
::memset(&first, 0, n); \
} while (0)
- if (_has_bits_[0 / 32] & 63) {
+ if (_has_bits_[0 / 32] & 31) {
ZR_(ctype_, weak_);
- if (has_experimental_map_key()) {
- if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- experimental_map_key_->clear();
- }
- }
}
#undef OFFSET_OF_FIELD_
@@ -6103,7 +6615,9 @@ void FieldOptions::Clear() {
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool FieldOptions::MergePartialFromCodedStream(
@@ -6176,23 +6690,6 @@ bool FieldOptions::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
- if (input->ExpectTag(74)) goto parse_experimental_map_key;
- break;
- }
-
- // optional string experimental_map_key = 9;
- case 9: {
- if (tag == 74) {
- parse_experimental_map_key:
- DO_(::google::protobuf::internal::WireFormatLite::ReadString(
- input, this->mutable_experimental_map_key()));
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->experimental_map_key().data(), this->experimental_map_key().length(),
- ::google::protobuf::internal::WireFormat::PARSE,
- "experimental_map_key");
- } else {
- goto handle_unusual;
- }
if (input->ExpectTag(80)) goto parse_weak;
break;
}
@@ -6277,16 +6774,6 @@ void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output);
}
- // optional string experimental_map_key = 9;
- if (has_experimental_map_key()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->experimental_map_key().data(), this->experimental_map_key().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "experimental_map_key");
- ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
- 9, this->experimental_map_key(), output);
- }
-
// optional bool weak = 10 [default = false];
if (has_weak()) {
::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output);
@@ -6302,7 +6789,7 @@ void FieldOptions::SerializeWithCachedSizes(
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -6333,17 +6820,6 @@ void FieldOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target);
}
- // optional string experimental_map_key = 9;
- if (has_experimental_map_key()) {
- ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
- this->experimental_map_key().data(), this->experimental_map_key().length(),
- ::google::protobuf::internal::WireFormat::SERIALIZE,
- "experimental_map_key");
- target =
- ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
- 9, this->experimental_map_key(), target);
- }
-
// optional bool weak = 10 [default = false];
if (has_weak()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target);
@@ -6360,7 +6836,7 @@ void FieldOptions::SerializeWithCachedSizes(
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -6371,7 +6847,7 @@ void FieldOptions::SerializeWithCachedSizes(
int FieldOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 31) {
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (has_ctype()) {
total_size += 1 +
@@ -6393,13 +6869,6 @@ int FieldOptions::ByteSize() const {
total_size += 1 + 1;
}
- // optional string experimental_map_key = 9;
- if (has_experimental_map_key()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::StringSize(
- this->experimental_map_key());
- }
-
// optional bool weak = 10 [default = false];
if (has_weak()) {
total_size += 1 + 1;
@@ -6416,7 +6885,7 @@ int FieldOptions::ByteSize() const {
total_size += _extensions_.ByteSize();
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -6455,15 +6924,14 @@ void FieldOptions::MergeFrom(const FieldOptions& from) {
if (from.has_deprecated()) {
set_deprecated(from.deprecated());
}
- if (from.has_experimental_map_key()) {
- set_experimental_map_key(from.experimental_map_key());
- }
if (from.has_weak()) {
set_weak(from.weak());
}
}
_extensions_.MergeFrom(from._extensions_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void FieldOptions::CopyFrom(const ::google::protobuf::Message& from) {
@@ -6486,19 +6954,32 @@ bool FieldOptions::IsInitialized() const {
}
void FieldOptions::Swap(FieldOptions* other) {
- if (other != this) {
- std::swap(ctype_, other->ctype_);
- std::swap(packed_, other->packed_);
- std::swap(lazy_, other->lazy_);
- std::swap(deprecated_, other->deprecated_);
- std::swap(experimental_map_key_, other->experimental_map_key_);
- std::swap(weak_, other->weak_);
- uninterpreted_option_.Swap(&other->uninterpreted_option_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- _extensions_.Swap(&other->_extensions_);
- }
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ FieldOptions temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
+ }
+}
+void FieldOptions::UnsafeArenaSwap(FieldOptions* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void FieldOptions::InternalSwap(FieldOptions* other) {
+ std::swap(ctype_, other->ctype_);
+ std::swap(packed_, other->packed_);
+ std::swap(lazy_, other->lazy_);
+ std::swap(deprecated_, other->deprecated_);
+ std::swap(weak_, other->weak_);
+ uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+ _extensions_.Swap(&other->_extensions_);
}
::google::protobuf::Metadata FieldOptions::GetMetadata() const {
@@ -6519,16 +7000,26 @@ const int EnumOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumOptions::EnumOptions()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumOptions)
}
+EnumOptions::EnumOptions(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _extensions_(arena), _internal_metadata_(arena),
+ uninterpreted_option_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumOptions)
+}
+
void EnumOptions::InitAsDefaultInstance() {
}
EnumOptions::EnumOptions(const EnumOptions& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions)
@@ -6547,10 +7038,20 @@ EnumOptions::~EnumOptions() {
}
void EnumOptions::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void EnumOptions::ArenaDtor(void* object) {
+ EnumOptions* _this = reinterpret_cast< EnumOptions* >(object);
+ (void)_this;
+}
+void EnumOptions::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void EnumOptions::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -6568,8 +7069,8 @@ const EnumOptions& EnumOptions::default_instance() {
EnumOptions* EnumOptions::default_instance_ = NULL;
-EnumOptions* EnumOptions::New() const {
- return new EnumOptions;
+EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<EnumOptions>(arena);
}
void EnumOptions::Clear() {
@@ -6591,7 +7092,9 @@ void EnumOptions::Clear() {
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool EnumOptions::MergePartialFromCodedStream(
@@ -6697,7 +7200,7 @@ void EnumOptions::SerializeWithCachedSizes(
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -6728,7 +7231,7 @@ void EnumOptions::SerializeWithCachedSizes(
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -6739,7 +7242,7 @@ void EnumOptions::SerializeWithCachedSizes(
int EnumOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 3) {
// optional bool allow_alias = 2;
if (has_allow_alias()) {
total_size += 1 + 1;
@@ -6761,7 +7264,7 @@ int EnumOptions::ByteSize() const {
total_size += _extensions_.ByteSize();
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -6796,7 +7299,9 @@ void EnumOptions::MergeFrom(const EnumOptions& from) {
}
}
_extensions_.MergeFrom(from._extensions_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void EnumOptions::CopyFrom(const ::google::protobuf::Message& from) {
@@ -6819,16 +7324,30 @@ 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_);
- std::swap(_cached_size_, other->_cached_size_);
- _extensions_.Swap(&other->_extensions_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ EnumOptions temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void EnumOptions::UnsafeArenaSwap(EnumOptions* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void EnumOptions::InternalSwap(EnumOptions* other) {
+ std::swap(allow_alias_, other->allow_alias_);
+ std::swap(deprecated_, other->deprecated_);
+ uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+ _extensions_.Swap(&other->_extensions_);
+}
::google::protobuf::Metadata EnumOptions::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -6847,16 +7366,26 @@ const int EnumValueOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumValueOptions::EnumValueOptions()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions)
}
+EnumValueOptions::EnumValueOptions(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _extensions_(arena), _internal_metadata_(arena),
+ uninterpreted_option_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValueOptions)
+}
+
void EnumValueOptions::InitAsDefaultInstance() {
}
EnumValueOptions::EnumValueOptions(const EnumValueOptions& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions)
@@ -6874,10 +7403,20 @@ EnumValueOptions::~EnumValueOptions() {
}
void EnumValueOptions::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void EnumValueOptions::ArenaDtor(void* object) {
+ EnumValueOptions* _this = reinterpret_cast< EnumValueOptions* >(object);
+ (void)_this;
+}
+void EnumValueOptions::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void EnumValueOptions::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -6895,8 +7434,8 @@ const EnumValueOptions& EnumValueOptions::default_instance() {
EnumValueOptions* EnumValueOptions::default_instance_ = NULL;
-EnumValueOptions* EnumValueOptions::New() const {
- return new EnumValueOptions;
+EnumValueOptions* EnumValueOptions::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<EnumValueOptions>(arena);
}
void EnumValueOptions::Clear() {
@@ -6904,7 +7443,9 @@ void EnumValueOptions::Clear() {
deprecated_ = false;
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool EnumValueOptions::MergePartialFromCodedStream(
@@ -6990,7 +7531,7 @@ void EnumValueOptions::SerializeWithCachedSizes(
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -7016,7 +7557,7 @@ void EnumValueOptions::SerializeWithCachedSizes(
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -7027,13 +7568,11 @@ void EnumValueOptions::SerializeWithCachedSizes(
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;
- }
-
+ // 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++) {
@@ -7044,7 +7583,7 @@ int EnumValueOptions::ByteSize() const {
total_size += _extensions_.ByteSize();
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -7076,7 +7615,9 @@ void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
}
}
_extensions_.MergeFrom(from._extensions_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void EnumValueOptions::CopyFrom(const ::google::protobuf::Message& from) {
@@ -7099,15 +7640,29 @@ bool EnumValueOptions::IsInitialized() const {
}
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_);
- std::swap(_cached_size_, other->_cached_size_);
- _extensions_.Swap(&other->_extensions_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ EnumValueOptions temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void EnumValueOptions::UnsafeArenaSwap(EnumValueOptions* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
+ std::swap(deprecated_, other->deprecated_);
+ uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+ _extensions_.Swap(&other->_extensions_);
+}
::google::protobuf::Metadata EnumValueOptions::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -7126,16 +7681,26 @@ const int ServiceOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
ServiceOptions::ServiceOptions()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions)
}
+ServiceOptions::ServiceOptions(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _extensions_(arena), _internal_metadata_(arena),
+ uninterpreted_option_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.ServiceOptions)
+}
+
void ServiceOptions::InitAsDefaultInstance() {
}
ServiceOptions::ServiceOptions(const ServiceOptions& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions)
@@ -7153,10 +7718,20 @@ ServiceOptions::~ServiceOptions() {
}
void ServiceOptions::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void ServiceOptions::ArenaDtor(void* object) {
+ ServiceOptions* _this = reinterpret_cast< ServiceOptions* >(object);
+ (void)_this;
+}
+void ServiceOptions::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void ServiceOptions::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -7174,8 +7749,8 @@ const ServiceOptions& ServiceOptions::default_instance() {
ServiceOptions* ServiceOptions::default_instance_ = NULL;
-ServiceOptions* ServiceOptions::New() const {
- return new ServiceOptions;
+ServiceOptions* ServiceOptions::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<ServiceOptions>(arena);
}
void ServiceOptions::Clear() {
@@ -7183,7 +7758,9 @@ void ServiceOptions::Clear() {
deprecated_ = false;
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool ServiceOptions::MergePartialFromCodedStream(
@@ -7269,7 +7846,7 @@ void ServiceOptions::SerializeWithCachedSizes(
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -7295,7 +7872,7 @@ void ServiceOptions::SerializeWithCachedSizes(
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -7306,13 +7883,11 @@ void ServiceOptions::SerializeWithCachedSizes(
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;
- }
-
+ // 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++) {
@@ -7323,7 +7898,7 @@ int ServiceOptions::ByteSize() const {
total_size += _extensions_.ByteSize();
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -7355,7 +7930,9 @@ void ServiceOptions::MergeFrom(const ServiceOptions& from) {
}
}
_extensions_.MergeFrom(from._extensions_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void ServiceOptions::CopyFrom(const ::google::protobuf::Message& from) {
@@ -7378,15 +7955,29 @@ bool ServiceOptions::IsInitialized() const {
}
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_);
- std::swap(_cached_size_, other->_cached_size_);
- _extensions_.Swap(&other->_extensions_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ ServiceOptions temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void ServiceOptions::UnsafeArenaSwap(ServiceOptions* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void ServiceOptions::InternalSwap(ServiceOptions* other) {
+ std::swap(deprecated_, other->deprecated_);
+ uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+ _extensions_.Swap(&other->_extensions_);
+}
::google::protobuf::Metadata ServiceOptions::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -7405,16 +7996,26 @@ const int MethodOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MethodOptions::MethodOptions()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MethodOptions)
}
+MethodOptions::MethodOptions(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _extensions_(arena), _internal_metadata_(arena),
+ uninterpreted_option_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.MethodOptions)
+}
+
void MethodOptions::InitAsDefaultInstance() {
}
MethodOptions::MethodOptions(const MethodOptions& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions)
@@ -7432,10 +8033,20 @@ MethodOptions::~MethodOptions() {
}
void MethodOptions::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void MethodOptions::ArenaDtor(void* object) {
+ MethodOptions* _this = reinterpret_cast< MethodOptions* >(object);
+ (void)_this;
+}
+void MethodOptions::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void MethodOptions::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -7453,8 +8064,8 @@ const MethodOptions& MethodOptions::default_instance() {
MethodOptions* MethodOptions::default_instance_ = NULL;
-MethodOptions* MethodOptions::New() const {
- return new MethodOptions;
+MethodOptions* MethodOptions::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<MethodOptions>(arena);
}
void MethodOptions::Clear() {
@@ -7462,7 +8073,9 @@ void MethodOptions::Clear() {
deprecated_ = false;
uninterpreted_option_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool MethodOptions::MergePartialFromCodedStream(
@@ -7548,7 +8161,7 @@ void MethodOptions::SerializeWithCachedSizes(
_extensions_.SerializeWithCachedSizes(
1000, 536870912, output);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -7574,7 +8187,7 @@ void MethodOptions::SerializeWithCachedSizes(
target = _extensions_.SerializeWithCachedSizesToArray(
1000, 536870912, target);
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -7585,13 +8198,11 @@ void MethodOptions::SerializeWithCachedSizes(
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;
- }
-
+ // 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++) {
@@ -7602,7 +8213,7 @@ int MethodOptions::ByteSize() const {
total_size += _extensions_.ByteSize();
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -7634,7 +8245,9 @@ void MethodOptions::MergeFrom(const MethodOptions& from) {
}
}
_extensions_.MergeFrom(from._extensions_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void MethodOptions::CopyFrom(const ::google::protobuf::Message& from) {
@@ -7657,15 +8270,29 @@ bool MethodOptions::IsInitialized() const {
}
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_);
- std::swap(_cached_size_, other->_cached_size_);
- _extensions_.Swap(&other->_extensions_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ MethodOptions temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void MethodOptions::UnsafeArenaSwap(MethodOptions* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void MethodOptions::InternalSwap(MethodOptions* other) {
+ std::swap(deprecated_, other->deprecated_);
+ uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+ _extensions_.Swap(&other->_extensions_);
+}
::google::protobuf::Metadata MethodOptions::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -7684,16 +8311,25 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
#endif // !_MSC_VER
UninterpretedOption_NamePart::UninterpretedOption_NamePart()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart)
}
+UninterpretedOption_NamePart::UninterpretedOption_NamePart(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption.NamePart)
+}
+
void UninterpretedOption_NamePart::InitAsDefaultInstance() {
}
UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart)
@@ -7702,7 +8338,7 @@ UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOp
void UninterpretedOption_NamePart::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ name_part_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
is_extension_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -7713,13 +8349,21 @@ UninterpretedOption_NamePart::~UninterpretedOption_NamePart() {
}
void UninterpretedOption_NamePart::SharedDtor() {
- if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_part_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_part_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void UninterpretedOption_NamePart::ArenaDtor(void* object) {
+ UninterpretedOption_NamePart* _this = reinterpret_cast< UninterpretedOption_NamePart* >(object);
+ (void)_this;
+}
+void UninterpretedOption_NamePart::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void UninterpretedOption_NamePart::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -7737,21 +8381,21 @@ const UninterpretedOption_NamePart& UninterpretedOption_NamePart::default_instan
UninterpretedOption_NamePart* UninterpretedOption_NamePart::default_instance_ = NULL;
-UninterpretedOption_NamePart* UninterpretedOption_NamePart::New() const {
- return new UninterpretedOption_NamePart;
+UninterpretedOption_NamePart* UninterpretedOption_NamePart::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<UninterpretedOption_NamePart>(arena);
}
void UninterpretedOption_NamePart::Clear() {
if (_has_bits_[0 / 32] & 3) {
if (has_name_part()) {
- if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_part_->clear();
- }
+ name_part_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
is_extension_ = false;
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
@@ -7772,7 +8416,7 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name_part().data(), this->name_part().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name_part");
+ "google.protobuf.UninterpretedOption.NamePart.name_part");
} else {
goto handle_unusual;
}
@@ -7825,7 +8469,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name_part().data(), this->name_part().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name_part");
+ "google.protobuf.UninterpretedOption.NamePart.name_part");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name_part(), output);
}
@@ -7835,7 +8479,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -7850,7 +8494,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name_part().data(), this->name_part().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name_part");
+ "google.protobuf.UninterpretedOption.NamePart.name_part");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name_part(), target);
@@ -7861,7 +8505,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -7869,24 +8513,39 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes(
return target;
}
+int UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const {
+ int total_size = 0;
+
+ if (has_name_part()) {
+ // required string name_part = 1;
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name_part());
+ }
+
+ if (has_is_extension()) {
+ // required bool is_extension = 2;
+ total_size += 1 + 1;
+ }
+
+ return total_size;
+}
int UninterpretedOption_NamePart::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) { // All required fields are present.
// required string name_part = 1;
- if (has_name_part()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::StringSize(
- this->name_part());
- }
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->name_part());
// required bool is_extension = 2;
- if (has_is_extension()) {
- total_size += 1 + 1;
- }
+ total_size += 1 + 1;
+ } else {
+ total_size += RequiredFieldsByteSizeFallback();
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -7919,7 +8578,9 @@ void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart&
set_is_extension(from.is_extension());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void UninterpretedOption_NamePart::CopyFrom(const ::google::protobuf::Message& from) {
@@ -7941,14 +8602,28 @@ bool UninterpretedOption_NamePart::IsInitialized() const {
}
void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) {
- if (other != this) {
- std::swap(name_part_, other->name_part_);
- std::swap(is_extension_, other->is_extension_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ UninterpretedOption_NamePart temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void UninterpretedOption_NamePart::UnsafeArenaSwap(UninterpretedOption_NamePart* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* other) {
+ name_part_.Swap(&other->name_part_);
+ std::swap(is_extension_, other->is_extension_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata UninterpretedOption_NamePart::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -7972,16 +8647,26 @@ const int UninterpretedOption::kAggregateValueFieldNumber;
#endif // !_MSC_VER
UninterpretedOption::UninterpretedOption()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption)
}
+UninterpretedOption::UninterpretedOption(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ name_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.UninterpretedOption)
+}
+
void UninterpretedOption::InitAsDefaultInstance() {
}
UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption)
@@ -7990,12 +8675,12 @@ UninterpretedOption::UninterpretedOption(const UninterpretedOption& from)
void UninterpretedOption::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ identifier_value_.UnsafeSetDefault(&::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::GetEmptyStringAlreadyInited());
- aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ aggregate_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -8005,19 +8690,23 @@ UninterpretedOption::~UninterpretedOption() {
}
void UninterpretedOption::SharedDtor() {
- if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete identifier_value_;
- }
- if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete string_value_;
- }
- if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete aggregate_value_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ identifier_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ string_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ aggregate_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void UninterpretedOption::ArenaDtor(void* object) {
+ UninterpretedOption* _this = reinterpret_cast< UninterpretedOption* >(object);
+ (void)_this;
+}
+void UninterpretedOption::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void UninterpretedOption::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -8035,8 +8724,8 @@ const UninterpretedOption& UninterpretedOption::default_instance() {
UninterpretedOption* UninterpretedOption::default_instance_ = NULL;
-UninterpretedOption* UninterpretedOption::New() const {
- return new UninterpretedOption;
+UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<UninterpretedOption>(arena);
}
void UninterpretedOption::Clear() {
@@ -8053,19 +8742,13 @@ void UninterpretedOption::Clear() {
if (_has_bits_[0 / 32] & 126) {
ZR_(positive_int_value_, double_value_);
if (has_identifier_value()) {
- if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- identifier_value_->clear();
- }
+ identifier_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_string_value()) {
- if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- string_value_->clear();
- }
+ string_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_aggregate_value()) {
- if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- aggregate_value_->clear();
- }
+ aggregate_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
}
@@ -8074,7 +8757,9 @@ void UninterpretedOption::Clear() {
name_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool UninterpretedOption::MergePartialFromCodedStream(
@@ -8110,7 +8795,7 @@ bool UninterpretedOption::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->identifier_value().data(), this->identifier_value().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "identifier_value");
+ "google.protobuf.UninterpretedOption.identifier_value");
} else {
goto handle_unusual;
}
@@ -8185,7 +8870,7 @@ bool UninterpretedOption::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->aggregate_value().data(), this->aggregate_value().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "aggregate_value");
+ "google.protobuf.UninterpretedOption.aggregate_value");
} else {
goto handle_unusual;
}
@@ -8229,7 +8914,7 @@ void UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->identifier_value().data(), this->identifier_value().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "identifier_value");
+ "google.protobuf.UninterpretedOption.identifier_value");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
3, this->identifier_value(), output);
}
@@ -8260,12 +8945,12 @@ void UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->aggregate_value().data(), this->aggregate_value().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "aggregate_value");
+ "google.protobuf.UninterpretedOption.aggregate_value");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
8, this->aggregate_value(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -8287,7 +8972,7 @@ void UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->identifier_value().data(), this->identifier_value().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "identifier_value");
+ "google.protobuf.UninterpretedOption.identifier_value");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
3, this->identifier_value(), target);
@@ -8320,13 +9005,13 @@ void UninterpretedOption::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->aggregate_value().data(), this->aggregate_value().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "aggregate_value");
+ "google.protobuf.UninterpretedOption.aggregate_value");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
8, this->aggregate_value(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -8337,7 +9022,7 @@ void UninterpretedOption::SerializeWithCachedSizes(
int UninterpretedOption::ByteSize() const {
int total_size = 0;
- if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+ if (_has_bits_[1 / 32] & 126) {
// optional string identifier_value = 3;
if (has_identifier_value()) {
total_size += 1 +
@@ -8387,7 +9072,7 @@ int UninterpretedOption::ByteSize() const {
this->name(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -8433,7 +9118,9 @@ void UninterpretedOption::MergeFrom(const UninterpretedOption& from) {
set_aggregate_value(from.aggregate_value());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void UninterpretedOption::CopyFrom(const ::google::protobuf::Message& from) {
@@ -8455,18 +9142,32 @@ bool UninterpretedOption::IsInitialized() const {
}
void UninterpretedOption::Swap(UninterpretedOption* other) {
- if (other != this) {
- name_.Swap(&other->name_);
- std::swap(identifier_value_, other->identifier_value_);
- std::swap(positive_int_value_, other->positive_int_value_);
- std::swap(negative_int_value_, other->negative_int_value_);
- std::swap(double_value_, other->double_value_);
- std::swap(string_value_, other->string_value_);
- std::swap(aggregate_value_, other->aggregate_value_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- }
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ UninterpretedOption temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
+ }
+}
+void UninterpretedOption::UnsafeArenaSwap(UninterpretedOption* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
+ name_.UnsafeArenaSwap(&other->name_);
+ identifier_value_.Swap(&other->identifier_value_);
+ std::swap(positive_int_value_, other->positive_int_value_);
+ std::swap(negative_int_value_, other->negative_int_value_);
+ std::swap(double_value_, other->double_value_);
+ string_value_.Swap(&other->string_value_);
+ aggregate_value_.Swap(&other->aggregate_value_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata UninterpretedOption::GetMetadata() const {
@@ -8488,16 +9189,27 @@ const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo_Location::SourceCodeInfo_Location()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location)
}
+SourceCodeInfo_Location::SourceCodeInfo_Location(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ path_(arena),
+ span_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo.Location)
+}
+
void SourceCodeInfo_Location::InitAsDefaultInstance() {
}
SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location)
@@ -8506,8 +9218,8 @@ SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location&
void SourceCodeInfo_Location::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ leading_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ trailing_comments_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -8517,16 +9229,22 @@ SourceCodeInfo_Location::~SourceCodeInfo_Location() {
}
void SourceCodeInfo_Location::SharedDtor() {
- if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete leading_comments_;
- }
- if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete trailing_comments_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ leading_comments_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ trailing_comments_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void SourceCodeInfo_Location::ArenaDtor(void* object) {
+ SourceCodeInfo_Location* _this = reinterpret_cast< SourceCodeInfo_Location* >(object);
+ (void)_this;
+}
+void SourceCodeInfo_Location::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void SourceCodeInfo_Location::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -8544,27 +9262,25 @@ const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() {
SourceCodeInfo_Location* SourceCodeInfo_Location::default_instance_ = NULL;
-SourceCodeInfo_Location* SourceCodeInfo_Location::New() const {
- return new SourceCodeInfo_Location;
+SourceCodeInfo_Location* SourceCodeInfo_Location::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<SourceCodeInfo_Location>(arena);
}
void SourceCodeInfo_Location::Clear() {
if (_has_bits_[0 / 32] & 12) {
if (has_leading_comments()) {
- if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- leading_comments_->clear();
- }
+ leading_comments_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_trailing_comments()) {
- if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- trailing_comments_->clear();
- }
+ trailing_comments_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
}
path_.Clear();
span_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool SourceCodeInfo_Location::MergePartialFromCodedStream(
@@ -8621,7 +9337,7 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->leading_comments().data(), this->leading_comments().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "leading_comments");
+ "google.protobuf.SourceCodeInfo.Location.leading_comments");
} else {
goto handle_unusual;
}
@@ -8638,7 +9354,7 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->trailing_comments().data(), this->trailing_comments().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "trailing_comments");
+ "google.protobuf.SourceCodeInfo.Location.trailing_comments");
} else {
goto handle_unusual;
}
@@ -8696,7 +9412,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->leading_comments().data(), this->leading_comments().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "leading_comments");
+ "google.protobuf.SourceCodeInfo.Location.leading_comments");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
3, this->leading_comments(), output);
}
@@ -8706,12 +9422,12 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->trailing_comments().data(), this->trailing_comments().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "trailing_comments");
+ "google.protobuf.SourceCodeInfo.Location.trailing_comments");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
4, this->trailing_comments(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -8754,7 +9470,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->leading_comments().data(), this->leading_comments().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "leading_comments");
+ "google.protobuf.SourceCodeInfo.Location.leading_comments");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
3, this->leading_comments(), target);
@@ -8765,13 +9481,13 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->trailing_comments().data(), this->trailing_comments().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "trailing_comments");
+ "google.protobuf.SourceCodeInfo.Location.trailing_comments");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
4, this->trailing_comments(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -8782,7 +9498,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
int SourceCodeInfo_Location::ByteSize() const {
int total_size = 0;
- if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) {
+ if (_has_bits_[2 / 32] & 12) {
// optional string leading_comments = 3;
if (has_leading_comments()) {
total_size += 1 +
@@ -8832,7 +9548,7 @@ int SourceCodeInfo_Location::ByteSize() const {
total_size += data_size;
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -8867,7 +9583,9 @@ void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
set_trailing_comments(from.trailing_comments());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) {
@@ -8888,16 +9606,30 @@ bool SourceCodeInfo_Location::IsInitialized() const {
}
void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) {
- if (other != this) {
- path_.Swap(&other->path_);
- span_.Swap(&other->span_);
- std::swap(leading_comments_, other->leading_comments_);
- std::swap(trailing_comments_, other->trailing_comments_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ SourceCodeInfo_Location temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void SourceCodeInfo_Location::UnsafeArenaSwap(SourceCodeInfo_Location* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) {
+ path_.UnsafeArenaSwap(&other->path_);
+ span_.UnsafeArenaSwap(&other->span_);
+ leading_comments_.Swap(&other->leading_comments_);
+ trailing_comments_.Swap(&other->trailing_comments_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -8915,16 +9647,26 @@ const int SourceCodeInfo::kLocationFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo::SourceCodeInfo()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo)
}
+SourceCodeInfo::SourceCodeInfo(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ location_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.SourceCodeInfo)
+}
+
void SourceCodeInfo::InitAsDefaultInstance() {
}
SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo)
@@ -8941,10 +9683,20 @@ SourceCodeInfo::~SourceCodeInfo() {
}
void SourceCodeInfo::SharedDtor() {
+ if (GetArenaNoVirtual() != NULL) {
+ return;
+ }
+
if (this != default_instance_) {
}
}
+void SourceCodeInfo::ArenaDtor(void* object) {
+ SourceCodeInfo* _this = reinterpret_cast< SourceCodeInfo* >(object);
+ (void)_this;
+}
+void SourceCodeInfo::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void SourceCodeInfo::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -8962,14 +9714,16 @@ const SourceCodeInfo& SourceCodeInfo::default_instance() {
SourceCodeInfo* SourceCodeInfo::default_instance_ = NULL;
-SourceCodeInfo* SourceCodeInfo::New() const {
- return new SourceCodeInfo;
+SourceCodeInfo* SourceCodeInfo::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<SourceCodeInfo>(arena);
}
void SourceCodeInfo::Clear() {
location_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool SourceCodeInfo::MergePartialFromCodedStream(
@@ -9027,7 +9781,7 @@ void SourceCodeInfo::SerializeWithCachedSizes(
1, this->location(i), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -9044,7 +9798,7 @@ void SourceCodeInfo::SerializeWithCachedSizes(
1, this->location(i), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -9063,7 +9817,7 @@ int SourceCodeInfo::ByteSize() const {
this->location(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -9089,7 +9843,9 @@ void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
GOOGLE_CHECK_NE(&from, this);
location_.MergeFrom(from.location_);
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) {
@@ -9110,12 +9866,26 @@ bool SourceCodeInfo::IsInitialized() const {
}
void SourceCodeInfo::Swap(SourceCodeInfo* other) {
- if (other != this) {
- location_.Swap(&other->location_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
- }
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ SourceCodeInfo temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
+ }
+}
+void SourceCodeInfo::UnsafeArenaSwap(SourceCodeInfo* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
+ location_.UnsafeArenaSwap(&other->location_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
}
::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const {
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index dd721be9..295b53f3 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -5,6 +5,7 @@
#define PROTOBUF_google_2fprotobuf_2fdescriptor_2eproto__INCLUDED
#include <string>
+#include <stdint.h>
#include <google/protobuf/stubs/common.h>
@@ -19,7 +20,10 @@
#error regenerate this file with a newer version of protoc.
#endif
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
@@ -167,21 +171,28 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorSet& default_instance();
+ void UnsafeArenaSwap(FileDescriptorSet* other);
void Swap(FileDescriptorSet* other);
// implements Message ----------------------------------------------
- FileDescriptorSet* New() const;
+ inline FileDescriptorSet* New() const { return New(NULL); }
+
+ FileDescriptorSet* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const FileDescriptorSet& from);
@@ -200,7 +211,21 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(FileDescriptorSet* other);
+ protected:
+ explicit FileDescriptorSet(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -222,8 +247,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
private:
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_;
@@ -249,21 +276,28 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const FileDescriptorProto& default_instance();
+ void UnsafeArenaSwap(FileDescriptorProto* other);
void Swap(FileDescriptorProto* other);
// implements Message ----------------------------------------------
- FileDescriptorProto* New() const;
+ inline FileDescriptorProto* New() const { return New(NULL); }
+
+ FileDescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const FileDescriptorProto& from);
@@ -282,7 +316,21 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(FileDescriptorProto* other);
+ protected:
+ explicit FileDescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -300,6 +348,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// optional string package = 2;
inline bool has_package() const;
@@ -312,6 +363,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline ::std::string* mutable_package();
inline ::std::string* release_package();
inline void set_allocated_package(::std::string* package);
+ inline ::std::string* unsafe_arena_release_package();
+ inline void unsafe_arena_set_allocated_package(
+ ::std::string* package);
// repeated string dependency = 3;
inline int dependency_size() const;
@@ -409,6 +463,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline ::google::protobuf::FileOptions* mutable_options();
inline ::google::protobuf::FileOptions* release_options();
inline void set_allocated_options(::google::protobuf::FileOptions* options);
+ inline ::google::protobuf::FileOptions* unsafe_arena_release_options();
+ inline void unsafe_arena_set_allocated_options(
+ ::google::protobuf::FileOptions* options);
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
inline bool has_source_code_info() const;
@@ -418,6 +475,24 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
+ inline ::google::protobuf::SourceCodeInfo* unsafe_arena_release_source_code_info();
+ inline void unsafe_arena_set_allocated_source_code_info(
+ ::google::protobuf::SourceCodeInfo* source_code_info);
+
+ // optional string syntax = 12;
+ inline bool has_syntax() const;
+ inline void clear_syntax();
+ static const int kSyntaxFieldNumber = 12;
+ inline const ::std::string& syntax() const;
+ inline void set_syntax(const ::std::string& value);
+ inline void set_syntax(const char* value);
+ inline void set_syntax(const char* value, size_t size);
+ inline ::std::string* mutable_syntax();
+ inline ::std::string* release_syntax();
+ inline void set_allocated_syntax(::std::string* syntax);
+ inline ::std::string* unsafe_arena_release_syntax();
+ inline void unsafe_arena_set_allocated_syntax(
+ ::std::string* syntax);
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
private:
@@ -429,13 +504,17 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
inline void clear_has_options();
inline void set_has_source_code_info();
inline void clear_has_source_code_info();
+ inline void set_has_syntax();
+ inline void clear_has_syntax();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
- ::std::string* package_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::internal::ArenaStringPtr package_;
::google::protobuf::RepeatedPtrField< ::std::string> dependency_;
::google::protobuf::RepeatedField< ::google::protobuf::int32 > public_dependency_;
::google::protobuf::RepeatedField< ::google::protobuf::int32 > weak_dependency_;
@@ -445,6 +524,7 @@ 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_;
+ ::google::protobuf::internal::ArenaStringPtr syntax_;
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();
@@ -467,21 +547,28 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto_ExtensionRange& default_instance();
+ void UnsafeArenaSwap(DescriptorProto_ExtensionRange* other);
void Swap(DescriptorProto_ExtensionRange* other);
// implements Message ----------------------------------------------
- DescriptorProto_ExtensionRange* New() const;
+ inline DescriptorProto_ExtensionRange* New() const { return New(NULL); }
+
+ DescriptorProto_ExtensionRange* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const DescriptorProto_ExtensionRange& from);
@@ -500,7 +587,21 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(DescriptorProto_ExtensionRange* other);
+ protected:
+ explicit DescriptorProto_ExtensionRange(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -528,8 +629,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
inline void set_has_end();
inline void clear_has_end();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::int32 start_;
@@ -556,21 +659,28 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const DescriptorProto& default_instance();
+ void UnsafeArenaSwap(DescriptorProto* other);
void Swap(DescriptorProto* other);
// implements Message ----------------------------------------------
- DescriptorProto* New() const;
+ inline DescriptorProto* New() const { return New(NULL); }
+
+ DescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const DescriptorProto& from);
@@ -589,7 +699,21 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(DescriptorProto* other);
+ protected:
+ explicit DescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -609,6 +733,9 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// repeated .google.protobuf.FieldDescriptorProto field = 2;
inline int field_size() const;
@@ -690,6 +817,9 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline ::google::protobuf::MessageOptions* mutable_options();
inline ::google::protobuf::MessageOptions* release_options();
inline void set_allocated_options(::google::protobuf::MessageOptions* options);
+ inline ::google::protobuf::MessageOptions* unsafe_arena_release_options();
+ inline void unsafe_arena_set_allocated_options(
+ ::google::protobuf::MessageOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
private:
@@ -698,11 +828,13 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
inline void set_has_options();
inline void clear_has_options();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_;
@@ -732,21 +864,28 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const FieldDescriptorProto& default_instance();
+ void UnsafeArenaSwap(FieldDescriptorProto* other);
void Swap(FieldDescriptorProto* other);
// implements Message ----------------------------------------------
- FieldDescriptorProto* New() const;
+ inline FieldDescriptorProto* New() const { return New(NULL); }
+
+ FieldDescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const FieldDescriptorProto& from);
@@ -765,7 +904,21 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(FieldDescriptorProto* other);
+ protected:
+ explicit FieldDescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -848,6 +1001,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// optional int32 number = 3;
inline bool has_number() const;
@@ -881,6 +1037,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline ::std::string* mutable_type_name();
inline ::std::string* release_type_name();
inline void set_allocated_type_name(::std::string* type_name);
+ inline ::std::string* unsafe_arena_release_type_name();
+ inline void unsafe_arena_set_allocated_type_name(
+ ::std::string* type_name);
// optional string extendee = 2;
inline bool has_extendee() const;
@@ -893,6 +1052,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline ::std::string* mutable_extendee();
inline ::std::string* release_extendee();
inline void set_allocated_extendee(::std::string* extendee);
+ inline ::std::string* unsafe_arena_release_extendee();
+ inline void unsafe_arena_set_allocated_extendee(
+ ::std::string* extendee);
// optional string default_value = 7;
inline bool has_default_value() const;
@@ -905,6 +1067,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline ::std::string* mutable_default_value();
inline ::std::string* release_default_value();
inline void set_allocated_default_value(::std::string* default_value);
+ inline ::std::string* unsafe_arena_release_default_value();
+ inline void unsafe_arena_set_allocated_default_value(
+ ::std::string* default_value);
// optional int32 oneof_index = 9;
inline bool has_oneof_index() const;
@@ -921,6 +1086,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline ::google::protobuf::FieldOptions* mutable_options();
inline ::google::protobuf::FieldOptions* release_options();
inline void set_allocated_options(::google::protobuf::FieldOptions* options);
+ inline ::google::protobuf::FieldOptions* unsafe_arena_release_options();
+ inline void unsafe_arena_set_allocated_options(
+ ::google::protobuf::FieldOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
private:
@@ -943,18 +1111,20 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
inline void set_has_options();
inline void clear_has_options();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::int32 number_;
int label_;
- ::std::string* type_name_;
- ::std::string* extendee_;
+ ::google::protobuf::internal::ArenaStringPtr type_name_;
+ ::google::protobuf::internal::ArenaStringPtr extendee_;
int type_;
::google::protobuf::int32 oneof_index_;
- ::std::string* default_value_;
+ ::google::protobuf::internal::ArenaStringPtr default_value_;
::google::protobuf::FieldOptions* options_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -978,21 +1148,28 @@ class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Messa
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const OneofDescriptorProto& default_instance();
+ void UnsafeArenaSwap(OneofDescriptorProto* other);
void Swap(OneofDescriptorProto* other);
// implements Message ----------------------------------------------
- OneofDescriptorProto* New() const;
+ inline OneofDescriptorProto* New() const { return New(NULL); }
+
+ OneofDescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const OneofDescriptorProto& from);
@@ -1011,7 +1188,21 @@ class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Messa
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(OneofDescriptorProto* other);
+ protected:
+ explicit OneofDescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1029,17 +1220,22 @@ class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Messa
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_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::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
+ ::google::protobuf::internal::ArenaStringPtr 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();
@@ -1062,21 +1258,28 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const EnumDescriptorProto& default_instance();
+ void UnsafeArenaSwap(EnumDescriptorProto* other);
void Swap(EnumDescriptorProto* other);
// implements Message ----------------------------------------------
- EnumDescriptorProto* New() const;
+ inline EnumDescriptorProto* New() const { return New(NULL); }
+
+ EnumDescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const EnumDescriptorProto& from);
@@ -1095,7 +1298,21 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(EnumDescriptorProto* other);
+ protected:
+ explicit EnumDescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1113,6 +1330,9 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
inline int value_size() const;
@@ -1134,6 +1354,9 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline ::google::protobuf::EnumOptions* mutable_options();
inline ::google::protobuf::EnumOptions* release_options();
inline void set_allocated_options(::google::protobuf::EnumOptions* options);
+ inline ::google::protobuf::EnumOptions* unsafe_arena_release_options();
+ inline void unsafe_arena_set_allocated_options(
+ ::google::protobuf::EnumOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
private:
@@ -1142,11 +1365,13 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
inline void set_has_options();
inline void clear_has_options();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_;
::google::protobuf::EnumOptions* options_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -1171,21 +1396,28 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueDescriptorProto& default_instance();
+ void UnsafeArenaSwap(EnumValueDescriptorProto* other);
void Swap(EnumValueDescriptorProto* other);
// implements Message ----------------------------------------------
- EnumValueDescriptorProto* New() const;
+ inline EnumValueDescriptorProto* New() const { return New(NULL); }
+
+ EnumValueDescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const EnumValueDescriptorProto& from);
@@ -1204,7 +1436,21 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(EnumValueDescriptorProto* other);
+ protected:
+ explicit EnumValueDescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1222,6 +1468,9 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// optional int32 number = 2;
inline bool has_number() const;
@@ -1238,6 +1487,9 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
inline ::google::protobuf::EnumValueOptions* mutable_options();
inline ::google::protobuf::EnumValueOptions* release_options();
inline void set_allocated_options(::google::protobuf::EnumValueOptions* options);
+ inline ::google::protobuf::EnumValueOptions* unsafe_arena_release_options();
+ inline void unsafe_arena_set_allocated_options(
+ ::google::protobuf::EnumValueOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
private:
@@ -1248,11 +1500,13 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
inline void set_has_options();
inline void clear_has_options();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::EnumValueOptions* options_;
::google::protobuf::int32 number_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -1277,21 +1531,28 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceDescriptorProto& default_instance();
+ void UnsafeArenaSwap(ServiceDescriptorProto* other);
void Swap(ServiceDescriptorProto* other);
// implements Message ----------------------------------------------
- ServiceDescriptorProto* New() const;
+ inline ServiceDescriptorProto* New() const { return New(NULL); }
+
+ ServiceDescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const ServiceDescriptorProto& from);
@@ -1310,7 +1571,21 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(ServiceDescriptorProto* other);
+ protected:
+ explicit ServiceDescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1328,6 +1603,9 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// repeated .google.protobuf.MethodDescriptorProto method = 2;
inline int method_size() const;
@@ -1349,6 +1627,9 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline ::google::protobuf::ServiceOptions* mutable_options();
inline ::google::protobuf::ServiceOptions* release_options();
inline void set_allocated_options(::google::protobuf::ServiceOptions* options);
+ inline ::google::protobuf::ServiceOptions* unsafe_arena_release_options();
+ inline void unsafe_arena_set_allocated_options(
+ ::google::protobuf::ServiceOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
private:
@@ -1357,11 +1638,13 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
inline void set_has_options();
inline void clear_has_options();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_;
::google::protobuf::ServiceOptions* options_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -1386,21 +1669,28 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const MethodDescriptorProto& default_instance();
+ void UnsafeArenaSwap(MethodDescriptorProto* other);
void Swap(MethodDescriptorProto* other);
// implements Message ----------------------------------------------
- MethodDescriptorProto* New() const;
+ inline MethodDescriptorProto* New() const { return New(NULL); }
+
+ MethodDescriptorProto* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const MethodDescriptorProto& from);
@@ -1419,7 +1709,21 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(MethodDescriptorProto* other);
+ protected:
+ explicit MethodDescriptorProto(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1437,6 +1741,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// optional string input_type = 2;
inline bool has_input_type() const;
@@ -1449,6 +1756,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline ::std::string* mutable_input_type();
inline ::std::string* release_input_type();
inline void set_allocated_input_type(::std::string* input_type);
+ inline ::std::string* unsafe_arena_release_input_type();
+ inline void unsafe_arena_set_allocated_input_type(
+ ::std::string* input_type);
// optional string output_type = 3;
inline bool has_output_type() const;
@@ -1461,6 +1771,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline ::std::string* mutable_output_type();
inline ::std::string* release_output_type();
inline void set_allocated_output_type(::std::string* output_type);
+ inline ::std::string* unsafe_arena_release_output_type();
+ inline void unsafe_arena_set_allocated_output_type(
+ ::std::string* output_type);
// optional .google.protobuf.MethodOptions options = 4;
inline bool has_options() const;
@@ -1470,6 +1783,9 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline ::google::protobuf::MethodOptions* mutable_options();
inline ::google::protobuf::MethodOptions* release_options();
inline void set_allocated_options(::google::protobuf::MethodOptions* options);
+ inline ::google::protobuf::MethodOptions* unsafe_arena_release_options();
+ inline void unsafe_arena_set_allocated_options(
+ ::google::protobuf::MethodOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
private:
@@ -1482,13 +1798,15 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
inline void set_has_options();
inline void clear_has_options();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
- ::std::string* input_type_;
- ::std::string* output_type_;
+ ::google::protobuf::internal::ArenaStringPtr name_;
+ ::google::protobuf::internal::ArenaStringPtr input_type_;
+ ::google::protobuf::internal::ArenaStringPtr output_type_;
::google::protobuf::MethodOptions* options_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -1512,21 +1830,28 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const FileOptions& default_instance();
+ void UnsafeArenaSwap(FileOptions* other);
void Swap(FileOptions* other);
// implements Message ----------------------------------------------
- FileOptions* New() const;
+ inline FileOptions* New() const { return New(NULL); }
+
+ FileOptions* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const FileOptions& from);
@@ -1545,7 +1870,21 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(FileOptions* other);
+ protected:
+ explicit FileOptions(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1588,6 +1927,9 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline ::std::string* mutable_java_package();
inline ::std::string* release_java_package();
inline void set_allocated_java_package(::std::string* java_package);
+ inline ::std::string* unsafe_arena_release_java_package();
+ inline void unsafe_arena_set_allocated_java_package(
+ ::std::string* java_package);
// optional string java_outer_classname = 8;
inline bool has_java_outer_classname() const;
@@ -1600,6 +1942,9 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline ::std::string* mutable_java_outer_classname();
inline ::std::string* release_java_outer_classname();
inline void set_allocated_java_outer_classname(::std::string* java_outer_classname);
+ inline ::std::string* unsafe_arena_release_java_outer_classname();
+ inline void unsafe_arena_set_allocated_java_outer_classname(
+ ::std::string* java_outer_classname);
// optional bool java_multiple_files = 10 [default = false];
inline bool has_java_multiple_files() const;
@@ -1640,6 +1985,9 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline ::std::string* mutable_go_package();
inline ::std::string* release_go_package();
inline void set_allocated_go_package(::std::string* go_package);
+ inline ::std::string* unsafe_arena_release_go_package();
+ inline void unsafe_arena_set_allocated_go_package(
+ ::std::string* go_package);
// optional bool cc_generic_services = 16 [default = false];
inline bool has_cc_generic_services() const;
@@ -1709,18 +2057,20 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
::google::protobuf::internal::ExtensionSet _extensions_;
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* java_package_;
- ::std::string* java_outer_classname_;
+ ::google::protobuf::internal::ArenaStringPtr java_package_;
+ ::google::protobuf::internal::ArenaStringPtr java_outer_classname_;
bool java_multiple_files_;
bool java_generate_equals_and_hash_;
bool java_string_check_utf8_;
bool cc_generic_services_;
int optimize_for_;
- ::std::string* go_package_;
+ ::google::protobuf::internal::ArenaStringPtr go_package_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
bool java_generic_services_;
bool py_generic_services_;
@@ -1747,21 +2097,28 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const MessageOptions& default_instance();
+ void UnsafeArenaSwap(MessageOptions* other);
void Swap(MessageOptions* other);
// implements Message ----------------------------------------------
- MessageOptions* New() const;
+ inline MessageOptions* New() const { return New(NULL); }
+
+ MessageOptions* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const MessageOptions& from);
@@ -1780,7 +2137,21 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(MessageOptions* other);
+ protected:
+ explicit MessageOptions(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1808,6 +2179,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
inline bool deprecated() const;
inline void set_deprecated(bool value);
+ // optional bool map_entry = 7;
+ inline bool has_map_entry() const;
+ inline void clear_map_entry();
+ static const int kMapEntryFieldNumber = 7;
+ inline bool map_entry() const;
+ inline void set_map_entry(bool value);
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int uninterpreted_option_size() const;
inline void clear_uninterpreted_option();
@@ -1829,17 +2207,22 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
inline void clear_has_no_standard_descriptor_accessor();
inline void set_has_deprecated();
inline void clear_has_deprecated();
+ inline void set_has_map_entry();
+ inline void clear_has_map_entry();
::google::protobuf::internal::ExtensionSet _extensions_;
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::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_;
bool deprecated_;
+ bool map_entry_;
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();
@@ -1862,21 +2245,28 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const FieldOptions& default_instance();
+ void UnsafeArenaSwap(FieldOptions* other);
void Swap(FieldOptions* other);
// implements Message ----------------------------------------------
- FieldOptions* New() const;
+ inline FieldOptions* New() const { return New(NULL); }
+
+ FieldOptions* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const FieldOptions& from);
@@ -1895,7 +2285,21 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(FieldOptions* other);
+ protected:
+ explicit FieldOptions(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -1955,18 +2359,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline bool deprecated() const;
inline void set_deprecated(bool value);
- // optional string experimental_map_key = 9;
- inline bool has_experimental_map_key() const;
- inline void clear_experimental_map_key();
- static const int kExperimentalMapKeyFieldNumber = 9;
- inline const ::std::string& experimental_map_key() const;
- inline void set_experimental_map_key(const ::std::string& value);
- inline void set_experimental_map_key(const char* value);
- inline void set_experimental_map_key(const char* value, size_t size);
- inline ::std::string* mutable_experimental_map_key();
- inline ::std::string* release_experimental_map_key();
- inline void set_allocated_experimental_map_key(::std::string* experimental_map_key);
-
// optional bool weak = 10 [default = false];
inline bool has_weak() const;
inline void clear_weak();
@@ -1997,15 +2389,15 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline void clear_has_lazy();
inline void set_has_deprecated();
inline void clear_has_deprecated();
- inline void set_has_experimental_map_key();
- inline void clear_has_experimental_map_key();
inline void set_has_weak();
inline void clear_has_weak();
::google::protobuf::internal::ExtensionSet _extensions_;
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
int ctype_;
@@ -2013,7 +2405,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
bool lazy_;
bool deprecated_;
bool weak_;
- ::std::string* experimental_map_key_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -2037,21 +2428,28 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const EnumOptions& default_instance();
+ void UnsafeArenaSwap(EnumOptions* other);
void Swap(EnumOptions* other);
// implements Message ----------------------------------------------
- EnumOptions* New() const;
+ inline EnumOptions* New() const { return New(NULL); }
+
+ EnumOptions* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const EnumOptions& from);
@@ -2070,7 +2468,21 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(EnumOptions* other);
+ protected:
+ explicit EnumOptions(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2113,8 +2525,10 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
::google::protobuf::internal::ExtensionSet _extensions_;
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
@@ -2142,21 +2556,28 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const EnumValueOptions& default_instance();
+ void UnsafeArenaSwap(EnumValueOptions* other);
void Swap(EnumValueOptions* other);
// implements Message ----------------------------------------------
- EnumValueOptions* New() const;
+ inline EnumValueOptions* New() const { return New(NULL); }
+
+ EnumValueOptions* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const EnumValueOptions& from);
@@ -2175,7 +2596,21 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(EnumValueOptions* other);
+ protected:
+ explicit EnumValueOptions(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2209,8 +2644,10 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
::google::protobuf::internal::ExtensionSet _extensions_;
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
@@ -2237,21 +2674,28 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const ServiceOptions& default_instance();
+ void UnsafeArenaSwap(ServiceOptions* other);
void Swap(ServiceOptions* other);
// implements Message ----------------------------------------------
- ServiceOptions* New() const;
+ inline ServiceOptions* New() const { return New(NULL); }
+
+ ServiceOptions* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const ServiceOptions& from);
@@ -2270,7 +2714,21 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(ServiceOptions* other);
+ protected:
+ explicit ServiceOptions(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2304,8 +2762,10 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
::google::protobuf::internal::ExtensionSet _extensions_;
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
@@ -2332,21 +2792,28 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const MethodOptions& default_instance();
+ void UnsafeArenaSwap(MethodOptions* other);
void Swap(MethodOptions* other);
// implements Message ----------------------------------------------
- MethodOptions* New() const;
+ inline MethodOptions* New() const { return New(NULL); }
+
+ MethodOptions* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const MethodOptions& from);
@@ -2365,7 +2832,21 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(MethodOptions* other);
+ protected:
+ explicit MethodOptions(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2399,8 +2880,10 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
::google::protobuf::internal::ExtensionSet _extensions_;
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
@@ -2427,21 +2910,28 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption_NamePart& default_instance();
+ void UnsafeArenaSwap(UninterpretedOption_NamePart* other);
void Swap(UninterpretedOption_NamePart* other);
// implements Message ----------------------------------------------
- UninterpretedOption_NamePart* New() const;
+ inline UninterpretedOption_NamePart* New() const { return New(NULL); }
+
+ UninterpretedOption_NamePart* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const UninterpretedOption_NamePart& from);
@@ -2460,7 +2950,21 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(UninterpretedOption_NamePart* other);
+ protected:
+ explicit UninterpretedOption_NamePart(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2478,6 +2982,9 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
inline ::std::string* mutable_name_part();
inline ::std::string* release_name_part();
inline void set_allocated_name_part(::std::string* name_part);
+ inline ::std::string* unsafe_arena_release_name_part();
+ inline void unsafe_arena_set_allocated_name_part(
+ ::std::string* name_part);
// required bool is_extension = 2;
inline bool has_is_extension() const;
@@ -2493,11 +3000,16 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
inline void set_has_is_extension();
inline void clear_has_is_extension();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
+ // helper for ByteSize()
+ int RequiredFieldsByteSizeFallback() const;
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_part_;
+ ::google::protobuf::internal::ArenaStringPtr name_part_;
bool is_extension_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
@@ -2521,21 +3033,28 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const UninterpretedOption& default_instance();
+ void UnsafeArenaSwap(UninterpretedOption* other);
void Swap(UninterpretedOption* other);
// implements Message ----------------------------------------------
- UninterpretedOption* New() const;
+ inline UninterpretedOption* New() const { return New(NULL); }
+
+ UninterpretedOption* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const UninterpretedOption& from);
@@ -2554,7 +3073,21 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(UninterpretedOption* other);
+ protected:
+ explicit UninterpretedOption(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2586,6 +3119,9 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline ::std::string* mutable_identifier_value();
inline ::std::string* release_identifier_value();
inline void set_allocated_identifier_value(::std::string* identifier_value);
+ inline ::std::string* unsafe_arena_release_identifier_value();
+ inline void unsafe_arena_set_allocated_identifier_value(
+ ::std::string* identifier_value);
// optional uint64 positive_int_value = 4;
inline bool has_positive_int_value() const;
@@ -2619,6 +3155,9 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline ::std::string* mutable_string_value();
inline ::std::string* release_string_value();
inline void set_allocated_string_value(::std::string* string_value);
+ inline ::std::string* unsafe_arena_release_string_value();
+ inline void unsafe_arena_set_allocated_string_value(
+ ::std::string* string_value);
// optional string aggregate_value = 8;
inline bool has_aggregate_value() const;
@@ -2631,6 +3170,9 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline ::std::string* mutable_aggregate_value();
inline ::std::string* release_aggregate_value();
inline void set_allocated_aggregate_value(::std::string* aggregate_value);
+ inline ::std::string* unsafe_arena_release_aggregate_value();
+ inline void unsafe_arena_set_allocated_aggregate_value(
+ ::std::string* aggregate_value);
// @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
private:
@@ -2647,17 +3189,19 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
inline void set_has_aggregate_value();
inline void clear_has_aggregate_value();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_;
- ::std::string* identifier_value_;
+ ::google::protobuf::internal::ArenaStringPtr identifier_value_;
::google::protobuf::uint64 positive_int_value_;
::google::protobuf::int64 negative_int_value_;
double double_value_;
- ::std::string* string_value_;
- ::std::string* aggregate_value_;
+ ::google::protobuf::internal::ArenaStringPtr string_value_;
+ ::google::protobuf::internal::ArenaStringPtr aggregate_value_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
@@ -2680,21 +3224,28 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const SourceCodeInfo_Location& default_instance();
+ void UnsafeArenaSwap(SourceCodeInfo_Location* other);
void Swap(SourceCodeInfo_Location* other);
// implements Message ----------------------------------------------
- SourceCodeInfo_Location* New() const;
+ inline SourceCodeInfo_Location* New() const { return New(NULL); }
+
+ SourceCodeInfo_Location* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const SourceCodeInfo_Location& from);
@@ -2713,7 +3264,21 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(SourceCodeInfo_Location* other);
+ protected:
+ explicit SourceCodeInfo_Location(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2755,6 +3320,9 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
inline ::std::string* mutable_leading_comments();
inline ::std::string* release_leading_comments();
inline void set_allocated_leading_comments(::std::string* leading_comments);
+ inline ::std::string* unsafe_arena_release_leading_comments();
+ inline void unsafe_arena_set_allocated_leading_comments(
+ ::std::string* leading_comments);
// optional string trailing_comments = 4;
inline bool has_trailing_comments() const;
@@ -2767,6 +3335,9 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
inline ::std::string* mutable_trailing_comments();
inline ::std::string* release_trailing_comments();
inline void set_allocated_trailing_comments(::std::string* trailing_comments);
+ inline ::std::string* unsafe_arena_release_trailing_comments();
+ inline void unsafe_arena_set_allocated_trailing_comments(
+ ::std::string* trailing_comments);
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
private:
@@ -2775,16 +3346,18 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
inline void set_has_trailing_comments();
inline void clear_has_trailing_comments();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::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_;
+ ::google::protobuf::internal::ArenaStringPtr leading_comments_;
+ ::google::protobuf::internal::ArenaStringPtr trailing_comments_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
@@ -2807,21 +3380,28 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const SourceCodeInfo& default_instance();
+ void UnsafeArenaSwap(SourceCodeInfo* other);
void Swap(SourceCodeInfo* other);
// implements Message ----------------------------------------------
- SourceCodeInfo* New() const;
+ inline SourceCodeInfo* New() const { return New(NULL); }
+
+ SourceCodeInfo* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const SourceCodeInfo& from);
@@ -2840,7 +3420,21 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(SourceCodeInfo* other);
+ protected:
+ explicit SourceCodeInfo(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -2864,8 +3458,10 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
private:
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_;
@@ -2928,68 +3524,67 @@ inline void FileDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void FileDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& FileDescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FileDescriptorProto::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
}
-inline void FileDescriptorProto::set_name(const char* value, size_t size) {
+inline void FileDescriptorProto::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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
}
inline ::std::string* FileDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FileDescriptorProto::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FileDescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FileDescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
+}
+inline void FileDescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
}
@@ -3004,68 +3599,67 @@ inline void FileDescriptorProto::clear_has_package() {
_has_bits_[0] &= ~0x00000002u;
}
inline void FileDescriptorProto::clear_package() {
- if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- package_->clear();
- }
+ package_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_package();
}
inline const ::std::string& FileDescriptorProto::package() const {
// @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
- return *package_;
+ return package_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FileDescriptorProto::set_package(const ::std::string& value) {
set_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- package_ = new ::std::string;
- }
- package_->assign(value);
+ package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- package_ = new ::std::string;
- }
- package_->assign(value);
+ package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
}
-inline void FileDescriptorProto::set_package(const char* value, size_t size) {
+inline void FileDescriptorProto::set_package(const char* value,
+ size_t size) {
set_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- package_ = new ::std::string;
- }
- package_->assign(reinterpret_cast<const char*>(value), size);
+ package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
}
inline ::std::string* FileDescriptorProto::mutable_package() {
set_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- package_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package)
- return package_;
+ return package_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FileDescriptorProto::release_package() {
clear_has_package();
- if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = package_;
- package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return package_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FileDescriptorProto::unsafe_arena_release_package() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_package();
+ return package_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FileDescriptorProto::set_allocated_package(::std::string* package) {
- if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete package_;
+ if (package != NULL) {
+ set_has_package();
+ } else {
+ clear_has_package();
}
- if (package) {
+ package_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
+}
+inline void FileDescriptorProto::unsafe_arena_set_allocated_package(
+ ::std::string* package) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (package != NULL) {
set_has_package();
- package_ = package;
} else {
clear_has_package();
- package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_package();
+ package_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ package, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
}
@@ -3323,18 +3917,53 @@ inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() con
}
inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
set_has_options();
- if (options_ == NULL) options_ = new ::google::protobuf::FileOptions;
+ if (options_ == NULL) {
+ options_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::FileOptions >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
return options_;
}
inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
clear_has_options();
+ if (GetArenaNoVirtual() != NULL) {
+ if (options_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::FileOptions* temp = new ::google::protobuf::FileOptions;
+ temp->MergeFrom(*options_);
+ options_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::FileOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::FileOptions* FileDescriptorProto::unsafe_arena_release_options() {
+ clear_has_options();
::google::protobuf::FileOptions* temp = options_;
options_ = NULL;
return temp;
}
inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
- delete options_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ if (options != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(options) == NULL) {
+ GetArenaNoVirtual()->Own(options);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(options)) {
+ ::google::protobuf::FileOptions* new_options =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::FileOptions >(
+ GetArenaNoVirtual());
+ new_options->CopyFrom(*options);
+ options = new_options;
+ }
+ }
options_ = options;
if (options) {
set_has_options();
@@ -3343,6 +3972,19 @@ inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileO
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
}
+inline void FileDescriptorProto::unsafe_arena_set_allocated_options(
+ ::google::protobuf::FileOptions* options) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.options)
+}
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
inline bool FileDescriptorProto::has_source_code_info() const {
@@ -3364,18 +4006,53 @@ inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_cod
}
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;
+ if (source_code_info_ == NULL) {
+ source_code_info_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::SourceCodeInfo >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
return source_code_info_;
}
inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
clear_has_source_code_info();
+ if (GetArenaNoVirtual() != NULL) {
+ if (source_code_info_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::SourceCodeInfo* temp = new ::google::protobuf::SourceCodeInfo;
+ temp->MergeFrom(*source_code_info_);
+ source_code_info_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+ source_code_info_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::unsafe_arena_release_source_code_info() {
+ clear_has_source_code_info();
::google::protobuf::SourceCodeInfo* temp = source_code_info_;
source_code_info_ = NULL;
return temp;
}
inline void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
- delete source_code_info_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete source_code_info_;
+ }
+ if (source_code_info != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(source_code_info) == NULL) {
+ GetArenaNoVirtual()->Own(source_code_info);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(source_code_info)) {
+ ::google::protobuf::SourceCodeInfo* new_source_code_info =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::SourceCodeInfo >(
+ GetArenaNoVirtual());
+ new_source_code_info->CopyFrom(*source_code_info);
+ source_code_info = new_source_code_info;
+ }
+ }
source_code_info_ = source_code_info;
if (source_code_info) {
set_has_source_code_info();
@@ -3384,6 +4061,94 @@ inline void FileDescriptorProto::set_allocated_source_code_info(::google::protob
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
}
+inline void FileDescriptorProto::unsafe_arena_set_allocated_source_code_info(
+ ::google::protobuf::SourceCodeInfo* source_code_info) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete source_code_info_;
+ }
+ source_code_info_ = source_code_info;
+ if (source_code_info) {
+ set_has_source_code_info();
+ } else {
+ clear_has_source_code_info();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
+}
+
+// optional string syntax = 12;
+inline bool FileDescriptorProto::has_syntax() const {
+ return (_has_bits_[0] & 0x00000800u) != 0;
+}
+inline void FileDescriptorProto::set_has_syntax() {
+ _has_bits_[0] |= 0x00000800u;
+}
+inline void FileDescriptorProto::clear_has_syntax() {
+ _has_bits_[0] &= ~0x00000800u;
+}
+inline void FileDescriptorProto::clear_syntax() {
+ syntax_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ clear_has_syntax();
+}
+inline const ::std::string& FileDescriptorProto::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
+ return syntax_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileDescriptorProto::set_syntax(const ::std::string& value) {
+ set_has_syntax();
+ syntax_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
+}
+inline void FileDescriptorProto::set_syntax(const char* value) {
+ set_has_syntax();
+ syntax_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
+}
+inline void FileDescriptorProto::set_syntax(const char* value,
+ size_t size) {
+ set_has_syntax();
+ syntax_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
+}
+inline ::std::string* FileDescriptorProto::mutable_syntax() {
+ set_has_syntax();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax)
+ return syntax_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FileDescriptorProto::release_syntax() {
+ clear_has_syntax();
+ return syntax_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FileDescriptorProto::unsafe_arena_release_syntax() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_syntax();
+ return syntax_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
+}
+inline void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) {
+ if (syntax != NULL) {
+ set_has_syntax();
+ } else {
+ clear_has_syntax();
+ }
+ syntax_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
+}
+inline void FileDescriptorProto::unsafe_arena_set_allocated_syntax(
+ ::std::string* syntax) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (syntax != NULL) {
+ set_has_syntax();
+ } else {
+ clear_has_syntax();
+ }
+ set_has_syntax();
+ syntax_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ syntax, GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
+}
// -------------------------------------------------------------------
@@ -3452,68 +4217,67 @@ inline void DescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void DescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& DescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void DescriptorProto::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
}
-inline void DescriptorProto::set_name(const char* value, size_t size) {
+inline void DescriptorProto::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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
}
inline ::std::string* DescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* DescriptorProto::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* DescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void DescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
+}
+inline void DescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
}
@@ -3717,18 +4481,53 @@ inline const ::google::protobuf::MessageOptions& DescriptorProto::options() cons
}
inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
set_has_options();
- if (options_ == NULL) options_ = new ::google::protobuf::MessageOptions;
+ if (options_ == NULL) {
+ options_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::MessageOptions >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
return options_;
}
inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
clear_has_options();
+ if (GetArenaNoVirtual() != NULL) {
+ if (options_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::MessageOptions* temp = new ::google::protobuf::MessageOptions;
+ temp->MergeFrom(*options_);
+ options_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::MessageOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::MessageOptions* DescriptorProto::unsafe_arena_release_options() {
+ clear_has_options();
::google::protobuf::MessageOptions* temp = options_;
options_ = NULL;
return temp;
}
inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
- delete options_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ if (options != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(options) == NULL) {
+ GetArenaNoVirtual()->Own(options);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(options)) {
+ ::google::protobuf::MessageOptions* new_options =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::MessageOptions >(
+ GetArenaNoVirtual());
+ new_options->CopyFrom(*options);
+ options = new_options;
+ }
+ }
options_ = options;
if (options) {
set_has_options();
@@ -3737,6 +4536,19 @@ inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOp
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
}
+inline void DescriptorProto::unsafe_arena_set_allocated_options(
+ ::google::protobuf::MessageOptions* options) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.DescriptorProto.options)
+}
// -------------------------------------------------------------------
@@ -3753,68 +4565,67 @@ inline void FieldDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void FieldDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& FieldDescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FieldDescriptorProto::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
}
-inline void FieldDescriptorProto::set_name(const char* value, size_t size) {
+inline void FieldDescriptorProto::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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
}
inline ::std::string* FieldDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FieldDescriptorProto::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FieldDescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FieldDescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
+}
+inline void FieldDescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
}
@@ -3903,68 +4714,67 @@ inline void FieldDescriptorProto::clear_has_type_name() {
_has_bits_[0] &= ~0x00000010u;
}
inline void FieldDescriptorProto::clear_type_name() {
- if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- type_name_->clear();
- }
+ type_name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return type_name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FieldDescriptorProto::set_type_name(const ::std::string& value) {
set_has_type_name();
- if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- type_name_ = new ::std::string;
- }
- type_name_->assign(value);
+ type_name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- type_name_ = new ::std::string;
- }
- type_name_->assign(value);
+ type_name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
}
-inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
+inline void FieldDescriptorProto::set_type_name(const char* value,
+ size_t size) {
set_has_type_name();
- if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- type_name_ = new ::std::string;
- }
- type_name_->assign(reinterpret_cast<const char*>(value), size);
+ type_name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- type_name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name)
- return type_name_;
+ return type_name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FieldDescriptorProto::release_type_name() {
clear_has_type_name();
- if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = type_name_;
- type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return type_name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FieldDescriptorProto::unsafe_arena_release_type_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_type_name();
+ return type_name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
- if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete type_name_;
+ if (type_name != NULL) {
+ set_has_type_name();
+ } else {
+ clear_has_type_name();
}
- if (type_name) {
+ type_name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
+}
+inline void FieldDescriptorProto::unsafe_arena_set_allocated_type_name(
+ ::std::string* type_name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (type_name != NULL) {
set_has_type_name();
- type_name_ = type_name;
} else {
clear_has_type_name();
- type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_type_name();
+ type_name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ type_name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
}
@@ -3979,68 +4789,67 @@ inline void FieldDescriptorProto::clear_has_extendee() {
_has_bits_[0] &= ~0x00000020u;
}
inline void FieldDescriptorProto::clear_extendee() {
- if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- extendee_->clear();
- }
+ extendee_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_extendee();
}
inline const ::std::string& FieldDescriptorProto::extendee() const {
// @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
- return *extendee_;
+ return extendee_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FieldDescriptorProto::set_extendee(const ::std::string& value) {
set_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- extendee_ = new ::std::string;
- }
- extendee_->assign(value);
+ extendee_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- extendee_ = new ::std::string;
- }
- extendee_->assign(value);
+ extendee_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
}
-inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
+inline void FieldDescriptorProto::set_extendee(const char* value,
+ size_t size) {
set_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- extendee_ = new ::std::string;
- }
- extendee_->assign(reinterpret_cast<const char*>(value), size);
+ extendee_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
}
inline ::std::string* FieldDescriptorProto::mutable_extendee() {
set_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- extendee_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee)
- return extendee_;
+ return extendee_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FieldDescriptorProto::release_extendee() {
clear_has_extendee();
- if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = extendee_;
- extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return extendee_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FieldDescriptorProto::unsafe_arena_release_extendee() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_extendee();
+ return extendee_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
- if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete extendee_;
+ if (extendee != NULL) {
+ set_has_extendee();
+ } else {
+ clear_has_extendee();
}
- if (extendee) {
+ extendee_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
+}
+inline void FieldDescriptorProto::unsafe_arena_set_allocated_extendee(
+ ::std::string* extendee) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (extendee != NULL) {
set_has_extendee();
- extendee_ = extendee;
} else {
clear_has_extendee();
- extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_extendee();
+ extendee_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ extendee, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
}
@@ -4055,68 +4864,67 @@ inline void FieldDescriptorProto::clear_has_default_value() {
_has_bits_[0] &= ~0x00000040u;
}
inline void FieldDescriptorProto::clear_default_value() {
- if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- default_value_->clear();
- }
+ default_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return default_value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FieldDescriptorProto::set_default_value(const ::std::string& value) {
set_has_default_value();
- if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- default_value_ = new ::std::string;
- }
- default_value_->assign(value);
+ default_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- default_value_ = new ::std::string;
- }
- default_value_->assign(value);
+ default_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
}
-inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
+inline void FieldDescriptorProto::set_default_value(const char* value,
+ size_t size) {
set_has_default_value();
- if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- default_value_ = new ::std::string;
- }
- default_value_->assign(reinterpret_cast<const char*>(value), size);
+ default_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- default_value_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value)
- return default_value_;
+ return default_value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FieldDescriptorProto::release_default_value() {
clear_has_default_value();
- if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = default_value_;
- default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return default_value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FieldDescriptorProto::unsafe_arena_release_default_value() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_default_value();
+ return default_value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
- if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete default_value_;
+ if (default_value != NULL) {
+ set_has_default_value();
+ } else {
+ clear_has_default_value();
}
- if (default_value) {
+ default_value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
+}
+inline void FieldDescriptorProto::unsafe_arena_set_allocated_default_value(
+ ::std::string* default_value) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (default_value != NULL) {
set_has_default_value();
- default_value_ = default_value;
} else {
clear_has_default_value();
- default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_default_value();
+ default_value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ default_value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
}
@@ -4164,18 +4972,53 @@ inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() c
}
inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
set_has_options();
- if (options_ == NULL) options_ = new ::google::protobuf::FieldOptions;
+ if (options_ == NULL) {
+ options_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::FieldOptions >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
return options_;
}
inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
clear_has_options();
+ if (GetArenaNoVirtual() != NULL) {
+ if (options_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::FieldOptions* temp = new ::google::protobuf::FieldOptions;
+ temp->MergeFrom(*options_);
+ options_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::FieldOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::FieldOptions* FieldDescriptorProto::unsafe_arena_release_options() {
+ clear_has_options();
::google::protobuf::FieldOptions* temp = options_;
options_ = NULL;
return temp;
}
inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
- delete options_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ if (options != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(options) == NULL) {
+ GetArenaNoVirtual()->Own(options);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(options)) {
+ ::google::protobuf::FieldOptions* new_options =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::FieldOptions >(
+ GetArenaNoVirtual());
+ new_options->CopyFrom(*options);
+ options = new_options;
+ }
+ }
options_ = options;
if (options) {
set_has_options();
@@ -4184,6 +5027,19 @@ inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::Fiel
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options)
}
+inline void FieldDescriptorProto::unsafe_arena_set_allocated_options(
+ ::google::protobuf::FieldOptions* options) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FieldDescriptorProto.options)
+}
// -------------------------------------------------------------------
@@ -4200,68 +5056,67 @@ inline void OneofDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void OneofDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& OneofDescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
}
-inline void OneofDescriptorProto::set_name(const char* value, size_t size) {
+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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
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;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* OneofDescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void OneofDescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
+}
+inline void OneofDescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
}
@@ -4280,68 +5135,67 @@ inline void EnumDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void EnumDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& EnumDescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void EnumDescriptorProto::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
}
inline void EnumDescriptorProto::set_name(const char* value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
}
-inline void EnumDescriptorProto::set_name(const char* value, size_t size) {
+inline void EnumDescriptorProto::set_name(const char* value,
+ size_t size) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(reinterpret_cast<const char*>(value), size);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
}
inline ::std::string* EnumDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* EnumDescriptorProto::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* EnumDescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void EnumDescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
+}
+inline void EnumDescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
}
@@ -4395,18 +5249,53 @@ inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() con
}
inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
set_has_options();
- if (options_ == NULL) options_ = new ::google::protobuf::EnumOptions;
+ if (options_ == NULL) {
+ options_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::EnumOptions >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
return options_;
}
inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
clear_has_options();
+ if (GetArenaNoVirtual() != NULL) {
+ if (options_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::EnumOptions* temp = new ::google::protobuf::EnumOptions;
+ temp->MergeFrom(*options_);
+ options_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::EnumOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::EnumOptions* EnumDescriptorProto::unsafe_arena_release_options() {
+ clear_has_options();
::google::protobuf::EnumOptions* temp = options_;
options_ = NULL;
return temp;
}
inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
- delete options_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ if (options != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(options) == NULL) {
+ GetArenaNoVirtual()->Own(options);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(options)) {
+ ::google::protobuf::EnumOptions* new_options =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::EnumOptions >(
+ GetArenaNoVirtual());
+ new_options->CopyFrom(*options);
+ options = new_options;
+ }
+ }
options_ = options;
if (options) {
set_has_options();
@@ -4415,6 +5304,19 @@ inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumO
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options)
}
+inline void EnumDescriptorProto::unsafe_arena_set_allocated_options(
+ ::google::protobuf::EnumOptions* options) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumDescriptorProto.options)
+}
// -------------------------------------------------------------------
@@ -4431,68 +5333,67 @@ inline void EnumValueDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void EnumValueDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& EnumValueDescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void EnumValueDescriptorProto::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
}
-inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
+inline void EnumValueDescriptorProto::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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
}
inline ::std::string* EnumValueDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* EnumValueDescriptorProto::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* EnumValueDescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
+}
+inline void EnumValueDescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
}
@@ -4540,18 +5441,53 @@ inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::opt
}
inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
set_has_options();
- if (options_ == NULL) options_ = new ::google::protobuf::EnumValueOptions;
+ if (options_ == NULL) {
+ options_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::EnumValueOptions >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
return options_;
}
inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
clear_has_options();
+ if (GetArenaNoVirtual() != NULL) {
+ if (options_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::EnumValueOptions* temp = new ::google::protobuf::EnumValueOptions;
+ temp->MergeFrom(*options_);
+ options_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::EnumValueOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::unsafe_arena_release_options() {
+ clear_has_options();
::google::protobuf::EnumValueOptions* temp = options_;
options_ = NULL;
return temp;
}
inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
- delete options_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ if (options != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(options) == NULL) {
+ GetArenaNoVirtual()->Own(options);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(options)) {
+ ::google::protobuf::EnumValueOptions* new_options =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::EnumValueOptions >(
+ GetArenaNoVirtual());
+ new_options->CopyFrom(*options);
+ options = new_options;
+ }
+ }
options_ = options;
if (options) {
set_has_options();
@@ -4560,6 +5496,19 @@ inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
}
+inline void EnumValueDescriptorProto::unsafe_arena_set_allocated_options(
+ ::google::protobuf::EnumValueOptions* options) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
+}
// -------------------------------------------------------------------
@@ -4576,68 +5525,67 @@ inline void ServiceDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void ServiceDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& ServiceDescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void ServiceDescriptorProto::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
}
-inline void ServiceDescriptorProto::set_name(const char* value, size_t size) {
+inline void ServiceDescriptorProto::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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
}
inline ::std::string* ServiceDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* ServiceDescriptorProto::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* ServiceDescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
+}
+inline void ServiceDescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
}
@@ -4691,18 +5639,53 @@ inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options
}
inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
set_has_options();
- if (options_ == NULL) options_ = new ::google::protobuf::ServiceOptions;
+ if (options_ == NULL) {
+ options_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::ServiceOptions >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
return options_;
}
inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
clear_has_options();
+ if (GetArenaNoVirtual() != NULL) {
+ if (options_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::ServiceOptions* temp = new ::google::protobuf::ServiceOptions;
+ temp->MergeFrom(*options_);
+ options_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::ServiceOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::unsafe_arena_release_options() {
+ clear_has_options();
::google::protobuf::ServiceOptions* temp = options_;
options_ = NULL;
return temp;
}
inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
- delete options_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ if (options != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(options) == NULL) {
+ GetArenaNoVirtual()->Own(options);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(options)) {
+ ::google::protobuf::ServiceOptions* new_options =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::ServiceOptions >(
+ GetArenaNoVirtual());
+ new_options->CopyFrom(*options);
+ options = new_options;
+ }
+ }
options_ = options;
if (options) {
set_has_options();
@@ -4711,6 +5694,19 @@ inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::Se
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options)
}
+inline void ServiceDescriptorProto::unsafe_arena_set_allocated_options(
+ ::google::protobuf::ServiceOptions* options) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.ServiceDescriptorProto.options)
+}
// -------------------------------------------------------------------
@@ -4727,68 +5723,67 @@ inline void MethodDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void MethodDescriptorProto::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& MethodDescriptorProto::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void MethodDescriptorProto::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
}
-inline void MethodDescriptorProto::set_name(const char* value, size_t size) {
+inline void MethodDescriptorProto::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);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
}
inline ::std::string* MethodDescriptorProto::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* MethodDescriptorProto::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* MethodDescriptorProto::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void MethodDescriptorProto::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
+}
+inline void MethodDescriptorProto::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
}
@@ -4803,68 +5798,67 @@ inline void MethodDescriptorProto::clear_has_input_type() {
_has_bits_[0] &= ~0x00000002u;
}
inline void MethodDescriptorProto::clear_input_type() {
- if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- input_type_->clear();
- }
+ input_type_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return input_type_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void MethodDescriptorProto::set_input_type(const ::std::string& value) {
set_has_input_type();
- if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- input_type_ = new ::std::string;
- }
- input_type_->assign(value);
+ input_type_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- input_type_ = new ::std::string;
- }
- input_type_->assign(value);
+ input_type_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
}
-inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
+inline void MethodDescriptorProto::set_input_type(const char* value,
+ size_t size) {
set_has_input_type();
- if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- input_type_ = new ::std::string;
- }
- input_type_->assign(reinterpret_cast<const char*>(value), size);
+ input_type_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- input_type_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type)
- return input_type_;
+ return input_type_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* MethodDescriptorProto::release_input_type() {
clear_has_input_type();
- if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = input_type_;
- input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return input_type_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* MethodDescriptorProto::unsafe_arena_release_input_type() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_input_type();
+ return input_type_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
- if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete input_type_;
+ if (input_type != NULL) {
+ set_has_input_type();
+ } else {
+ clear_has_input_type();
}
- if (input_type) {
+ input_type_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
+}
+inline void MethodDescriptorProto::unsafe_arena_set_allocated_input_type(
+ ::std::string* input_type) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (input_type != NULL) {
set_has_input_type();
- input_type_ = input_type;
} else {
clear_has_input_type();
- input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_input_type();
+ input_type_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ input_type, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
}
@@ -4879,68 +5873,67 @@ inline void MethodDescriptorProto::clear_has_output_type() {
_has_bits_[0] &= ~0x00000004u;
}
inline void MethodDescriptorProto::clear_output_type() {
- if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- output_type_->clear();
- }
+ output_type_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return output_type_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void MethodDescriptorProto::set_output_type(const ::std::string& value) {
set_has_output_type();
- if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- output_type_ = new ::std::string;
- }
- output_type_->assign(value);
+ output_type_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- output_type_ = new ::std::string;
- }
- output_type_->assign(value);
+ output_type_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
}
-inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
+inline void MethodDescriptorProto::set_output_type(const char* value,
+ size_t size) {
set_has_output_type();
- if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- output_type_ = new ::std::string;
- }
- output_type_->assign(reinterpret_cast<const char*>(value), size);
+ output_type_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- output_type_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type)
- return output_type_;
+ return output_type_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* MethodDescriptorProto::release_output_type() {
clear_has_output_type();
- if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = output_type_;
- output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return output_type_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* MethodDescriptorProto::unsafe_arena_release_output_type() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_output_type();
+ return output_type_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
- if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete output_type_;
+ if (output_type != NULL) {
+ set_has_output_type();
+ } else {
+ clear_has_output_type();
}
- if (output_type) {
+ output_type_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
+}
+inline void MethodDescriptorProto::unsafe_arena_set_allocated_output_type(
+ ::std::string* output_type) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (output_type != NULL) {
set_has_output_type();
- output_type_ = output_type;
} else {
clear_has_output_type();
- output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_output_type();
+ output_type_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ output_type, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
}
@@ -4964,18 +5957,53 @@ inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options()
}
inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
set_has_options();
- if (options_ == NULL) options_ = new ::google::protobuf::MethodOptions;
+ if (options_ == NULL) {
+ options_ = ::google::protobuf::Arena::CreateMessage< ::google::protobuf::MethodOptions >(
+ GetArenaNoVirtual());
+ }
// @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
return options_;
}
inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
clear_has_options();
+ if (GetArenaNoVirtual() != NULL) {
+ if (options_ == NULL) {
+ return NULL;
+ } else {
+ ::google::protobuf::MethodOptions* temp = new ::google::protobuf::MethodOptions;
+ temp->MergeFrom(*options_);
+ options_ = NULL;
+ return temp;
+ }
+ } else {
+ ::google::protobuf::MethodOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+ }
+}
+inline ::google::protobuf::MethodOptions* MethodDescriptorProto::unsafe_arena_release_options() {
+ clear_has_options();
::google::protobuf::MethodOptions* temp = options_;
options_ = NULL;
return temp;
}
inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
- delete options_;
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ if (options != NULL) {
+ if (GetArenaNoVirtual() != NULL &&
+ ::google::protobuf::Arena::GetArena(options) == NULL) {
+ GetArenaNoVirtual()->Own(options);
+ } else if (GetArenaNoVirtual() !=
+ ::google::protobuf::Arena::GetArena(options)) {
+ ::google::protobuf::MethodOptions* new_options =
+ ::google::protobuf::Arena::CreateMessage< ::google::protobuf::MethodOptions >(
+ GetArenaNoVirtual());
+ new_options->CopyFrom(*options);
+ options = new_options;
+ }
+ }
options_ = options;
if (options) {
set_has_options();
@@ -4984,6 +6012,19 @@ inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::Met
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options)
}
+inline void MethodDescriptorProto::unsafe_arena_set_allocated_options(
+ ::google::protobuf::MethodOptions* options) {
+ if (GetArenaNoVirtual() == NULL) {
+ delete options_;
+ }
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.MethodDescriptorProto.options)
+}
// -------------------------------------------------------------------
@@ -5000,68 +6041,67 @@ inline void FileOptions::clear_has_java_package() {
_has_bits_[0] &= ~0x00000001u;
}
inline void FileOptions::clear_java_package() {
- if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- java_package_->clear();
- }
+ java_package_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return java_package_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FileOptions::set_java_package(const ::std::string& value) {
set_has_java_package();
- if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- java_package_ = new ::std::string;
- }
- java_package_->assign(value);
+ java_package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- java_package_ = new ::std::string;
- }
- java_package_->assign(value);
+ java_package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
}
-inline void FileOptions::set_java_package(const char* value, size_t size) {
+inline void FileOptions::set_java_package(const char* value,
+ size_t size) {
set_has_java_package();
- if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- java_package_ = new ::std::string;
- }
- java_package_->assign(reinterpret_cast<const char*>(value), size);
+ java_package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- java_package_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package)
- return java_package_;
+ return java_package_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FileOptions::release_java_package() {
clear_has_java_package();
- if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = java_package_;
- java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return java_package_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FileOptions::unsafe_arena_release_java_package() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_java_package();
+ return java_package_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FileOptions::set_allocated_java_package(::std::string* java_package) {
- if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete java_package_;
+ if (java_package != NULL) {
+ set_has_java_package();
+ } else {
+ clear_has_java_package();
}
- if (java_package) {
+ java_package_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
+}
+inline void FileOptions::unsafe_arena_set_allocated_java_package(
+ ::std::string* java_package) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (java_package != NULL) {
set_has_java_package();
- java_package_ = java_package;
} else {
clear_has_java_package();
- java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_java_package();
+ java_package_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ java_package, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
}
@@ -5076,68 +6116,67 @@ 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::GetEmptyStringAlreadyInited()) {
- java_outer_classname_->clear();
- }
+ java_outer_classname_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return java_outer_classname_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FileOptions::set_java_outer_classname(const ::std::string& value) {
set_has_java_outer_classname();
- if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- java_outer_classname_ = new ::std::string;
- }
- java_outer_classname_->assign(value);
+ java_outer_classname_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- java_outer_classname_ = new ::std::string;
- }
- java_outer_classname_->assign(value);
+ java_outer_classname_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@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) {
+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::GetEmptyStringAlreadyInited()) {
- java_outer_classname_ = new ::std::string;
- }
- java_outer_classname_->assign(reinterpret_cast<const char*>(value), size);
+ java_outer_classname_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- java_outer_classname_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname)
- return java_outer_classname_;
+ return java_outer_classname_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FileOptions::release_java_outer_classname() {
clear_has_java_outer_classname();
- if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = java_outer_classname_;
- java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return java_outer_classname_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FileOptions::unsafe_arena_release_java_outer_classname() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_java_outer_classname();
+ return java_outer_classname_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
- if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete java_outer_classname_;
+ if (java_outer_classname != NULL) {
+ set_has_java_outer_classname();
+ } else {
+ clear_has_java_outer_classname();
}
- if (java_outer_classname) {
+ java_outer_classname_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
+}
+inline void FileOptions::unsafe_arena_set_allocated_java_outer_classname(
+ ::std::string* java_outer_classname) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (java_outer_classname != NULL) {
set_has_java_outer_classname();
- java_outer_classname_ = java_outer_classname;
} else {
clear_has_java_outer_classname();
- java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_java_outer_classname();
+ java_outer_classname_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ java_outer_classname, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
}
@@ -5249,68 +6288,67 @@ inline void FileOptions::clear_has_go_package() {
_has_bits_[0] &= ~0x00000040u;
}
inline void FileOptions::clear_go_package() {
- if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- go_package_->clear();
- }
+ go_package_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return go_package_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void FileOptions::set_go_package(const ::std::string& value) {
set_has_go_package();
- if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- go_package_ = new ::std::string;
- }
- go_package_->assign(value);
+ go_package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
}
inline void FileOptions::set_go_package(const char* value) {
set_has_go_package();
- if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- go_package_ = new ::std::string;
- }
- go_package_->assign(value);
+ go_package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
}
-inline void FileOptions::set_go_package(const char* value, size_t size) {
+inline void FileOptions::set_go_package(const char* value,
+ size_t size) {
set_has_go_package();
- if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- go_package_ = new ::std::string;
- }
- go_package_->assign(reinterpret_cast<const char*>(value), size);
+ go_package_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
}
inline ::std::string* FileOptions::mutable_go_package() {
set_has_go_package();
- if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- go_package_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package)
- return go_package_;
+ return go_package_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* FileOptions::release_go_package() {
clear_has_go_package();
- if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = go_package_;
- go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return go_package_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* FileOptions::unsafe_arena_release_go_package() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_go_package();
+ return go_package_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void FileOptions::set_allocated_go_package(::std::string* go_package) {
- if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete go_package_;
+ if (go_package != NULL) {
+ set_has_go_package();
+ } else {
+ clear_has_go_package();
}
- if (go_package) {
+ go_package_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
+}
+inline void FileOptions::unsafe_arena_set_allocated_go_package(
+ ::std::string* go_package) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (go_package != NULL) {
set_has_go_package();
- go_package_ = go_package;
} else {
clear_has_go_package();
- go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_go_package();
+ go_package_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ go_package, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
}
@@ -5516,6 +6554,30 @@ inline void MessageOptions::set_deprecated(bool value) {
// @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated)
}
+// optional bool map_entry = 7;
+inline bool MessageOptions::has_map_entry() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+inline void MessageOptions::set_has_map_entry() {
+ _has_bits_[0] |= 0x00000008u;
+}
+inline void MessageOptions::clear_has_map_entry() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+inline void MessageOptions::clear_map_entry() {
+ map_entry_ = false;
+ clear_has_map_entry();
+}
+inline bool MessageOptions::map_entry() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry)
+ return map_entry_;
+}
+inline void MessageOptions::set_map_entry(bool value) {
+ set_has_map_entry();
+ map_entry_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry)
+}
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int MessageOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
@@ -5647,91 +6709,15 @@ inline void FieldOptions::set_deprecated(bool value) {
// @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated)
}
-// optional string experimental_map_key = 9;
-inline bool FieldOptions::has_experimental_map_key() const {
- return (_has_bits_[0] & 0x00000010u) != 0;
-}
-inline void FieldOptions::set_has_experimental_map_key() {
- _has_bits_[0] |= 0x00000010u;
-}
-inline void FieldOptions::clear_has_experimental_map_key() {
- _has_bits_[0] &= ~0x00000010u;
-}
-inline void FieldOptions::clear_experimental_map_key() {
- if (experimental_map_key_ != &::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::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::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::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::GetEmptyStringAlreadyInited()) {
- experimental_map_key_ = new ::std::string;
- }
- // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.experimental_map_key)
- return experimental_map_key_;
-}
-inline ::std::string* FieldOptions::release_experimental_map_key() {
- clear_has_experimental_map_key();
- if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = experimental_map_key_;
- experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
-}
-inline void FieldOptions::set_allocated_experimental_map_key(::std::string* experimental_map_key) {
- if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete experimental_map_key_;
- }
- if (experimental_map_key) {
- set_has_experimental_map_key();
- experimental_map_key_ = experimental_map_key;
- } else {
- clear_has_experimental_map_key();
- experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- }
- // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldOptions.experimental_map_key)
-}
-
// optional bool weak = 10 [default = false];
inline bool FieldOptions::has_weak() const {
- return (_has_bits_[0] & 0x00000020u) != 0;
+ return (_has_bits_[0] & 0x00000010u) != 0;
}
inline void FieldOptions::set_has_weak() {
- _has_bits_[0] |= 0x00000020u;
+ _has_bits_[0] |= 0x00000010u;
}
inline void FieldOptions::clear_has_weak() {
- _has_bits_[0] &= ~0x00000020u;
+ _has_bits_[0] &= ~0x00000010u;
}
inline void FieldOptions::clear_weak() {
weak_ = false;
@@ -6048,68 +7034,67 @@ 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::GetEmptyStringAlreadyInited()) {
- name_part_->clear();
- }
+ name_part_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return name_part_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
set_has_name_part();
- if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_part_ = new ::std::string;
- }
- name_part_->assign(value);
+ name_part_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_part_ = new ::std::string;
- }
- name_part_->assign(value);
+ name_part_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@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) {
+inline void UninterpretedOption_NamePart::set_name_part(const char* value,
+ size_t size) {
set_has_name_part();
- if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_part_ = new ::std::string;
- }
- name_part_->assign(reinterpret_cast<const char*>(value), size);
+ name_part_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- name_part_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part)
- return name_part_;
+ return name_part_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* UninterpretedOption_NamePart::release_name_part() {
clear_has_name_part();
- if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_part_;
- name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_part_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* UninterpretedOption_NamePart::unsafe_arena_release_name_part() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name_part();
+ return name_part_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
- if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_part_;
+ if (name_part != NULL) {
+ set_has_name_part();
+ } else {
+ clear_has_name_part();
}
- if (name_part) {
+ name_part_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+inline void UninterpretedOption_NamePart::unsafe_arena_set_allocated_name_part(
+ ::std::string* name_part) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name_part != NULL) {
set_has_name_part();
- name_part_ = name_part;
} else {
clear_has_name_part();
- name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name_part();
+ name_part_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name_part, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
}
@@ -6182,68 +7167,67 @@ inline void UninterpretedOption::clear_has_identifier_value() {
_has_bits_[0] &= ~0x00000002u;
}
inline void UninterpretedOption::clear_identifier_value() {
- if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- identifier_value_->clear();
- }
+ identifier_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return identifier_value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void UninterpretedOption::set_identifier_value(const ::std::string& value) {
set_has_identifier_value();
- if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- identifier_value_ = new ::std::string;
- }
- identifier_value_->assign(value);
+ identifier_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- identifier_value_ = new ::std::string;
- }
- identifier_value_->assign(value);
+ identifier_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
}
-inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
+inline void UninterpretedOption::set_identifier_value(const char* value,
+ size_t size) {
set_has_identifier_value();
- if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- identifier_value_ = new ::std::string;
- }
- identifier_value_->assign(reinterpret_cast<const char*>(value), size);
+ identifier_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- identifier_value_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value)
- return identifier_value_;
+ return identifier_value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* UninterpretedOption::release_identifier_value() {
clear_has_identifier_value();
- if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = identifier_value_;
- identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return identifier_value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* UninterpretedOption::unsafe_arena_release_identifier_value() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_identifier_value();
+ return identifier_value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
- if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete identifier_value_;
+ if (identifier_value != NULL) {
+ set_has_identifier_value();
+ } else {
+ clear_has_identifier_value();
}
- if (identifier_value) {
+ identifier_value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
+}
+inline void UninterpretedOption::unsafe_arena_set_allocated_identifier_value(
+ ::std::string* identifier_value) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (identifier_value != NULL) {
set_has_identifier_value();
- identifier_value_ = identifier_value;
} else {
clear_has_identifier_value();
- identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_identifier_value();
+ identifier_value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ identifier_value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
}
@@ -6330,68 +7314,67 @@ inline void UninterpretedOption::clear_has_string_value() {
_has_bits_[0] &= ~0x00000020u;
}
inline void UninterpretedOption::clear_string_value() {
- if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- string_value_->clear();
- }
+ string_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return string_value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void UninterpretedOption::set_string_value(const ::std::string& value) {
set_has_string_value();
- if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- string_value_ = new ::std::string;
- }
- string_value_->assign(value);
+ string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- string_value_ = new ::std::string;
- }
- string_value_->assign(value);
+ string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
}
-inline void UninterpretedOption::set_string_value(const void* value, size_t size) {
+inline void UninterpretedOption::set_string_value(const void* value,
+ size_t size) {
set_has_string_value();
- if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- string_value_ = new ::std::string;
- }
- string_value_->assign(reinterpret_cast<const char*>(value), size);
+ string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@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::GetEmptyStringAlreadyInited()) {
- string_value_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value)
- return string_value_;
+ return string_value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* UninterpretedOption::release_string_value() {
clear_has_string_value();
- if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = string_value_;
- string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return string_value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* UninterpretedOption::unsafe_arena_release_string_value() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_string_value();
+ return string_value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
- if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete string_value_;
+ if (string_value != NULL) {
+ set_has_string_value();
+ } else {
+ clear_has_string_value();
}
- if (string_value) {
+ string_value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
+}
+inline void UninterpretedOption::unsafe_arena_set_allocated_string_value(
+ ::std::string* string_value) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (string_value != NULL) {
set_has_string_value();
- string_value_ = string_value;
} else {
clear_has_string_value();
- string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_string_value();
+ string_value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ string_value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
}
@@ -6406,68 +7389,67 @@ inline void UninterpretedOption::clear_has_aggregate_value() {
_has_bits_[0] &= ~0x00000040u;
}
inline void UninterpretedOption::clear_aggregate_value() {
- if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- aggregate_value_->clear();
- }
+ aggregate_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return aggregate_value_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
set_has_aggregate_value();
- if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- aggregate_value_ = new ::std::string;
- }
- aggregate_value_->assign(value);
+ aggregate_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
}
inline void UninterpretedOption::set_aggregate_value(const char* value) {
set_has_aggregate_value();
- if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- aggregate_value_ = new ::std::string;
- }
- aggregate_value_->assign(value);
+ aggregate_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
}
-inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+inline void UninterpretedOption::set_aggregate_value(const char* value,
+ size_t size) {
set_has_aggregate_value();
- if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- aggregate_value_ = new ::std::string;
- }
- aggregate_value_->assign(reinterpret_cast<const char*>(value), size);
+ aggregate_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
}
inline ::std::string* UninterpretedOption::mutable_aggregate_value() {
set_has_aggregate_value();
- if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- aggregate_value_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value)
- return aggregate_value_;
+ return aggregate_value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* UninterpretedOption::release_aggregate_value() {
clear_has_aggregate_value();
- if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = aggregate_value_;
- aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return aggregate_value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* UninterpretedOption::unsafe_arena_release_aggregate_value() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_aggregate_value();
+ return aggregate_value_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
- if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete aggregate_value_;
+ if (aggregate_value != NULL) {
+ set_has_aggregate_value();
+ } else {
+ clear_has_aggregate_value();
}
- if (aggregate_value) {
+ aggregate_value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
+}
+inline void UninterpretedOption::unsafe_arena_set_allocated_aggregate_value(
+ ::std::string* aggregate_value) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (aggregate_value != NULL) {
set_has_aggregate_value();
- aggregate_value_ = aggregate_value;
} else {
clear_has_aggregate_value();
- aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_aggregate_value();
+ aggregate_value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ aggregate_value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
}
@@ -6546,68 +7528,67 @@ inline void SourceCodeInfo_Location::clear_has_leading_comments() {
_has_bits_[0] &= ~0x00000004u;
}
inline void SourceCodeInfo_Location::clear_leading_comments() {
- if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- leading_comments_->clear();
- }
+ leading_comments_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return leading_comments_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
set_has_leading_comments();
- if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- leading_comments_ = new ::std::string;
- }
- leading_comments_->assign(value);
+ leading_comments_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
}
inline void SourceCodeInfo_Location::set_leading_comments(const char* value) {
set_has_leading_comments();
- if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- leading_comments_ = new ::std::string;
- }
- leading_comments_->assign(value);
+ leading_comments_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@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) {
+inline void SourceCodeInfo_Location::set_leading_comments(const char* value,
+ size_t size) {
set_has_leading_comments();
- if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- leading_comments_ = new ::std::string;
- }
- leading_comments_->assign(reinterpret_cast<const char*>(value), size);
+ leading_comments_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
}
inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
set_has_leading_comments();
- if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- leading_comments_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments)
- return leading_comments_;
+ return leading_comments_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* SourceCodeInfo_Location::release_leading_comments() {
clear_has_leading_comments();
- if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = leading_comments_;
- leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return leading_comments_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* SourceCodeInfo_Location::unsafe_arena_release_leading_comments() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_leading_comments();
+ return leading_comments_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
- if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete leading_comments_;
+ if (leading_comments != NULL) {
+ set_has_leading_comments();
+ } else {
+ clear_has_leading_comments();
}
- if (leading_comments) {
+ leading_comments_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+inline void SourceCodeInfo_Location::unsafe_arena_set_allocated_leading_comments(
+ ::std::string* leading_comments) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (leading_comments != NULL) {
set_has_leading_comments();
- leading_comments_ = leading_comments;
} else {
clear_has_leading_comments();
- leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_leading_comments();
+ leading_comments_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ leading_comments, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
}
@@ -6622,68 +7603,67 @@ inline void SourceCodeInfo_Location::clear_has_trailing_comments() {
_has_bits_[0] &= ~0x00000008u;
}
inline void SourceCodeInfo_Location::clear_trailing_comments() {
- if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- trailing_comments_->clear();
- }
+ trailing_comments_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
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_;
+ return trailing_comments_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
set_has_trailing_comments();
- if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- trailing_comments_ = new ::std::string;
- }
- trailing_comments_->assign(value);
+ trailing_comments_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
}
inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
set_has_trailing_comments();
- if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- trailing_comments_ = new ::std::string;
- }
- trailing_comments_->assign(value);
+ trailing_comments_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@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) {
+inline void SourceCodeInfo_Location::set_trailing_comments(const char* value,
+ size_t size) {
set_has_trailing_comments();
- if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- trailing_comments_ = new ::std::string;
- }
- trailing_comments_->assign(reinterpret_cast<const char*>(value), size);
+ trailing_comments_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
}
inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
set_has_trailing_comments();
- if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- trailing_comments_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments)
- return trailing_comments_;
+ return trailing_comments_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
clear_has_trailing_comments();
- if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = trailing_comments_;
- trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return trailing_comments_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* SourceCodeInfo_Location::unsafe_arena_release_trailing_comments() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_trailing_comments();
+ return trailing_comments_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
- if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete trailing_comments_;
+ if (trailing_comments != NULL) {
+ set_has_trailing_comments();
+ } else {
+ clear_has_trailing_comments();
}
- if (trailing_comments) {
+ trailing_comments_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+inline void SourceCodeInfo_Location::unsafe_arena_set_allocated_trailing_comments(
+ ::std::string* trailing_comments) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (trailing_comments != NULL) {
set_has_trailing_comments();
- trailing_comments_ = trailing_comments;
} else {
clear_has_trailing_comments();
- trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_trailing_comments();
+ trailing_comments_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ trailing_comments, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
}
@@ -6752,8 +7732,8 @@ inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions
return ::google::protobuf::FieldOptions_CType_descriptor();
}
-} // namespace google
} // namespace protobuf
+} // namespace google
#endif // SWIG
// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index a753601f..f30f4df5 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -37,6 +37,7 @@
// without any other information (e.g. without reading its imports).
+syntax = "proto2";
package google.protobuf;
option java_package = "com.google.protobuf";
@@ -74,10 +75,14 @@ message FileDescriptorProto {
optional FileOptions options = 8;
// This field contains optional information about the original source code.
- // You may safely remove this entire field whithout harming runtime
+ // You may safely remove this entire field without harming runtime
// functionality of the descriptors -- the information is needed only by
// development tools.
optional SourceCodeInfo source_code_info = 9;
+
+ // The syntax of the proto file.
+ // The supported values are "proto2" and "proto3".
+ optional string syntax = 12;
}
// Describes a message type.
@@ -306,7 +311,10 @@ message FileOptions {
optional OptimizeMode optimize_for = 9 [default=SPEED];
// Sets the Go package where structs generated from this .proto will be
- // placed. There is no default.
+ // placed. If omitted, the Go package will be derived from the following:
+ // - The basename of the package import path, if provided.
+ // - Otherwise, the package statement in the .proto file, if present.
+ // - Otherwise, the basename of the .proto file, without extension.
optional string go_package = 11;
@@ -315,7 +323,7 @@ message FileOptions {
// are not specific to any particular RPC system. They are generated by the
// main code generators in each language (without additional plugins).
// Generic services were the only kind of service generation supported by
- // early versions of proto2.
+ // early versions of google.protobuf.
//
// Generic services are now considered deprecated in favor of using plugins
// that generate code specific to your particular RPC system. Therefore,
@@ -371,6 +379,29 @@ message MessageOptions {
// this is a formalization for deprecating messages.
optional bool deprecated = 3 [default=false];
+ // Whether the message is an automatically generated map entry type for the
+ // maps field.
+ //
+ // For maps fields:
+ // map<KeyType, ValueType> map_field = 1;
+ // The parsed descriptor looks like:
+ // message MapFieldEntry {
+ // option map_entry = true;
+ // optional KeyType key = 1;
+ // optional ValueType value = 2;
+ // }
+ // repeated MapFieldEntry map_field = 1;
+ //
+ // Implementations may choose not to generate the map_entry=true message, but
+ // use a native map in the target language to hold the keys and values.
+ // The reflection APIs in such implementions still need to work as
+ // if the field is a repeated message field.
+ //
+ // NOTE: Do not set the option in .proto files. Always use the maps syntax
+ // instead. The option should only be implicitly set by the proto compiler
+ // parser.
+ optional bool map_entry = 7;
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -436,20 +467,6 @@ message FieldOptions {
// is a formalization for deprecating fields.
optional bool deprecated = 3 [default=false];
- // EXPERIMENTAL. DO NOT USE.
- // For "map" fields, the name of the field in the enclosed type that
- // is the key for this map. For example, suppose we have:
- // message Item {
- // required string name = 1;
- // required string value = 2;
- // }
- // message Config {
- // repeated Item items = 1 [experimental_map_key="name"];
- // }
- // In this situation, the map key for Item will be set to "name".
- // TODO: Fully-implement this, then remove the "experimental_" prefix.
- optional string experimental_map_key = 9;
-
// For Google-internal migration only. Do not use.
optional bool weak = 10 [default=false];
diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py
index 48a0d48a..c5a8d8a2 100644
--- a/src/google/protobuf/descriptor_pb2_test.py
+++ b/src/google/protobuf/descriptor_pb2_test.py
@@ -33,14 +33,14 @@
# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date.
from google3.pyglib import resources
-import unittest
+from google.apputils import basetest
_DESC = 'google3/net/proto2/proto/descriptor_pb2.'
_OLD = _DESC + 'py-prebuilt'
_NEW = _DESC + 'compiled'
-class PregeneratedFileChanged(unittest.TestCase):
+class PregeneratedFileChanged(basetest.TestCase):
def testSameText(self):
generated = resources.GetResource(_NEW)
@@ -51,4 +51,4 @@ class PregeneratedFileChanged(unittest.TestCase):
'regnerate a new version of %s and add it to your CL' % _OLD)
if __name__ == '__main__':
- unittest.main()
+ basetest.main()
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index ac96160c..3e6de803 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -360,6 +360,34 @@ TEST_F(FileDescriptorTest, BuildAgain) {
EXPECT_TRUE(pool_.BuildFile(file) == NULL);
}
+TEST_F(FileDescriptorTest, Syntax) {
+ FileDescriptorProto proto;
+ proto.set_name("foo");
+ // Enable the test when we also populate the syntax for proto2.
+#if 0
+ {
+ proto.set_syntax("proto2");
+ DescriptorPool pool;
+ const FileDescriptor* file = pool.BuildFile(proto);
+ EXPECT_TRUE(file != NULL);
+ EXPECT_EQ(FileDescriptor::SYNTAX_PROTO2, file->syntax());
+ FileDescriptorProto other;
+ file->CopyTo(&other);
+ EXPECT_EQ("proto2", other.syntax());
+ }
+#endif
+ {
+ proto.set_syntax("proto3");
+ DescriptorPool pool;
+ const FileDescriptor* file = pool.BuildFile(proto);
+ EXPECT_TRUE(file != NULL);
+ EXPECT_EQ(FileDescriptor::SYNTAX_PROTO3, file->syntax());
+ FileDescriptorProto other;
+ file->CopyTo(&other);
+ EXPECT_EQ("proto3", other.syntax());
+ }
+}
+
// ===================================================================
// Test simple flat messages and fields.
@@ -2157,6 +2185,12 @@ TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) {
// Placeholder files should not be findable.
EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
+
+ // Copy*To should not crash for placeholder files.
+ FileDescriptorProto baz_file_proto;
+ baz_file->CopyTo(&baz_file_proto);
+ baz_file->CopySourceCodeInfoTo(&baz_file_proto);
+ EXPECT_FALSE(baz_file_proto.has_source_code_info());
}
TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) {
@@ -4736,6 +4770,553 @@ TEST_F(ValidationErrorTest, UnusedImportWarning) {
"}");
}
+namespace {
+void FillValidMapEntry(FileDescriptorProto* file_proto) {
+ ASSERT_TRUE(TextFormat::ParseFromString(
+ "name: 'foo.proto' "
+ "message_type { "
+ " name: 'Foo' "
+ " field { "
+ " name: 'foo_map' number: 1 label:LABEL_REPEATED "
+ " type_name: 'FooMapEntry' "
+ " } "
+ " nested_type { "
+ " name: 'FooMapEntry' "
+ " options { map_entry: true } "
+ " field { "
+ " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
+ " } "
+ " field { "
+ " name: 'value' number: 2 type:TYPE_INT32 label:LABEL_OPTIONAL "
+ " } "
+ " } "
+ "} "
+ "message_type { "
+ " name: 'Bar' "
+ " extension_range { start: 1 end: 10 }"
+ "} ",
+ file_proto));
+}
+static const char* kMapEntryErrorMessage =
+ "foo.proto: Foo.foo_map: OTHER: map_entry should not be set explicitly. "
+ "Use map<KeyType, ValueType> instead.\n";
+static const char* kMapEntryKeyTypeErrorMessage =
+ "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot be float/double, "
+ "bytes or message types.\n";
+
+} // namespace
+
+TEST_F(ValidationErrorTest, MapEntryBase) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ BuildFile(file_proto.DebugString());
+}
+
+TEST_F(ValidationErrorTest, MapEntryExtensionRange) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "extension_range { "
+ " start: 10 end: 20 "
+ "} ",
+ file_proto.mutable_message_type(0)->mutable_nested_type(0));
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryExtension) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "extension { "
+ " name: 'foo_ext' extendee: '.Bar' number: 5"
+ "} ",
+ file_proto.mutable_message_type(0)->mutable_nested_type(0));
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryNestedType) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "nested_type { "
+ " name: 'Bar' "
+ "} ",
+ file_proto.mutable_message_type(0)->mutable_nested_type(0));
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryEnumTypes) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "enum_type { "
+ " name: 'BarEnum' "
+ " value { name: 'BAR_BAR' number:0 } "
+ "} ",
+ file_proto.mutable_message_type(0)->mutable_nested_type(0));
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryExtraField) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "field { "
+ " name: 'other_field' "
+ " label: LABEL_OPTIONAL "
+ " type: TYPE_INT32 "
+ " number: 3 "
+ "} ",
+ file_proto.mutable_message_type(0)->mutable_nested_type(0));
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryMessageName) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ file_proto.mutable_message_type(0)->mutable_nested_type(0)->set_name(
+ "OtherMapEntry");
+ file_proto.mutable_message_type(0)->mutable_field(0)->set_type_name(
+ "OtherMapEntry");
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryNoneRepeatedMapEntry) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ file_proto.mutable_message_type(0)->mutable_field(0)->set_label(
+ FieldDescriptorProto::LABEL_OPTIONAL);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryDifferentContainingType) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ // Move the nested MapEntry message into the top level, which should not pass
+ // the validation.
+ file_proto.mutable_message_type()->AddAllocated(
+ file_proto.mutable_message_type(0)->mutable_nested_type()->ReleaseLast());
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyName) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->set_name("Key");
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyLabel) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->set_label(FieldDescriptorProto::LABEL_REQUIRED);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyNumber) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->set_number(3);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryValueName) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* value = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(1);
+ value->set_name("Value");
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryValueLabel) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* value = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(1);
+ value->set_label(FieldDescriptorProto::LABEL_REQUIRED);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryValueNumber) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* value = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(1);
+ value->set_number(3);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeFloat) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->set_type(FieldDescriptorProto::TYPE_FLOAT);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeDouble) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->set_type(FieldDescriptorProto::TYPE_DOUBLE);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeBytes) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->set_type(FieldDescriptorProto::TYPE_BYTES);
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeEnum) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->clear_type();
+ key->set_type_name("BarEnum");
+ EnumDescriptorProto* enum_proto = file_proto.add_enum_type();
+ enum_proto->set_name("BarEnum");
+ EnumValueDescriptorProto* enum_value_proto = enum_proto->add_value();
+ enum_value_proto->set_name("BAR_VALUE0");
+ enum_value_proto->set_number(0);
+ BuildFileWithErrors(file_proto.DebugString(),
+ "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
+ "be enum types.\n");
+ // Enum keys are not allowed in proto3 as well.
+ // Get rid of extensions for proto3 to make it proto3 compatible.
+ file_proto.mutable_message_type()->RemoveLast();
+ file_proto.set_syntax("proto3");
+ BuildFileWithErrors(file_proto.DebugString(),
+ "foo.proto: Foo.foo_map: TYPE: Key in map fields cannot "
+ "be enum types.\n");
+}
+
+
+TEST_F(ValidationErrorTest, MapEntryKeyTypeMessage) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ FieldDescriptorProto* key = file_proto.mutable_message_type(0)
+ ->mutable_nested_type(0)
+ ->mutable_field(0);
+ key->clear_type();
+ key->set_type_name(".Bar");
+ BuildFileWithErrors(file_proto.DebugString(), kMapEntryKeyTypeErrorMessage);
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithField) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "field { "
+ " name: 'FooMapEntry' "
+ " type: TYPE_INT32 "
+ " label: LABEL_OPTIONAL "
+ " number: 100 "
+ "}",
+ file_proto.mutable_message_type(0));
+ BuildFileWithErrors(
+ file_proto.DebugString(),
+ "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+ "\"Foo\".\n"
+ "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
+ "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+ "with an existing field.\n");
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithMessage) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "nested_type { "
+ " name: 'FooMapEntry' "
+ "}",
+ file_proto.mutable_message_type(0));
+ BuildFileWithErrors(
+ file_proto.DebugString(),
+ "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+ "\"Foo\".\n"
+ "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+ "with an existing nested message type.\n");
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithEnum) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "enum_type { "
+ " name: 'FooMapEntry' "
+ " value { name: 'ENTRY_FOO' number: 0 }"
+ "}",
+ file_proto.mutable_message_type(0));
+ BuildFileWithErrors(
+ file_proto.DebugString(),
+ "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+ "\"Foo\".\n"
+ "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+ "with an existing enum type.\n");
+}
+
+TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) {
+ FileDescriptorProto file_proto;
+ FillValidMapEntry(&file_proto);
+ TextFormat::MergeFromString(
+ "oneof_decl { "
+ " name: 'FooMapEntry' "
+ "}"
+ "field { "
+ " name: 'int_field' "
+ " type: TYPE_INT32 "
+ " label: LABEL_OPTIONAL "
+ " oneof_index: 0 "
+ " number: 100 "
+ "} ",
+ file_proto.mutable_message_type(0));
+ BuildFileWithErrors(
+ file_proto.DebugString(),
+ "foo.proto: Foo.FooMapEntry: NAME: \"FooMapEntry\" is already defined in "
+ "\"Foo\".\n"
+ "foo.proto: Foo.foo_map: TYPE: \"FooMapEntry\" is not defined.\n"
+ "foo.proto: Foo: NAME: Expanded map entry type FooMapEntry conflicts "
+ "with an existing oneof type.\n");
+}
+
+TEST_F(ValidationErrorTest, Proto3RequiredFields) {
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " field { name:'foo' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
+ "}",
+ "foo.proto: Foo.foo: OTHER: Required fields are not allowed in "
+ "proto3.\n");
+
+ // applied to nested types as well.
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " nested_type { "
+ " name : 'Bar' "
+ " field { name:'bar' number:1 label:LABEL_REQUIRED type:TYPE_INT32 } "
+ " } "
+ "}",
+ "foo.proto: Foo.Bar.bar: OTHER: Required fields are not allowed in "
+ "proto3.\n");
+
+ // optional and repeated fields are OK.
+ BuildFile(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
+ " field { name:'bar' number:2 label:LABEL_REPEATED type:TYPE_INT32 } "
+ "}");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3DefaultValue) {
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " default_value: '1' }"
+ "}",
+ "foo.proto: Foo.foo: OTHER: Explicit default values are not allowed in "
+ "proto3.\n");
+
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " nested_type { "
+ " name : 'Bar' "
+ " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " default_value: '1' }"
+ " } "
+ "}",
+ "foo.proto: Foo.Bar.bar: OTHER: Explicit default values are not allowed "
+ "in proto3.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3ExtensionRange) {
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " field { name:'foo' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
+ " extension_range { start:10 end:100 } "
+ "}",
+ "foo.proto: Foo: OTHER: Extension ranges are not allowed in "
+ "proto3.\n");
+
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " nested_type { "
+ " name : 'Bar' "
+ " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_INT32 } "
+ " extension_range { start:10 end:100 } "
+ " } "
+ "}",
+ "foo.proto: Foo.Bar: OTHER: Extension ranges are not allowed in "
+ "proto3.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3MessageSetWireFormat) {
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " options { message_set_wire_format: true } "
+ "}",
+ "foo.proto: Foo: OTHER: MessageSet is not supported "
+ "in proto3.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3Enum) {
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "enum_type { "
+ " name: 'FooEnum' "
+ " value { name: 'FOO_FOO' number:1 } "
+ "}",
+ "foo.proto: FooEnum: OTHER: The first enum value must be "
+ "zero in proto3.\n");
+
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " enum_type { "
+ " name: 'FooEnum' "
+ " value { name: 'FOO_FOO' number:1 } "
+ " } "
+ "}",
+ "foo.proto: Foo.FooEnum: OTHER: The first enum value must be "
+ "zero in proto3.\n");
+
+ // valid case.
+ BuildFile(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "enum_type { "
+ " name: 'FooEnum' "
+ " value { name: 'FOO_FOO' number:0 } "
+ "}");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3LiteRuntime) {
+ // Lite runtime is not supported in proto3.
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "options { "
+ " optimize_for: LITE_RUNTIME "
+ "} ",
+ "foo.proto: foo.proto: OTHER: Lite runtime is not supported "
+ "in proto3.\n");
+}
+
+
+TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) {
+ // Define an enum in a proto2 file.
+ BuildFile(
+ "name: 'foo.proto' "
+ "package: 'foo' "
+ "syntax: 'proto2' "
+ "enum_type { "
+ " name: 'FooEnum' "
+ " value { name: 'DEFAULT_OPTION' number:0 } "
+ "}");
+
+ // Now try to refer to it. (All tests in the fixture use the same pool, so we
+ // can refer to the enum above in this definition.)
+ BuildFileWithErrors(
+ "name: 'bar.proto' "
+ "dependency: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " field { name:'bar' number:1 label:LABEL_OPTIONAL type:TYPE_ENUM "
+ " type_name: 'foo.FooEnum' }"
+ "}",
+ "bar.proto: Foo.bar: TYPE: Enum type \"foo.FooEnum\" is not a proto3 "
+ "enum, but is used in \"Foo\" which is a proto3 message type.\n");
+}
+
+TEST_F(ValidationErrorTest, ValidateProto3Extension) {
+ // Valid for options.
+ 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.set_syntax("proto3");
+ 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);
+
+ // Copy and change the package of the descriptor.proto
+ BuildFile(
+ "name: 'google.protobuf.proto' "
+ "syntax: 'proto2' "
+ "message_type { "
+ " name: 'Container' extension_range { start: 1 end: 1000 } "
+ "}");
+ BuildFileWithErrors(
+ "name: 'bar.proto' "
+ "syntax: 'proto3' "
+ "dependency: 'google.protobuf.proto' "
+ "extension { "
+ " name: 'bar' number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 "
+ " extendee: 'Container' "
+ "}",
+ "bar.proto: bar: OTHER: Extensions in proto3 are only allowed for "
+ "defining options.\n");
+}
// ===================================================================
// DescriptorDatabase
diff --git a/src/google/protobuf/drop_unknown_fields_test.cc b/src/google/protobuf/drop_unknown_fields_test.cc
new file mode 100644
index 00000000..2a672c7a
--- /dev/null
+++ b/src/google/protobuf/drop_unknown_fields_test.cc
@@ -0,0 +1,88 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/unittest_drop_unknown_fields.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using unittest_drop_unknown_fields::Foo;
+using unittest_drop_unknown_fields::FooWithExtraFields;
+
+namespace protobuf {
+
+TEST(DropUnknownFieldsTest, GeneratedMessage) {
+ FooWithExtraFields foo_with_extra_fields;
+ foo_with_extra_fields.set_int32_value(1);
+ foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
+ foo_with_extra_fields.set_extra_int32_value(2);
+
+ Foo foo;
+ ASSERT_TRUE(foo.ParseFromString(foo_with_extra_fields.SerializeAsString()));
+ EXPECT_EQ(1, foo.int32_value());
+ EXPECT_EQ(static_cast<int>(FooWithExtraFields::QUX),
+ static_cast<int>(foo.enum_value()));
+ // We don't generate unknown field accessors but the UnknownFieldSet is
+ // still exposed through reflection API.
+ EXPECT_TRUE(foo.GetReflection()->GetUnknownFields(foo).empty());
+
+ ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo.SerializeAsString()));
+ EXPECT_EQ(1, foo_with_extra_fields.int32_value());
+ EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value());
+ // The "extra_int32_value" field should be lost.
+ EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value());
+}
+
+TEST(DropUnknownFieldsTest, DynamicMessage) {
+ FooWithExtraFields foo_with_extra_fields;
+ foo_with_extra_fields.set_int32_value(1);
+ foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
+ foo_with_extra_fields.set_extra_int32_value(2);
+
+ google::protobuf::DynamicMessageFactory factory;
+ scoped_ptr<google::protobuf::Message> foo(
+ factory.GetPrototype(Foo::descriptor())->New());
+ ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString()));
+ EXPECT_TRUE(foo->GetReflection()->GetUnknownFields(*foo).empty());
+
+ ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo->SerializeAsString()));
+ EXPECT_EQ(1, foo_with_extra_fields.int32_value());
+ EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value());
+ // The "extra_int32_value" field should be lost.
+ EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value());
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 4cca9869..db1dd4d3 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -72,6 +72,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/arenastring.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
@@ -85,6 +86,8 @@ using internal::ExtensionSet;
using internal::GeneratedMessageReflection;
+using internal::ArenaStringPtr;
+
// ===================================================================
// Some helper tables and functions...
@@ -131,7 +134,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
- return sizeof(string*);
+ return sizeof(ArenaStringPtr);
}
break;
}
@@ -162,7 +165,7 @@ int OneofFieldSpaceUsed(const FieldDescriptor* field) {
switch (field->options().ctype()) {
default:
case FieldOptions::STRING:
- return sizeof(string*);
+ return sizeof(ArenaStringPtr);
}
break;
}
@@ -236,6 +239,8 @@ class DynamicMessage : public Message {
// implements Message ----------------------------------------------
Message* New() const;
+ Message* New(::google::protobuf::Arena* arena) const;
+ ::google::protobuf::Arena* GetArena() const { return NULL; };
int GetCachedSize() const;
void SetCachedSize(int size) const;
@@ -245,6 +250,8 @@ class DynamicMessage : public Message {
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
+ DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena);
+ void SharedCtor();
inline bool is_prototype() const {
return type_info_->prototype == this ||
@@ -261,7 +268,6 @@ class DynamicMessage : public Message {
}
const TypeInfo* type_info_;
-
// TODO(kenton): Make this an atomic<int> when C++ supports it.
mutable int cached_byte_size_;
};
@@ -269,6 +275,17 @@ class DynamicMessage : public Message {
DynamicMessage::DynamicMessage(const TypeInfo* type_info)
: type_info_(type_info),
cached_byte_size_(0) {
+ SharedCtor();
+}
+
+DynamicMessage::DynamicMessage(const TypeInfo* type_info,
+ ::google::protobuf::Arena* arena)
+ : type_info_(type_info),
+ cached_byte_size_(0) {
+ SharedCtor();
+}
+
+void DynamicMessage::SharedCtor() {
// We need to call constructors for various fields manually and set
// default values where appropriate. We use placement new to call
// constructors. If you haven't heard of placement new, I suggest Googling
@@ -330,15 +347,17 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info)
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
if (!field->is_repeated()) {
+ const string* default_value;
if (is_prototype()) {
- new(field_ptr) const string*(&field->default_value_string());
+ default_value = &field->default_value_string();
} else {
- string* default_value =
- *reinterpret_cast<string* const*>(
+ default_value =
+ &(reinterpret_cast<const ArenaStringPtr*>(
type_info_->prototype->OffsetToPointer(
- type_info_->offsets[i]));
- new(field_ptr) string*(default_value);
+ type_info_->offsets[i]))->Get(NULL));
}
+ ArenaStringPtr* asp = new(field_ptr) ArenaStringPtr();
+ asp->UnsafeSetDefault(default_value);
} else {
new(field_ptr) RepeatedPtrField<string>();
}
@@ -390,9 +409,15 @@ DynamicMessage::~DynamicMessage() {
if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
switch (field->options().ctype()) {
default:
- case FieldOptions::STRING:
- delete *reinterpret_cast<string**>(field_ptr);
+ case FieldOptions::STRING: {
+ const ::std::string* default_value =
+ &(reinterpret_cast<const ArenaStringPtr*>(
+ type_info_->prototype->OffsetToPointer(
+ type_info_->offsets[i]))->Get(NULL));
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
+ NULL);
break;
+ }
}
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
delete *reinterpret_cast<Message**>(field_ptr);
@@ -440,10 +465,12 @@ DynamicMessage::~DynamicMessage() {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
- string* ptr = *reinterpret_cast<string**>(field_ptr);
- if (ptr != &field->default_value_string()) {
- delete ptr;
- }
+ const ::std::string* default_value =
+ &(reinterpret_cast<const ArenaStringPtr*>(
+ type_info_->prototype->OffsetToPointer(
+ type_info_->offsets[i]))->Get(NULL));
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
+ NULL);
break;
}
}
@@ -492,6 +519,16 @@ Message* DynamicMessage::New() const {
return new(new_base) DynamicMessage(type_info_);
}
+Message* DynamicMessage::New(::google::protobuf::Arena* arena) const {
+ if (arena != NULL) {
+ Message* message = New();
+ arena->Own(message);
+ return message;
+ } else {
+ return New();
+ }
+}
+
int DynamicMessage::GetCachedSize() const {
return cached_byte_size_;
}
@@ -672,7 +709,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
type_info->oneof_case_offset,
type_info->pool,
this,
- type_info->size));
+ type_info->size,
+ -1 /* arena_offset */));
} else {
type_info->reflection.reset(
new GeneratedMessageReflection(
@@ -684,7 +722,8 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
type_info->extensions_offset,
type_info->pool,
this,
- type_info->size));
+ type_info->size,
+ -1 /* arena_offset */));
}
// Cross link prototypes.
prototype->CrossLinkPrototypes();
@@ -723,12 +762,8 @@ void DynamicMessageFactory::ConstructDefaultOneofInstance(
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()));
- }
+ ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr();
+ asp->UnsafeSetDefault(&field->default_value_string());
break;
}
break;
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index 10ed7005..1e947e6d 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -39,6 +39,9 @@
#define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/message.h>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index a1c1661b..6353ecbf 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -226,5 +226,13 @@ TEST_F(DynamicMessageTest, SpaceUsed) {
EXPECT_LT(initial_space_used, message->SpaceUsed());
}
+TEST_F(DynamicMessageTest, Arena) {
+ Arena arena;
+ Message* message = prototype_->New(&arena);
+ (void)message; // avoid unused-variable error.
+ // Return without freeing: should not leak.
+}
+
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 274554b5..d6ebe4c3 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -174,12 +174,21 @@ void ExtensionSet::RegisterMessageExtension(const MessageLite* containing_type,
// ===================================================================
// Constructors and basic methods.
-ExtensionSet::ExtensionSet() {}
+ExtensionSet::ExtensionSet(::google::protobuf::Arena* arena) : arena_(arena) {
+ if (arena_ != NULL) {
+ arena_->OwnDestructor(&extensions_);
+ }
+}
+
+ExtensionSet::ExtensionSet() : arena_(NULL) {}
ExtensionSet::~ExtensionSet() {
- for (map<int, Extension>::iterator iter = extensions_.begin();
- iter != extensions_.end(); ++iter) {
- iter->second.Free();
+ // Deletes all allocated extensions.
+ if (arena_ == NULL) {
+ for (map<int, Extension>::iterator iter = extensions_.begin();
+ iter != extensions_.end(); ++iter) {
+ iter->second.Free();
+ }
}
}
@@ -301,7 +310,8 @@ void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_##UPPERCASE); \
extension->is_repeated = true; \
extension->is_packed = packed; \
- extension->repeated_##LOWERCASE##_value = new RepeatedField<LOWERCASE>(); \
+ extension->repeated_##LOWERCASE##_value = \
+ Arena::Create<RepeatedField<LOWERCASE> >(arena_, arena_); \
} else { \
GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \
GOOGLE_DCHECK_EQ(extension->is_packed, packed); \
@@ -345,34 +355,44 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type,
switch (WireFormatLite::FieldTypeToCppType(
static_cast<WireFormatLite::FieldType>(field_type))) {
case WireFormatLite::CPPTYPE_INT32:
- extension->repeated_int32_value = new RepeatedField<int32>();
+ extension->repeated_int32_value =
+ Arena::Create<RepeatedField<int32> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_INT64:
- extension->repeated_int64_value = new RepeatedField<int64>();
+ extension->repeated_int64_value =
+ Arena::Create<RepeatedField<int64> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_UINT32:
- extension->repeated_uint32_value = new RepeatedField<uint32>();
+ extension->repeated_uint32_value =
+ Arena::Create<RepeatedField<uint32> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_UINT64:
- extension->repeated_uint64_value = new RepeatedField<uint64>();
+ extension->repeated_uint64_value =
+ Arena::Create<RepeatedField<uint64> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_DOUBLE:
- extension->repeated_double_value = new RepeatedField<double>();
+ extension->repeated_double_value =
+ Arena::Create<RepeatedField<double> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_FLOAT:
- extension->repeated_float_value = new RepeatedField<float>();
+ extension->repeated_float_value =
+ Arena::Create<RepeatedField<float> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_BOOL:
- extension->repeated_bool_value = new RepeatedField<bool>();
+ extension->repeated_bool_value =
+ Arena::Create<RepeatedField<bool> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_ENUM:
- extension->repeated_enum_value = new RepeatedField<int>();
+ extension->repeated_enum_value =
+ Arena::Create<RepeatedField<int> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_STRING:
- extension->repeated_string_value = new RepeatedPtrField< ::std::string>();
+ extension->repeated_string_value =
+ Arena::Create<RepeatedPtrField< ::std::string> >(arena_, arena_);
break;
case WireFormatLite::CPPTYPE_MESSAGE:
- extension->repeated_message_value = new RepeatedPtrField<MessageLite>();
+ extension->repeated_message_value =
+ Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
break;
}
}
@@ -444,7 +464,8 @@ void ExtensionSet::AddEnum(int number, FieldType type,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_ENUM);
extension->is_repeated = true;
extension->is_packed = packed;
- extension->repeated_enum_value = new RepeatedField<int>();
+ extension->repeated_enum_value =
+ Arena::Create<RepeatedField<int> >(arena_, arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM);
GOOGLE_DCHECK_EQ(extension->is_packed, packed);
@@ -474,7 +495,7 @@ string* ExtensionSet::MutableString(int number, FieldType type,
extension->type = type;
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
extension->is_repeated = false;
- extension->string_value = new string;
+ extension->string_value = Arena::Create<string>(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, STRING);
}
@@ -504,7 +525,8 @@ string* ExtensionSet::AddString(int number, FieldType type,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_STRING);
extension->is_repeated = true;
extension->is_packed = false;
- extension->repeated_string_value = new RepeatedPtrField<string>();
+ extension->repeated_string_value =
+ Arena::Create<RepeatedPtrField<string> >(arena_, arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING);
}
@@ -544,7 +566,7 @@ MessageLite* ExtensionSet::MutableMessage(int number, FieldType type,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false;
extension->is_lazy = false;
- extension->message_value = prototype.New();
+ extension->message_value = prototype.New(arena_);
extension->is_cleared = false;
return extension->message_value;
} else {
@@ -576,14 +598,32 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = false;
extension->is_lazy = false;
- extension->message_value = message;
+ if (message->GetArena() == arena_) {
+ extension->message_value = message;
+ } else {
+ extension->message_value = message->New(arena_);
+ extension->message_value->CheckTypeAndMergeFrom(*message);
+ if (message->GetArena() == NULL) {
+ delete message;
+ }
+ }
} else {
GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
if (extension->is_lazy) {
extension->lazymessage_value->SetAllocatedMessage(message);
} else {
- delete extension->message_value;
- extension->message_value = message;
+ if (arena_ == NULL) {
+ delete extension->message_value;
+ }
+ if (message->GetArena() == arena_) {
+ extension->message_value = message;
+ } else {
+ extension->message_value = message->New(arena_);
+ extension->message_value->CheckTypeAndMergeFrom(*message);
+ if (message->GetArena() == NULL) {
+ delete message;
+ }
+ }
}
}
extension->is_cleared = false;
@@ -600,7 +640,39 @@ MessageLite* ExtensionSet::ReleaseMessage(int number,
MessageLite* ret = NULL;
if (iter->second.is_lazy) {
ret = iter->second.lazymessage_value->ReleaseMessage(prototype);
- delete iter->second.lazymessage_value;
+ if (arena_ == NULL) {
+ delete iter->second.lazymessage_value;
+ }
+ } else {
+ if (arena_ == NULL) {
+ ret = iter->second.message_value;
+ } else {
+ // ReleaseMessage() always returns a heap-allocated message, and we are
+ // on an arena, so we need to make a copy of this message to return.
+ ret = (iter->second.message_value)->New();
+ ret->CheckTypeAndMergeFrom(*iter->second.message_value);
+ }
+ }
+ extensions_.erase(number);
+ return ret;
+ }
+}
+
+MessageLite* ExtensionSet::UnsafeArenaReleaseMessage(
+ int number, const MessageLite& prototype) {
+ map<int, Extension>::iterator iter = extensions_.find(number);
+ if (iter == extensions_.end()) {
+ // Not present. Return NULL.
+ return NULL;
+ } else {
+ GOOGLE_DCHECK_TYPE(iter->second, OPTIONAL, MESSAGE);
+ MessageLite* ret = NULL;
+ if (iter->second.is_lazy) {
+ ret =
+ iter->second.lazymessage_value->UnsafeArenaReleaseMessage(prototype);
+ if (arena_ == NULL) {
+ delete iter->second.lazymessage_value;
+ }
} else {
ret = iter->second.message_value;
}
@@ -637,7 +709,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
extension->is_repeated = true;
extension->repeated_message_value =
- new RepeatedPtrField<MessageLite>();
+ Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
@@ -647,7 +719,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type,
MessageLite* result = extension->repeated_message_value
->AddFromCleared<GenericTypeHandler<MessageLite> >();
if (result == NULL) {
- result = prototype.New();
+ result = prototype.New(arena_);
extension->repeated_message_value->AddAllocated(result);
}
return result;
@@ -765,138 +837,142 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
for (map<int, Extension>::const_iterator iter = other.extensions_.begin();
iter != other.extensions_.end(); ++iter) {
const Extension& other_extension = iter->second;
+ InternalExtensionMergeFrom(iter->first, other_extension);
+ }
+}
- if (other_extension.is_repeated) {
- Extension* extension;
- bool is_new = MaybeNewExtension(iter->first, other_extension.descriptor,
- &extension);
- if (is_new) {
- // Extension did not already exist in set.
- extension->type = other_extension.type;
- extension->is_packed = other_extension.is_packed;
- extension->is_repeated = true;
- } else {
- GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
- GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed);
- GOOGLE_DCHECK(extension->is_repeated);
- }
+void ExtensionSet::InternalExtensionMergeFrom(
+ int number, const Extension& other_extension) {
+ if (other_extension.is_repeated) {
+ Extension* extension;
+ bool is_new = MaybeNewExtension(number, other_extension.descriptor,
+ &extension);
+ if (is_new) {
+ // Extension did not already exist in set.
+ extension->type = other_extension.type;
+ extension->is_packed = other_extension.is_packed;
+ extension->is_repeated = true;
+ } else {
+ GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+ GOOGLE_DCHECK_EQ(extension->is_packed, other_extension.is_packed);
+ GOOGLE_DCHECK(extension->is_repeated);
+ }
- switch (cpp_type(other_extension.type)) {
-#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \
- case WireFormatLite::CPPTYPE_##UPPERCASE: \
- if (is_new) { \
- extension->repeated_##LOWERCASE##_value = \
- new REPEATED_TYPE; \
- } \
- extension->repeated_##LOWERCASE##_value->MergeFrom( \
- *other_extension.repeated_##LOWERCASE##_value); \
- break;
+ switch (cpp_type(other_extension.type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE, REPEATED_TYPE) \
+ case WireFormatLite::CPPTYPE_##UPPERCASE: \
+ if (is_new) { \
+ extension->repeated_##LOWERCASE##_value = \
+ Arena::Create<REPEATED_TYPE >(arena_, arena_); \
+ } \
+ extension->repeated_##LOWERCASE##_value->MergeFrom( \
+ *other_extension.repeated_##LOWERCASE##_value); \
+ break;
- HANDLE_TYPE( INT32, int32, RepeatedField < int32>);
- HANDLE_TYPE( INT64, int64, RepeatedField < int64>);
- HANDLE_TYPE( UINT32, uint32, RepeatedField < uint32>);
- HANDLE_TYPE( UINT64, uint64, RepeatedField < uint64>);
- HANDLE_TYPE( FLOAT, float, RepeatedField < float>);
- HANDLE_TYPE( DOUBLE, double, RepeatedField < double>);
- HANDLE_TYPE( BOOL, bool, RepeatedField < bool>);
- HANDLE_TYPE( ENUM, enum, RepeatedField < int>);
- HANDLE_TYPE( STRING, string, RepeatedPtrField< string>);
+ HANDLE_TYPE( INT32, int32, RepeatedField < int32>);
+ HANDLE_TYPE( INT64, int64, RepeatedField < int64>);
+ HANDLE_TYPE( UINT32, uint32, RepeatedField < uint32>);
+ HANDLE_TYPE( UINT64, uint64, RepeatedField < uint64>);
+ HANDLE_TYPE( FLOAT, float, RepeatedField < float>);
+ HANDLE_TYPE( DOUBLE, double, RepeatedField < double>);
+ HANDLE_TYPE( BOOL, bool, RepeatedField < bool>);
+ HANDLE_TYPE( ENUM, enum, RepeatedField < int>);
+ HANDLE_TYPE( STRING, string, RepeatedPtrField< string>);
#undef HANDLE_TYPE
- case WireFormatLite::CPPTYPE_MESSAGE:
- if (is_new) {
- extension->repeated_message_value =
- new RepeatedPtrField<MessageLite>();
- }
- // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
- // it would attempt to allocate new objects.
- RepeatedPtrField<MessageLite>* other_repeated_message =
- other_extension.repeated_message_value;
- for (int i = 0; i < other_repeated_message->size(); i++) {
- const MessageLite& other_message = other_repeated_message->Get(i);
- MessageLite* target = extension->repeated_message_value
- ->AddFromCleared<GenericTypeHandler<MessageLite> >();
- if (target == NULL) {
- target = other_message.New();
- extension->repeated_message_value->AddAllocated(target);
- }
- target->CheckTypeAndMergeFrom(other_message);
+ case WireFormatLite::CPPTYPE_MESSAGE:
+ if (is_new) {
+ extension->repeated_message_value =
+ Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ }
+ // We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
+ // it would attempt to allocate new objects.
+ RepeatedPtrField<MessageLite>* other_repeated_message =
+ other_extension.repeated_message_value;
+ for (int i = 0; i < other_repeated_message->size(); i++) {
+ const MessageLite& other_message = other_repeated_message->Get(i);
+ MessageLite* target = extension->repeated_message_value
+ ->AddFromCleared<GenericTypeHandler<MessageLite> >();
+ if (target == NULL) {
+ target = other_message.New(arena_);
+ extension->repeated_message_value->AddAllocated(target);
}
+ target->CheckTypeAndMergeFrom(other_message);
+ }
+ break;
+ }
+ } else {
+ if (!other_extension.is_cleared) {
+ switch (cpp_type(other_extension.type)) {
+#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
+ case WireFormatLite::CPPTYPE_##UPPERCASE: \
+ Set##CAMELCASE(number, other_extension.type, \
+ other_extension.LOWERCASE##_value, \
+ other_extension.descriptor); \
break;
- }
- } else {
- if (!other_extension.is_cleared) {
- switch (cpp_type(other_extension.type)) {
-#define HANDLE_TYPE(UPPERCASE, LOWERCASE, CAMELCASE) \
- case WireFormatLite::CPPTYPE_##UPPERCASE: \
- Set##CAMELCASE(iter->first, other_extension.type, \
- other_extension.LOWERCASE##_value, \
- other_extension.descriptor); \
- break;
-
- HANDLE_TYPE( INT32, int32, Int32);
- HANDLE_TYPE( INT64, int64, Int64);
- HANDLE_TYPE(UINT32, uint32, UInt32);
- HANDLE_TYPE(UINT64, uint64, UInt64);
- HANDLE_TYPE( FLOAT, float, Float);
- HANDLE_TYPE(DOUBLE, double, Double);
- HANDLE_TYPE( BOOL, bool, Bool);
- HANDLE_TYPE( ENUM, enum, Enum);
+
+ HANDLE_TYPE( INT32, int32, Int32);
+ HANDLE_TYPE( INT64, int64, Int64);
+ HANDLE_TYPE(UINT32, uint32, UInt32);
+ HANDLE_TYPE(UINT64, uint64, UInt64);
+ HANDLE_TYPE( FLOAT, float, Float);
+ HANDLE_TYPE(DOUBLE, double, Double);
+ HANDLE_TYPE( BOOL, bool, Bool);
+ HANDLE_TYPE( ENUM, enum, Enum);
#undef HANDLE_TYPE
- case WireFormatLite::CPPTYPE_STRING:
- SetString(iter->first, other_extension.type,
- *other_extension.string_value,
- other_extension.descriptor);
- break;
- case WireFormatLite::CPPTYPE_MESSAGE: {
- Extension* extension;
- bool is_new = MaybeNewExtension(iter->first,
- other_extension.descriptor,
- &extension);
- if (is_new) {
- extension->type = other_extension.type;
- extension->is_packed = other_extension.is_packed;
- extension->is_repeated = false;
- if (other_extension.is_lazy) {
- extension->is_lazy = true;
- extension->lazymessage_value =
- other_extension.lazymessage_value->New();
+ case WireFormatLite::CPPTYPE_STRING:
+ SetString(number, other_extension.type,
+ *other_extension.string_value,
+ other_extension.descriptor);
+ break;
+ case WireFormatLite::CPPTYPE_MESSAGE: {
+ Extension* extension;
+ bool is_new = MaybeNewExtension(number,
+ other_extension.descriptor,
+ &extension);
+ if (is_new) {
+ extension->type = other_extension.type;
+ extension->is_packed = other_extension.is_packed;
+ extension->is_repeated = false;
+ if (other_extension.is_lazy) {
+ extension->is_lazy = true;
+ extension->lazymessage_value =
+ other_extension.lazymessage_value->New(arena_);
+ extension->lazymessage_value->MergeFrom(
+ *other_extension.lazymessage_value);
+ } else {
+ extension->is_lazy = false;
+ extension->message_value =
+ other_extension.message_value->New(arena_);
+ extension->message_value->CheckTypeAndMergeFrom(
+ *other_extension.message_value);
+ }
+ } else {
+ GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
+ GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed);
+ GOOGLE_DCHECK(!extension->is_repeated);
+ if (other_extension.is_lazy) {
+ if (extension->is_lazy) {
extension->lazymessage_value->MergeFrom(
*other_extension.lazymessage_value);
} else {
- extension->is_lazy = false;
- extension->message_value =
- other_extension.message_value->New();
extension->message_value->CheckTypeAndMergeFrom(
- *other_extension.message_value);
+ other_extension.lazymessage_value->GetMessage(
+ *extension->message_value));
}
} else {
- GOOGLE_DCHECK_EQ(extension->type, other_extension.type);
- GOOGLE_DCHECK_EQ(extension->is_packed,other_extension.is_packed);
- GOOGLE_DCHECK(!extension->is_repeated);
- if (other_extension.is_lazy) {
- if (extension->is_lazy) {
- extension->lazymessage_value->MergeFrom(
- *other_extension.lazymessage_value);
- } else {
- extension->message_value->CheckTypeAndMergeFrom(
- other_extension.lazymessage_value->GetMessage(
- *extension->message_value));
- }
+ if (extension->is_lazy) {
+ extension->lazymessage_value->MutableMessage(
+ *other_extension.message_value)->CheckTypeAndMergeFrom(
+ *other_extension.message_value);
} else {
- if (extension->is_lazy) {
- extension->lazymessage_value->MutableMessage(
- *other_extension.message_value)->CheckTypeAndMergeFrom(
- *other_extension.message_value);
- } else {
- extension->message_value->CheckTypeAndMergeFrom(
- *other_extension.message_value);
- }
+ extension->message_value->CheckTypeAndMergeFrom(
+ *other_extension.message_value);
}
}
- extension->is_cleared = false;
- break;
}
+ extension->is_cleared = false;
+ break;
}
}
}
@@ -904,7 +980,19 @@ void ExtensionSet::MergeFrom(const ExtensionSet& other) {
}
void ExtensionSet::Swap(ExtensionSet* x) {
- extensions_.swap(x->extensions_);
+ if (GetArenaNoVirtual() == x->GetArenaNoVirtual()) {
+ extensions_.swap(x->extensions_);
+ } else {
+ // TODO(cfallin, rohananil): We maybe able to optimize a case where we are
+ // swapping from heap to arena-allocated extension set, by just Own()'ing
+ // the extensions.
+ ExtensionSet extension_set;
+ extension_set.MergeFrom(*x);
+ x->Clear();
+ x->MergeFrom(*this);
+ Clear();
+ MergeFrom(extension_set);
+ }
}
void ExtensionSet::SwapExtension(ExtensionSet* other,
@@ -920,18 +1008,42 @@ void ExtensionSet::SwapExtension(ExtensionSet* other,
if (this_iter != extensions_.end() &&
other_iter != other->extensions_.end()) {
- std::swap(this_iter->second, other_iter->second);
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ using std::swap;
+ swap(this_iter->second, other_iter->second);
+ } else {
+ // TODO(cfallin, rohananil): We could further optimize these cases,
+ // especially avoid creation of ExtensionSet, and move MergeFrom logic
+ // into Extensions itself (which takes arena as an argument).
+ // We do it this way to reuse the copy-across-arenas logic already
+ // implemented in ExtensionSet's MergeFrom.
+ ExtensionSet temp;
+ temp.InternalExtensionMergeFrom(number, other_iter->second);
+ map<int, Extension>::iterator temp_iter = temp.extensions_.find(number);
+ other_iter->second.Clear();
+ other->InternalExtensionMergeFrom(number, this_iter->second);
+ this_iter->second.Clear();
+ InternalExtensionMergeFrom(number, temp_iter->second);
+ }
return;
}
if (this_iter == extensions_.end()) {
- extensions_.insert(make_pair(number, other_iter->second));
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ extensions_.insert(make_pair(number, other_iter->second));
+ } else {
+ InternalExtensionMergeFrom(number, other_iter->second);
+ }
other->extensions_.erase(number);
return;
}
if (other_iter == other->extensions_.end()) {
- other->extensions_.insert(make_pair(number, this_iter->second));
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ other->extensions_.insert(make_pair(number, this_iter->second));
+ } else {
+ other->InternalExtensionMergeFrom(number, this_iter->second);
+ }
extensions_.erase(number);
return;
}
@@ -1223,7 +1335,7 @@ bool ExtensionSet::MaybeNewExtension(int number,
const FieldDescriptor* descriptor,
Extension** result) {
pair<map<int, Extension>::iterator, bool> insert_result =
- extensions_.insert(make_pair(number, Extension()));
+ extensions_.insert(make_pair(number, Extension()));
*result = &insert_result.first->second;
(*result)->descriptor = descriptor;
return insert_result.second;
@@ -1554,6 +1666,8 @@ int ExtensionSet::Extension::GetSize() const {
return 0;
}
+// This function deletes all allocated objects. This function should be only
+// called if the Extension was created with an arena.
void ExtensionSet::Extension::Free() {
if (is_repeated) {
switch (cpp_type(type)) {
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index d6fc45df..6d6702b3 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -51,6 +51,7 @@
namespace google {
namespace protobuf {
+ class Arena;
class Descriptor; // descriptor.h
class FieldDescriptor; // descriptor.h
class DescriptorPool; // descriptor.h
@@ -157,6 +158,7 @@ class MessageSetFieldSkipper;
class LIBPROTOBUF_EXPORT ExtensionSet {
public:
ExtensionSet();
+ explicit ExtensionSet(::google::protobuf::Arena* arena);
~ExtensionSet();
// These are called at startup by protocol-compiler-generated code to
@@ -261,9 +263,13 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const FieldDescriptor* descriptor,
MessageLite* message);
MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
+ MessageLite* UnsafeArenaReleaseMessage(
+ int number, const MessageLite& prototype);
+
MessageLite* ReleaseMessage(const FieldDescriptor* descriptor,
MessageFactory* factory);
#undef desc
+ ::google::protobuf::Arena* GetArenaNoVirtual() const { return arena_; }
// repeated fields -------------------------------------------------
@@ -421,12 +427,14 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
LazyMessageExtension() {}
virtual ~LazyMessageExtension() {}
- virtual LazyMessageExtension* New() const = 0;
+ virtual LazyMessageExtension* New(::google::protobuf::Arena* arena) const = 0;
virtual const MessageLite& GetMessage(
const MessageLite& prototype) const = 0;
virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
virtual void SetAllocatedMessage(MessageLite *message) = 0;
virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
+ virtual MessageLite* UnsafeArenaReleaseMessage(
+ const MessageLite& prototype) = 0;
virtual bool IsInitialized() const = 0;
virtual int ByteSize() const = 0;
@@ -524,6 +532,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
};
+ // Merges existing Extension from other_extension
+ void InternalExtensionMergeFrom(int number, const Extension& other_extension);
+
// 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
@@ -569,7 +580,6 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
ExtensionFinder* extension_finder,
MessageSetFieldSkipper* field_skipper);
-
// Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This
// friendship should automatically extend to ExtensionSet::Extension, but
// unfortunately some older compilers (e.g. GCC 3.4.4) do not implement this
@@ -587,7 +597,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// for 100 elements or more. Also, we want AppendToList() to order fields
// by field number.
std::map<int, Extension> extensions_;
-
+ ::google::protobuf::Arena* arena_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
};
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index eae4d574..5f4ca1c3 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -169,7 +169,7 @@ MessageLite* ExtensionSet::MutableMessage(const FieldDescriptor* descriptor,
const MessageLite* prototype =
factory->GetPrototype(descriptor->message_type());
extension->is_lazy = false;
- extension->message_value = prototype->New();
+ extension->message_value = prototype->New(arena_);
extension->is_cleared = false;
return extension->message_value;
} else {
@@ -196,9 +196,16 @@ MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
if (iter->second.is_lazy) {
ret = iter->second.lazymessage_value->ReleaseMessage(
*factory->GetPrototype(descriptor->message_type()));
- delete iter->second.lazymessage_value;
+ if (arena_ == NULL) {
+ delete iter->second.lazymessage_value;
+ }
} else {
- ret = iter->second.message_value;
+ if (arena_ != NULL) {
+ ret = (iter->second.message_value)->New();
+ ret->CheckTypeAndMergeFrom(*(iter->second.message_value));
+ } else {
+ ret = iter->second.message_value;
+ }
}
extensions_.erase(descriptor->number());
return ret;
@@ -213,7 +220,7 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE);
extension->is_repeated = true;
extension->repeated_message_value =
- new RepeatedPtrField<MessageLite>();
+ ::google::protobuf::Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
@@ -230,7 +237,7 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
} else {
prototype = &extension->repeated_message_value->Get(0);
}
- result = prototype->New();
+ result = prototype->New(arena_);
extension->repeated_message_value->AddAllocated(result);
}
return result;
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 8a00bafd..b9d07353 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/unittest_mset.pb.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/arena.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/wire_format.h>
@@ -319,6 +320,117 @@ TEST(ExtensionSetTest, SwapExtensionBothFull) {
TestUtil::ExpectAllExtensionsSet(message2);
}
+TEST(ExtensionSetTest, ArenaSetAllExtension) {
+ ::google::protobuf::Arena arena1;
+ unittest::TestAllExtensions* message1 =
+ ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+ TestUtil::SetAllExtensions(message1);
+ TestUtil::ExpectAllExtensionsSet(*message1);
+}
+
+TEST(ExtensionSetTest, ArenaCopyConstructor) {
+ ::google::protobuf::Arena arena1;
+ unittest::TestAllExtensions* message1 =
+ ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+ TestUtil::SetAllExtensions(message1);
+ unittest::TestAllExtensions message2(*message1);
+ arena1.Reset();
+ TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensionSetTest, ArenaMergeFrom) {
+ ::google::protobuf::Arena arena1;
+ unittest::TestAllExtensions* message1 =
+ ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+ TestUtil::SetAllExtensions(message1);
+ unittest::TestAllExtensions message2;
+ message2.MergeFrom(*message1);
+ arena1.Reset();
+ TestUtil::ExpectAllExtensionsSet(message2);
+}
+
+TEST(ExtensionSetTest, ArenaSetAllocatedMessageAndRelease) {
+ ::google::protobuf::Arena arena;
+ unittest::TestAllExtensions* message =
+ ::google::protobuf::Arena::CreateMessage<unittest::TestAllExtensions>(&arena);
+ EXPECT_FALSE(message->HasExtension(
+ unittest::optional_foreign_message_extension));
+ // Add a extension using SetAllocatedExtension
+ unittest::ForeignMessage* foreign_message = new unittest::ForeignMessage();
+ message->SetAllocatedExtension(unittest::optional_foreign_message_extension,
+ foreign_message);
+ // foreign_message is copied underneath, as foreign_message is on heap
+ // and extension_set is on an arena.
+ EXPECT_NE(foreign_message,
+ message->MutableExtension(
+ unittest::optional_foreign_message_extension));
+
+ // Underlying message is copied, and returned.
+ unittest::ForeignMessage* released_message = message->ReleaseExtension(
+ unittest::optional_foreign_message_extension);
+ delete released_message;
+ EXPECT_FALSE(message->HasExtension(
+ unittest::optional_foreign_message_extension));
+}
+
+TEST(ExtensionSetTest, SwapExtensionBothFullWithArena) {
+ ::google::protobuf::Arena arena1;
+ scoped_ptr<google::protobuf::Arena> arena2(new ::google::protobuf::Arena());
+
+ unittest::TestAllExtensions* message1 =
+ Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+ unittest::TestAllExtensions* message2 =
+ Arena::CreateMessage<unittest::TestAllExtensions>(arena2.get());
+
+ TestUtil::SetAllExtensions(message1);
+ TestUtil::SetAllExtensions(message2);
+ message1->SetExtension(unittest::optional_int32_extension, 1);
+ message2->SetExtension(unittest::optional_int32_extension, 2);
+ message1->Swap(message2);
+ EXPECT_EQ(2, message1->GetExtension(unittest::optional_int32_extension));
+ EXPECT_EQ(1, message2->GetExtension(unittest::optional_int32_extension));
+ // Re-set the original values so ExpectAllExtensionsSet is happy.
+ message1->SetExtension(unittest::optional_int32_extension, 101);
+ message2->SetExtension(unittest::optional_int32_extension, 101);
+ TestUtil::ExpectAllExtensionsSet(*message1);
+ TestUtil::ExpectAllExtensionsSet(*message2);
+ arena2.reset(NULL);
+ TestUtil::ExpectAllExtensionsSet(*message1);
+ // Test corner cases, when one is empty and other is not.
+ ::google::protobuf::Arena arena3, arena4;
+
+ unittest::TestAllExtensions* message3 =
+ Arena::CreateMessage<unittest::TestAllExtensions>(&arena3);
+ unittest::TestAllExtensions* message4 =
+ Arena::CreateMessage<unittest::TestAllExtensions>(&arena4);
+ TestUtil::SetAllExtensions(message3);
+ message3->Swap(message4);
+ arena3.Reset();
+ TestUtil::ExpectAllExtensionsSet(*message4);
+}
+
+TEST(ExtensionSetTest, SwapFieldsOfExtensionBothFullWithArena) {
+ google::protobuf::Arena arena1;
+ google::protobuf::Arena* arena2 = new ::google::protobuf::Arena();
+
+ unittest::TestAllExtensions* message1 =
+ Arena::CreateMessage<unittest::TestAllExtensions>(&arena1);
+ unittest::TestAllExtensions* message2 =
+ Arena::CreateMessage<unittest::TestAllExtensions>(arena2);
+
+ 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);
+ delete arena2;
+ TestUtil::ExpectAllExtensionsSet(*message1);
+}
+
TEST(ExtensionSetTest, SwapExtensionWithSelf) {
unittest::TestAllExtensions message1;
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 536de7d9..ea97aebc 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -74,6 +74,19 @@ const string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
return (d == NULL ? GetEmptyString() : d->name());
}
+namespace {
+inline bool SupportsArenas(const Descriptor* descriptor) {
+ // In open-source release we enable arena support by default but as we also
+ // down-integrate descriptor.pb.(h|cc) from our internal code base which
+ // hasn't enabled arena support yet, here we need to be able to handle both
+ // cases for descriptor protos.
+ if (!Arena::is_arena_constructable<FileDescriptorProto>::type::value) {
+ return descriptor->name() != "google/protobuf/descriptor.proto";
+ }
+ return true;
+}
+} // anonymous namespace
+
// ===================================================================
// Helpers for reporting usage errors (e.g. trying to use GetInt32() on
// a string field).
@@ -177,13 +190,15 @@ GeneratedMessageReflection::GeneratedMessageReflection(
int extensions_offset,
const DescriptorPool* descriptor_pool,
MessageFactory* factory,
- int object_size)
+ int object_size,
+ int arena_offset)
: descriptor_ (descriptor),
default_instance_ (default_instance),
offsets_ (offsets),
has_bits_offset_ (has_bits_offset),
unknown_fields_offset_(unknown_fields_offset),
extensions_offset_(extensions_offset),
+ arena_offset_ (arena_offset),
object_size_ (object_size),
descriptor_pool_ ((descriptor_pool == NULL) ?
DescriptorPool::generated_pool() :
@@ -202,7 +217,8 @@ GeneratedMessageReflection::GeneratedMessageReflection(
int oneof_case_offset,
const DescriptorPool* descriptor_pool,
MessageFactory* factory,
- int object_size)
+ int object_size,
+ int arena_offset)
: descriptor_ (descriptor),
default_instance_ (default_instance),
default_oneof_instance_ (default_oneof_instance),
@@ -211,6 +227,7 @@ GeneratedMessageReflection::GeneratedMessageReflection(
oneof_case_offset_(oneof_case_offset),
unknown_fields_offset_(unknown_fields_offset),
extensions_offset_(extensions_offset),
+ arena_offset_ (arena_offset),
object_size_ (object_size),
descriptor_pool_ ((descriptor_pool == NULL) ?
DescriptorPool::generated_pool() :
@@ -220,14 +237,39 @@ GeneratedMessageReflection::GeneratedMessageReflection(
GeneratedMessageReflection::~GeneratedMessageReflection() {}
+namespace {
+UnknownFieldSet* empty_unknown_field_set_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
+
+void InitEmptyUnknownFieldSet() {
+ empty_unknown_field_set_ = new UnknownFieldSet;
+}
+
+const UnknownFieldSet& GetEmptyUnknownFieldSet() {
+ ::google::protobuf::GoogleOnceInit(&empty_unknown_field_set_once_, &InitEmptyUnknownFieldSet);
+ return *empty_unknown_field_set_;
+}
+} // namespace
+
const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
const Message& message) const {
+ if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ return GetEmptyUnknownFieldSet();
+ }
+ if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+ return GetInternalMetadataWithArena(message).unknown_fields();
+ }
const void* ptr = reinterpret_cast<const uint8*>(&message) +
unknown_fields_offset_;
return *reinterpret_cast<const UnknownFieldSet*>(ptr);
}
+
UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields(
Message* message) const {
+ if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+ return MutableInternalMetadataWithArena(message)->
+ mutable_unknown_fields();
+ }
void* ptr = reinterpret_cast<uint8*>(message) + unknown_fields_offset_;
return reinterpret_cast<UnknownFieldSet*>(ptr);
}
@@ -303,12 +345,13 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
- const string* ptr = GetField<const string*>(message, field);
-
// Initially, the string points to the default value stored in
// the prototype. Only count the string if it has been changed
// from the default value.
- const string* default_ptr = DefaultRaw<const string*>(field);
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ const string* ptr =
+ &GetField<ArenaStringPtr>(message, field).Get(default_ptr);
if (ptr != default_ptr) {
// string fields are represented by just a pointer, so also
@@ -363,8 +406,9 @@ void GeneratedMessageReflection::SwapField(
case FieldDescriptor::CPPTYPE_STRING:
case FieldDescriptor::CPPTYPE_MESSAGE:
- MutableRaw<RepeatedPtrFieldBase>(message1, field)->Swap(
- MutableRaw<RepeatedPtrFieldBase>(message2, field));
+ MutableRaw<RepeatedPtrFieldBase>(message1, field)->
+ Swap<GenericTypeHandler<google::protobuf::Message> >(
+ MutableRaw<RepeatedPtrFieldBase>(message2, field));
break;
default:
@@ -396,8 +440,8 @@ void GeneratedMessageReflection::SwapField(
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING:
- std::swap(*MutableRaw<string*>(message1, field),
- *MutableRaw<string*>(message2, field));
+ MutableRaw<ArenaStringPtr>(message1, field)->Swap(
+ MutableRaw<ArenaStringPtr>(message2, field));
break;
}
break;
@@ -549,12 +593,29 @@ void GeneratedMessageReflection::Swap(
<< "\"). Note that the exact same class is required; not just the same "
"descriptor.";
- uint32* has_bits1 = MutableHasBits(message1);
- uint32* has_bits2 = MutableHasBits(message2);
- int has_bits_size = (descriptor_->field_count() + 31) / 32;
+ // Check that both messages are in the same arena (or both on the heap). We
+ // need to copy all data if not, due to ownership semantics.
+ if (GetArena(message1) != GetArena(message2)) {
+ // Slow copy path.
+ // Use our arena as temp space, if available.
+ Message* temp = message1->New(GetArena(message1));
+ temp->MergeFrom(*message1);
+ message1->CopyFrom(*message2);
+ message2->CopyFrom(*temp);
+ if (GetArena(message1) == NULL) {
+ delete temp;
+ }
+ return;
+ }
+
+ if (has_bits_offset_ != -1) {
+ uint32* has_bits1 = MutableHasBits(message1);
+ uint32* has_bits2 = MutableHasBits(message2);
+ int has_bits_size = (descriptor_->field_count() + 31) / 32;
- for (int i = 0; i < has_bits_size; i++) {
- std::swap(has_bits1[i], has_bits2[i]);
+ for (int i = 0; i < has_bits_size; i++) {
+ std::swap(has_bits1[i], has_bits2[i]);
+ }
}
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -715,17 +776,13 @@ void GeneratedMessageReflection::ClearField(
case FieldDescriptor::CPPTYPE_STRING: {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- const string* default_ptr = DefaultRaw<const string*>(field);
- string** value = MutableRaw<string*>(message, field);
- if (*value != default_ptr) {
- if (field->has_default_value()) {
- (*value)->assign(field->default_value_string());
- } else {
- (*value)->clear();
- }
- }
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ MutableRaw<ArenaStringPtr>(message, field)->Destroy(default_ptr,
+ GetArena(message));
break;
+ }
}
break;
}
@@ -994,8 +1051,11 @@ string GeneratedMessageReflection::GetString(
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- return *GetField<const string*>(message, field);
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
+ }
}
GOOGLE_LOG(FATAL) << "Can't get here.";
@@ -1013,8 +1073,11 @@ const string& GeneratedMessageReflection::GetStringReference(
} else {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- return *GetField<const string*>(message, field);
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ return GetField<ArenaStringPtr>(message, field).Get(default_ptr);
+ }
}
GOOGLE_LOG(FATAL) << "Can't get here.";
@@ -1034,16 +1097,15 @@ void GeneratedMessageReflection::SetString(
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
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);
- } else {
- (*ptr)->assign(value);
+ MutableField<ArenaStringPtr>(message, field)->UnsafeSetDefault(
+ default_ptr);
}
+ MutableField<ArenaStringPtr>(message, field)->Set(default_ptr,
+ value, GetArena(message));
break;
}
}
@@ -1125,42 +1187,80 @@ void GeneratedMessageReflection::AddString(
// -------------------------------------------------------------------
+inline bool CreateUnknownEnumValues(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
const Message& message, const FieldDescriptor* field) const {
- USAGE_CHECK_ALL(GetEnum, SINGULAR, ENUM);
+ // Usage checked by GetEnumValue.
+ int value = GetEnumValue(message, field);
+ return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
+}
+
+int GeneratedMessageReflection::GetEnumValue(
+ const Message& message, const FieldDescriptor* field) const {
+ USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM);
- int value;
+ int32 value;
if (field->is_extension()) {
value = GetExtensionSet(message).GetEnum(
field->number(), field->default_value_enum()->number());
} else {
value = GetField<int>(message, field);
}
- const EnumValueDescriptor* result =
- field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
- << field->full_name() << " of type "
- << field->enum_type()->full_name() << ".";
- return result;
+ return value;
}
void GeneratedMessageReflection::SetEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
- USAGE_CHECK_ALL(SetEnum, SINGULAR, ENUM);
+ // Usage checked by SetEnumValue.
USAGE_CHECK_ENUM_VALUE(SetEnum);
+ SetEnumValueInternal(message, field, value->number());
+}
+
+void GeneratedMessageReflection::SetEnumValue(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
+ USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM);
+ if (!CreateUnknownEnumValues(descriptor_->file())) {
+ // Check that the value is valid if we don't support direct storage of
+ // unknown enum values.
+ const EnumValueDescriptor* value_desc =
+ field->enum_type()->FindValueByNumber(value);
+ if (value_desc == NULL) {
+ GOOGLE_LOG(DFATAL) << "SetEnumValue accepts only valid integer values: value "
+ << value << " unexpected for field " << field->full_name();
+ // In production builds, DFATAL will not terminate the program, so we have
+ // to do something reasonable: just set the default value.
+ value = field->default_value_enum()->number();
+ }
+ }
+ SetEnumValueInternal(message, field, value);
+}
+void GeneratedMessageReflection::SetEnumValueInternal(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
if (field->is_extension()) {
MutableExtensionSet(message)->SetEnum(field->number(), field->type(),
- value->number(), field);
+ value, field);
} else {
- SetField<int>(message, field, value->number());
+ SetField<int>(message, field, value);
}
}
const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
const Message& message, const FieldDescriptor* field, int index) const {
- USAGE_CHECK_ALL(GetRepeatedEnum, REPEATED, ENUM);
+ // Usage checked by GetRepeatedEnumValue.
+ int value = GetRepeatedEnumValue(message, field, index);
+ return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
+}
+
+int GeneratedMessageReflection::GetRepeatedEnumValue(
+ const Message& message, const FieldDescriptor* field, int index) const {
+ USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM);
int value;
if (field->is_extension()) {
@@ -1168,41 +1268,89 @@ const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
} else {
value = GetRepeatedField<int>(message, field, index);
}
- const EnumValueDescriptor* result =
- field->enum_type()->FindValueByNumber(value);
- GOOGLE_CHECK(result != NULL) << "Value " << value << " is not valid for field "
- << field->full_name() << " of type "
- << field->enum_type()->full_name() << ".";
- return result;
+ return value;
}
void GeneratedMessageReflection::SetRepeatedEnum(
Message* message,
const FieldDescriptor* field, int index,
const EnumValueDescriptor* value) const {
- USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
+ // Usage checked by SetRepeatedEnumValue.
USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
+ SetRepeatedEnumValueInternal(message, field, index, value->number());
+}
+void GeneratedMessageReflection::SetRepeatedEnumValue(
+ Message* message,
+ const FieldDescriptor* field, int index,
+ int value) const {
+ USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
+ if (!CreateUnknownEnumValues(descriptor_->file())) {
+ // Check that the value is valid if we don't support direct storage of
+ // unknown enum values.
+ const EnumValueDescriptor* value_desc =
+ field->enum_type()->FindValueByNumber(value);
+ if (value_desc == NULL) {
+ GOOGLE_LOG(DFATAL) << "SetRepeatedEnumValue accepts only valid integer values: "
+ << "value " << value << " unexpected for field "
+ << field->full_name();
+ // In production builds, DFATAL will not terminate the program, so we have
+ // to do something reasonable: just set the default value.
+ value = field->default_value_enum()->number();
+ }
+ }
+ SetRepeatedEnumValueInternal(message, field, index, value);
+}
+
+void GeneratedMessageReflection::SetRepeatedEnumValueInternal(
+ Message* message,
+ const FieldDescriptor* field, int index,
+ int value) const {
if (field->is_extension()) {
MutableExtensionSet(message)->SetRepeatedEnum(
- field->number(), index, value->number());
+ field->number(), index, value);
} else {
- SetRepeatedField<int>(message, field, index, value->number());
+ SetRepeatedField<int>(message, field, index, value);
}
}
void GeneratedMessageReflection::AddEnum(
Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const {
- USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
+ // Usage checked by AddEnumValue.
USAGE_CHECK_ENUM_VALUE(AddEnum);
+ AddEnumValueInternal(message, field, value->number());
+}
+void GeneratedMessageReflection::AddEnumValue(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
+ USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
+ if (!CreateUnknownEnumValues(descriptor_->file())) {
+ // Check that the value is valid if we don't support direct storage of
+ // unknown enum values.
+ const EnumValueDescriptor* value_desc =
+ field->enum_type()->FindValueByNumber(value);
+ if (value_desc == NULL) {
+ GOOGLE_LOG(DFATAL) << "AddEnumValue accepts only valid integer values: value "
+ << value << " unexpected for field " << field->full_name();
+ // In production builds, DFATAL will not terminate the program, so we have
+ // to do something reasonable: just set the default value.
+ value = field->default_value_enum()->number();
+ }
+ }
+ AddEnumValueInternal(message, field, value);
+}
+
+void GeneratedMessageReflection::AddEnumValueInternal(
+ Message* message, const FieldDescriptor* field,
+ int value) const {
if (field->is_extension()) {
MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
field->options().packed(),
- value->number(), field);
+ value, field);
} else {
- AddField<int>(message, field, value->number());
+ AddField<int>(message, field, value);
}
}
@@ -1246,7 +1394,7 @@ Message* GeneratedMessageReflection::MutableMessage(
ClearOneof(message, field->containing_oneof());
result_holder = MutableField<Message*>(message, field);
const Message* default_message = DefaultRaw<const Message*>(field);
- *result_holder = default_message->New();
+ *result_holder = default_message->New(message->GetArena());
}
} else {
SetBit(message, field);
@@ -1254,14 +1402,14 @@ Message* GeneratedMessageReflection::MutableMessage(
if (*result_holder == NULL) {
const Message* default_message = DefaultRaw<const Message*>(field);
- *result_holder = default_message->New();
+ *result_holder = default_message->New(message->GetArena());
}
result = *result_holder;
return result;
}
}
-void GeneratedMessageReflection::SetAllocatedMessage(
+void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage(
Message* message,
Message* sub_message,
const FieldDescriptor* field) const {
@@ -1288,12 +1436,42 @@ void GeneratedMessageReflection::SetAllocatedMessage(
SetBit(message, field);
}
Message** sub_message_holder = MutableRaw<Message*>(message, field);
- delete *sub_message_holder;
+ if (GetArena(message) == NULL) {
+ delete *sub_message_holder;
+ }
*sub_message_holder = sub_message;
}
}
-Message* GeneratedMessageReflection::ReleaseMessage(
+void GeneratedMessageReflection::SetAllocatedMessage(
+ Message* message,
+ Message* sub_message,
+ const FieldDescriptor* field) const {
+ // If message and sub-message are in different memory ownership domains
+ // (different arenas, or one is on heap and one is not), then we may need to
+ // do a copy.
+ if (sub_message != NULL &&
+ sub_message->GetArena() != message->GetArena()) {
+ if (sub_message->GetArena() == NULL && message->GetArena() != NULL) {
+ // Case 1: parent is on an arena and child is heap-allocated. We can add
+ // the child to the arena's Own() list to free on arena destruction, then
+ // set our pointer.
+ message->GetArena()->Own(sub_message);
+ UnsafeArenaSetAllocatedMessage(message, sub_message, field);
+ } else {
+ // Case 2: all other cases. We need to make a copy. MutableMessage() will
+ // either get the existing message object, or instantiate a new one as
+ // appropriate w.r.t. our arena.
+ Message* sub_message_copy = MutableMessage(message, field);
+ sub_message_copy->CopyFrom(*sub_message);
+ }
+ } else {
+ // Same memory ownership domains.
+ UnsafeArenaSetAllocatedMessage(message, sub_message, field);
+ }
+}
+
+Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage(
Message* message,
const FieldDescriptor* field,
MessageFactory* factory) const {
@@ -1320,6 +1498,19 @@ Message* GeneratedMessageReflection::ReleaseMessage(
}
}
+Message* GeneratedMessageReflection::ReleaseMessage(
+ Message* message,
+ const FieldDescriptor* field,
+ MessageFactory* factory) const {
+ Message* released = UnsafeArenaReleaseMessage(message, field, factory);
+ if (GetArena(message) != NULL && released != NULL) {
+ Message* copy_from_arena = released->New();
+ copy_from_arena->CopyFrom(*released);
+ released = copy_from_arena;
+ }
+ return released;
+}
+
const Message& GeneratedMessageReflection::GetRepeatedMessage(
const Message& message, const FieldDescriptor* field, int index) const {
USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
@@ -1371,8 +1562,11 @@ Message* GeneratedMessageReflection::AddMessage(
} else {
prototype = &repeated->Get<GenericTypeHandler<Message> >(0);
}
- result = prototype->New();
- repeated->AddAllocated<GenericTypeHandler<Message> >(result);
+ result = prototype->New(message->GetArena());
+ // We can guarantee here that repeated and result are either both heap
+ // allocated or arena owned. So it is safe to call the unsafe version
+ // of AddAllocated.
+ repeated->UnsafeArenaAddAllocated<GenericTypeHandler<Message> >(result);
}
return result;
}
@@ -1445,6 +1639,10 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
}
+bool GeneratedMessageReflection::SupportsUnknownEnumValues() const {
+ return CreateUnknownEnumValues(descriptor_->file());
+}
+
// ===================================================================
// Some private helpers.
@@ -1487,11 +1685,17 @@ inline const Type& GeneratedMessageReflection::DefaultRaw(
inline const uint32* GeneratedMessageReflection::GetHasBits(
const Message& message) const {
+ if (has_bits_offset_ == -1) { // proto3 with no has-bits.
+ return NULL;
+ }
const void* ptr = reinterpret_cast<const uint8*>(&message) + has_bits_offset_;
return reinterpret_cast<const uint32*>(ptr);
}
inline uint32* GeneratedMessageReflection::MutableHasBits(
Message* message) const {
+ if (has_bits_offset_ == -1) {
+ return NULL;
+ }
void* ptr = reinterpret_cast<uint8*>(message) + has_bits_offset_;
return reinterpret_cast<uint32*>(ptr);
}
@@ -1525,25 +1729,113 @@ inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
return reinterpret_cast<ExtensionSet*>(ptr);
}
+inline Arena* GeneratedMessageReflection::GetArena(Message* message) const {
+ if (arena_offset_ == kNoArenaPointer) {
+ return NULL;
+ }
+
+ if (unknown_fields_offset_ == kUnknownFieldSetInMetadata) {
+ // zero-overhead arena pointer overloading UnknownFields
+ return GetInternalMetadataWithArena(*message).arena();
+ }
+
+ // Baseline case: message class has a dedicated arena pointer.
+ void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
+ return *reinterpret_cast<Arena**>(ptr);
+}
+
+inline const InternalMetadataWithArena&
+GeneratedMessageReflection::GetInternalMetadataWithArena(
+ const Message& message) const {
+ const void* ptr = reinterpret_cast<const uint8*>(&message) + arena_offset_;
+ return *reinterpret_cast<const InternalMetadataWithArena*>(ptr);
+}
+
+inline InternalMetadataWithArena*
+GeneratedMessageReflection::MutableInternalMetadataWithArena(
+ Message* message) const {
+ void* ptr = reinterpret_cast<uint8*>(message) + arena_offset_;
+ return reinterpret_cast<InternalMetadataWithArena*>(ptr);
+}
+
// Simple accessors for manipulating has_bits_.
inline bool GeneratedMessageReflection::HasBit(
const Message& message, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ // proto3: no has-bits. All fields present except messages, which are
+ // present only if their message-field pointer is non-NULL.
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ return GetRaw<const Message*>(message, field) != NULL;
+ } else {
+ // Non-message field (and non-oneof, since that was handled in HasField()
+ // before calling us), and singular (again, checked in HasField). So, this
+ // field must be a scalar.
+
+ // Scalar primitive (numeric or string/bytes) fields are present if
+ // their value is non-zero (numeric) or non-empty (string/bytes). N.B.:
+ // we must use this definition here, rather than the "scalar fields
+ // always present" in the proto3 docs, because MergeFrom() semantics
+ // require presence as "present on wire", and reflection-based merge
+ // (which uses HasField()) needs to be consistent with this.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ return GetField<ArenaStringPtr>(message, field).Get(
+ default_ptr).size() > 0;
+ }
+ }
+ return false;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return GetRaw<bool>(message, field) != false;
+ case FieldDescriptor::CPPTYPE_INT32:
+ return GetRaw<int32>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return GetRaw<int64>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return GetRaw<uint32>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return GetRaw<uint64>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return GetRaw<float>(message, field) != 0.0;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return GetRaw<double>(message, field) != 0.0;
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return GetRaw<int>(message, field) != 0;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ // handled above; avoid warning
+ GOOGLE_LOG(FATAL) << "Reached impossible case in HasBit().";
+ break;
+ }
+ }
+ }
return GetHasBits(message)[field->index() / 32] &
(1 << (field->index() % 32));
}
inline void GeneratedMessageReflection::SetBit(
Message* message, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ return;
+ }
MutableHasBits(message)[field->index() / 32] |= (1 << (field->index() % 32));
}
inline void GeneratedMessageReflection::ClearBit(
Message* message, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ return;
+ }
MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32));
}
inline void GeneratedMessageReflection::SwapBit(
Message* message1, Message* message2, const FieldDescriptor* field) const {
+ if (has_bits_offset_ == -1) {
+ return;
+ }
bool temp_has_bit = HasBit(*message1, field);
if (HasBit(*message2, field)) {
SetBit(message1, field);
@@ -1591,9 +1883,13 @@ inline void GeneratedMessageReflection::ClearOneof(
case FieldDescriptor::CPPTYPE_STRING: {
switch (field->options().ctype()) {
default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING:
- delete *MutableRaw<string*>(message, field);
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ MutableField<ArenaStringPtr>(message, field)->
+ Destroy(default_ptr, GetArena(message));
break;
+ }
}
break;
}
@@ -1678,6 +1974,32 @@ inline Type* GeneratedMessageReflection::AddField(
return repeated->Add();
}
+MessageFactory* GeneratedMessageReflection::GetMessageFactory() const {
+ return message_factory_;
+}
+
+void* GeneratedMessageReflection::RepeatedFieldData(
+ Message* message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpp_type,
+ const Descriptor* message_type) const {
+ GOOGLE_CHECK(field->is_repeated());
+ GOOGLE_CHECK(field->cpp_type() == cpp_type ||
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+ cpp_type == FieldDescriptor::CPPTYPE_INT32))
+ << "The type parameter T in RepeatedFieldRef<T> API doesn't match "
+ << "the actual field type (for enums T should be the generated enum "
+ << "type or int32).";
+ if (message_type != NULL) {
+ GOOGLE_CHECK_EQ(message_type, field->message_type());
+ }
+ if (field->is_extension()) {
+ return MutableExtensionSet(message)->MutableRawRepeatedField(
+ field->number(), field->type(), field->is_packed(), field);
+ } else {
+ return reinterpret_cast<uint8*>(message) + offsets_[field->index()];
+ }
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index b6671ad0..afdfd435 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -45,6 +45,7 @@
// is released to components.
#include <google/protobuf/generated_enum_reflection.h>
#include <google/protobuf/message.h>
+#include <google/protobuf/metadata.h>
#include <google/protobuf/unknown_field_set.h>
@@ -134,7 +135,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int extensions_offset,
const DescriptorPool* pool,
MessageFactory* factory,
- int object_size);
+ int object_size,
+ int arena_offset);
// Similar with the construction above. Call this construction if the
// message has oneof definition.
@@ -170,7 +172,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int oneof_case_offset,
const DescriptorPool* pool,
MessageFactory* factory,
- int object_size);
+ int object_size,
+ int arena_offset);
~GeneratedMessageReflection();
// implements Reflection -------------------------------------------
@@ -217,6 +220,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
string* scratch) const;
const EnumValueDescriptor* GetEnum(const Message& message,
const FieldDescriptor* field) const;
+ int GetEnumValue(const Message& message,
+ const FieldDescriptor* field) const;
const Message& GetMessage(const Message& message,
const FieldDescriptor* field,
MessageFactory* factory = NULL) const;
@@ -245,6 +250,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const string& value) const;
void SetEnum (Message* message, const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
+ void SetEnumValue(Message* message, const FieldDescriptor* field,
+ int value) const;
Message* MutableMessage(Message* message, const FieldDescriptor* field,
MessageFactory* factory = NULL) const;
void SetAllocatedMessage(Message* message,
@@ -275,6 +282,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const EnumValueDescriptor* GetRepeatedEnum(const Message& message,
const FieldDescriptor* field,
int index) const;
+ int GetRepeatedEnumValue(const Message& message,
+ const FieldDescriptor* field,
+ int index) const;
const Message& GetRepeatedMessage(const Message& message,
const FieldDescriptor* field,
int index) const;
@@ -299,6 +309,8 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const string& value) const;
void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
int index, const EnumValueDescriptor* value) const;
+ void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field,
+ int index, int value) const;
// Get a mutable pointer to a field with a message type.
Message* MutableRepeatedMessage(Message* message,
const FieldDescriptor* field,
@@ -323,17 +335,42 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
void AddEnum(Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const;
+ void AddEnumValue(Message* message,
+ const FieldDescriptor* field,
+ int value) const;
Message* AddMessage(Message* message, const FieldDescriptor* field,
MessageFactory* factory = NULL) const;
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
+ bool SupportsUnknownEnumValues() const;
+
+ // This value for arena_offset_ indicates that there is no arena pointer in
+ // this message (e.g., old generated code).
+ static const int kNoArenaPointer = -1;
+
+ // This value for unknown_field_offset_ indicates that there is no
+ // UnknownFieldSet in this message, and that instead, we are using the
+ // Zero-Overhead Arena Pointer trick. When this is the case, arena_offset_
+ // actually indexes to an InternalMetadataWithArena instance, which can return
+ // either an arena pointer or an UnknownFieldSet or both. It is never the case
+ // that unknown_field_offset_ == kUnknownFieldSetInMetadata && arena_offset_
+ // == kNoArenaPointer.
+ static const int kUnknownFieldSetInMetadata = -1;
+
protected:
virtual void* MutableRawRepeatedField(
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
int ctype, const Descriptor* desc) const;
+ virtual MessageFactory* GetMessageFactory() const;
+
+ virtual void* RepeatedFieldData(
+ Message* message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpp_type,
+ const Descriptor* message_type) const;
+
private:
friend class GeneratedMessage;
@@ -350,6 +387,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int oneof_case_offset_;
int unknown_fields_offset_;
int extensions_offset_;
+ int arena_offset_;
int object_size_;
const DescriptorPool* descriptor_pool_;
@@ -376,6 +414,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const OneofDescriptor* oneof_descriptor) const;
inline const ExtensionSet& GetExtensionSet(const Message& message) const;
inline ExtensionSet* MutableExtensionSet(Message* message) const;
+ inline Arena* GetArena(Message* message) const;
+ inline const internal::InternalMetadataWithArena&
+ GetInternalMetadataWithArena(const Message& message) const;
+ inline internal::InternalMetadataWithArena*
+ MutableInternalMetadataWithArena(Message* message) const;
inline bool HasBit(const Message& message,
const FieldDescriptor* field) const;
@@ -438,6 +481,28 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int GetExtensionNumberOrDie(const Descriptor* type) const;
+ // Internal versions of EnumValue API perform no checking. Called after checks
+ // by public methods.
+ void SetEnumValueInternal(Message* message,
+ const FieldDescriptor* field,
+ int value) const;
+ void SetRepeatedEnumValueInternal(Message* message,
+ const FieldDescriptor* field,
+ int index,
+ int value) const;
+ void AddEnumValueInternal(Message* message,
+ const FieldDescriptor* field,
+ int value) const;
+
+
+ Message* UnsafeArenaReleaseMessage(Message* message,
+ const FieldDescriptor* field,
+ MessageFactory* factory = NULL) const;
+
+ void UnsafeArenaSetAllocatedMessage(Message* message,
+ Message* sub_message,
+ const FieldDescriptor* field) const;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
};
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 53449755..df88205c 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -40,8 +40,10 @@
#include <google/protobuf/io/coded_stream_inl.h>
#include <algorithm>
+#include <utility>
#include <limits.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/arena.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -149,6 +151,19 @@ void CodedInputStream::PopLimit(Limit limit) {
legitimate_message_end_ = false;
}
+std::pair<CodedInputStream::Limit, int>
+CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
+ return make_pair(PushLimit(byte_limit), --recursion_budget_);
+}
+
+bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
+ bool result = ConsumedEntireMessage();
+ PopLimit(limit);
+ GOOGLE_DCHECK_LT(recursion_budget_, recursion_limit_);
+ ++recursion_budget_;
+ return result;
+}
+
int CodedInputStream::BytesUntilLimit() const {
if (current_limit_ == INT_MAX) return -1;
int current_position = CurrentPosition();
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 775c6067..b9c30fa3 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -110,6 +110,7 @@
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
#include <string>
+#include <utility>
#ifdef _MSC_VER
#if defined(_M_IX86) && \
!defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST)
@@ -129,8 +130,8 @@
#endif
#include <google/protobuf/stubs/common.h>
-
namespace google {
+
namespace protobuf {
class DescriptorPool;
@@ -388,6 +389,23 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Decrements the recursion depth.
void DecrementRecursionDepth();
+ // Shorthand for make_pair(PushLimit(byte_limit), --recursion_budget_).
+ // Using this can reduce code size and complexity in some cases. The caller
+ // is expected to check that the second part of the result is non-negative (to
+ // bail out if the depth of recursion is too high) and, if all is well, to
+ // later pass the first part of the result to PopLimit() or similar.
+ std::pair<CodedInputStream::Limit, int> IncrementRecursionDepthAndPushLimit(
+ int byte_limit);
+
+ // Helper that is equivalent to: {
+ // bool result = ConsumedEntireMessage();
+ // PopLimit(limit);
+ // DecrementRecursionDepth();
+ // return result; }
+ // Using this can reduce code size and complexity in some cases.
+ // Do not use unless the current recursion depth is greater than zero.
+ bool DecrementRecursionDepthAndPopLimit(Limit limit);
+
// Extension Registry ----------------------------------------------
// ADVANCED USAGE: 99.9% of people can ignore this section.
//
@@ -470,9 +488,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream);
- ZeroCopyInputStream* input_;
const uint8* buffer_;
const uint8* buffer_end_; // pointer to the end of the buffer.
+ ZeroCopyInputStream* input_;
int total_bytes_read_; // total bytes read from input_, including
// the current buffer
@@ -513,9 +531,10 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// If -2: Internal: Limit has been reached, print full size when destructing.
int total_bytes_warning_threshold_;
- // Current recursion depth, controlled by IncrementRecursionDepth() and
- // DecrementRecursionDepth().
- int recursion_depth_;
+ // Current recursion budget, controlled by IncrementRecursionDepth() and
+ // similar. Starts at recursion_limit_ and goes down: if this reaches
+ // -1 we are over budget.
+ int recursion_budget_;
// Recursion depth limit, set by SetRecursionLimit().
int recursion_limit_;
@@ -1132,16 +1151,17 @@ inline void CodedOutputStream::Advance(int amount) {
}
inline void CodedInputStream::SetRecursionLimit(int limit) {
+ recursion_budget_ += limit - recursion_limit_;
recursion_limit_ = limit;
}
inline bool CodedInputStream::IncrementRecursionDepth() {
- ++recursion_depth_;
- return recursion_depth_ <= recursion_limit_;
+ --recursion_budget_;
+ return recursion_budget_ >= 0;
}
inline void CodedInputStream::DecrementRecursionDepth() {
- if (recursion_depth_ > 0) --recursion_depth_;
+ if (recursion_budget_ < recursion_limit_) ++recursion_budget_;
}
inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool,
@@ -1163,9 +1183,9 @@ inline int CodedInputStream::BufferSize() const {
}
inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
- : input_(input),
- buffer_(NULL),
+ : buffer_(NULL),
buffer_end_(NULL),
+ input_(input),
total_bytes_read_(0),
overflow_bytes_(0),
last_tag_(0),
@@ -1175,7 +1195,7 @@ inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
buffer_size_after_limit_(0),
total_bytes_limit_(kDefaultTotalBytesLimit),
total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
- recursion_depth_(0),
+ recursion_budget_(default_recursion_limit_),
recursion_limit_(default_recursion_limit_),
extension_pool_(NULL),
extension_factory_(NULL) {
@@ -1184,9 +1204,9 @@ inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input)
}
inline CodedInputStream::CodedInputStream(const uint8* buffer, int size)
- : input_(NULL),
- buffer_(buffer),
+ : buffer_(buffer),
buffer_end_(buffer + size),
+ input_(NULL),
total_bytes_read_(size),
overflow_bytes_(0),
last_tag_(0),
@@ -1196,7 +1216,7 @@ inline CodedInputStream::CodedInputStream(const uint8* buffer, int size)
buffer_size_after_limit_(0),
total_bytes_limit_(kDefaultTotalBytesLimit),
total_bytes_warning_threshold_(kDefaultTotalBytesWarningThreshold),
- recursion_depth_(0),
+ recursion_budget_(default_recursion_limit_),
recursion_limit_(default_recursion_limit_),
extension_pool_(NULL),
extension_factory_(NULL) {
diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h
index 88c14cab..cd8d1746 100644
--- a/src/google/protobuf/io/coded_stream_inl.h
+++ b/src/google/protobuf/io/coded_stream_inl.h
@@ -36,6 +36,7 @@
#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <string>
@@ -51,10 +52,12 @@ inline bool CodedInputStream::InternalReadStringInline(string* buffer,
if (BufferSize() >= size) {
STLStringResizeUninitialized(buffer, size);
- // When buffer is empty, string_as_array(buffer) will return NULL but memcpy
- // requires non-NULL pointers even when size is 0. Hench this check.
- if (size > 0) {
- memcpy(mutable_string_data(buffer), buffer_, size);
+ std::pair<char*, bool> z = as_string_data(buffer);
+ if (z.second) {
+ // Oddly enough, memcpy() requires its first two args to be non-NULL even
+ // if we copy 0 bytes. So, we have ensured that z.first is non-NULL here.
+ GOOGLE_DCHECK(z.first != NULL);
+ memcpy(z.first, 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 f4cb5ea1..bbe5e399 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -144,6 +144,7 @@ uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize];
// checks.
const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024};
+
// -------------------------------------------------------------------
// Varint tests.
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index ee286961..e6037863 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -48,7 +48,7 @@ static const int kDefaultBufferSize = 65536;
GzipInputStream::GzipInputStream(
ZeroCopyInputStream* sub_stream, Format format, int buffer_size)
- : format_(format), sub_stream_(sub_stream), zerror_(Z_OK) {
+ : format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) {
zcontext_.zalloc = Z_NULL;
zcontext_.zfree = Z_NULL;
zcontext_.opaque = Z_NULL;
@@ -134,6 +134,7 @@ bool GzipInputStream::Next(const void** data, int* size) {
if (zcontext_.next_out != NULL) {
// sub_stream_ may have concatenated streams to follow
zerror_ = inflateEnd(&zcontext_);
+ byte_count_ += zcontext_.total_out;
if (zerror_ != Z_OK) {
return false;
}
@@ -178,8 +179,12 @@ bool GzipInputStream::Skip(int count) {
return ok;
}
int64 GzipInputStream::ByteCount() const {
- return zcontext_.total_out +
- (((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_));
+ int64 ret = byte_count_ + zcontext_.total_out;
+ if (zcontext_.next_out != NULL && output_position_ != NULL) {
+ ret += reinterpret_cast<uintptr_t>(zcontext_.next_out) -
+ reinterpret_cast<uintptr_t>(output_position_);
+ }
+ return ret;
}
// =========================================================================
diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
index c7ccc260..82445000 100644
--- a/src/google/protobuf/io/gzip_stream.h
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -99,6 +99,7 @@ class LIBPROTOBUF_EXPORT GzipInputStream : public ZeroCopyInputStream {
void* output_buffer_;
void* output_position_;
size_t output_buffer_length_;
+ int64 byte_count_;
int Inflate(int flush);
void DoNextOutput(const void** data, int* size);
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index c8df4177..e621ba1d 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -142,6 +142,19 @@ void Printer::Print(const char* text,
Print(vars, text);
}
+void Printer::Print(const char* text,
+ const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ Print(vars, text);
+}
+
void Printer::Indent() {
indent_ += " ";
}
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index f06cbf2f..92ce3409 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -86,6 +86,11 @@ class LIBPROTOBUF_EXPORT Printer {
void Print(const char* text, const char* variable1, const string& value1,
const char* variable2, const string& value2,
const char* variable3, const string& value3);
+ // Like the first Print(), except the substitutions are given as parameters.
+ void Print(const char* text, const char* variable1, const string& value1,
+ const char* variable2, const string& value2,
+ const char* variable3, const string& value3,
+ const char* variable4, const string& value4);
// TODO(kenton): Overloaded versions with more variables? Three seems
// to be enough.
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 58aff0e2..97b73b88 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -37,6 +37,7 @@
#include <algorithm>
#include <limits>
+#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stl_util.h>
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 e18da72c..a517161d 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -334,6 +334,18 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea
// ===================================================================
+// mutable_string_data() and as_string_data() are workarounds to improve
+// the performance of writing new data to an existing string. Unfortunately
+// the methods provided by the string class are suboptimal, and using memcpy()
+// is mildly annoying because it requires its pointer args to be non-NULL even
+// if we ask it to copy 0 bytes. Furthermore, string_as_array() has the
+// property that it always returns NULL if its arg is the empty string, exactly
+// what we want to avoid if we're using it in conjunction with memcpy()!
+// With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size),
+// where s is a string*. Without C++11, &(*s)[0] is not guaranteed to be safe,
+// so we use string_as_array(), and live with the extra logic that tests whether
+// *s is empty.
+
// 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().
@@ -347,6 +359,19 @@ inline char* mutable_string_data(string* s) {
#endif
}
+// as_string_data(s) is equivalent to
+// ({ char* p = mutable_string_data(s); make_pair(p, p != NULL); })
+// Sometimes it's faster: in some scenarios p cannot be NULL, and then the
+// code can avoid that check.
+inline std::pair<char*, bool> as_string_data(string* s) {
+ char *p = mutable_string_data(s);
+#ifdef LANG_CXX11
+ return make_pair(p, true);
+#else
+ return make_pair(p, p != NULL);
+#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 bf978cc8..dd3d1285 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -656,6 +656,43 @@ TEST_F(IoTest, TwoSessionWriteGzip) {
delete [] temp_buffer;
delete [] buffer;
}
+
+TEST_F(IoTest, GzipInputByteCountAfterClosed) {
+ string golden = "abcdefghijklmnopqrstuvwxyz";
+ string compressed = Compress(golden, GzipOutputStream::Options());
+
+ for (int i = 0; i < kBlockSizeCount; i++) {
+ ArrayInputStream arr_input(compressed.data(), compressed.size(),
+ kBlockSizes[i]);
+ GzipInputStream gz_input(&arr_input);
+ const void* buffer;
+ int size;
+ while (gz_input.Next(&buffer, &size)) {
+ EXPECT_LE(gz_input.ByteCount(), golden.size());
+ }
+ EXPECT_EQ(golden.size(), gz_input.ByteCount());
+ }
+}
+
+TEST_F(IoTest, GzipInputByteCountAfterClosedConcatenatedStreams) {
+ string golden1 = "abcdefghijklmnopqrstuvwxyz";
+ string golden2 = "the quick brown fox jumps over the lazy dog";
+ const size_t total_size = golden1.size() + golden2.size();
+ string compressed = Compress(golden1, GzipOutputStream::Options()) +
+ Compress(golden2, GzipOutputStream::Options());
+
+ for (int i = 0; i < kBlockSizeCount; i++) {
+ ArrayInputStream arr_input(compressed.data(), compressed.size(),
+ kBlockSizes[i]);
+ GzipInputStream gz_input(&arr_input);
+ const void* buffer;
+ int size;
+ while (gz_input.Next(&buffer, &size)) {
+ EXPECT_LE(gz_input.ByteCount(), total_size);
+ }
+ EXPECT_EQ(total_size, gz_input.ByteCount());
+ }
+}
#endif
// There is no string input, only string output. Also, it doesn't support
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 1324ed9b..aab00fdf 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/reflection_internal.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
@@ -49,6 +50,7 @@
#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/singleton.h>
#include <google/protobuf/stubs/stl_util.h>
namespace google {
@@ -222,6 +224,38 @@ void* Reflection::MutableRawRepeatedString(
}
+// Default EnumValue API implementations. Real reflection implementations should
+// override these. However, there are several legacy implementations that do
+// not, and cannot easily be changed at the same time as the Reflection API, so
+// we provide these for now.
+// TODO: Remove these once all Reflection implementations are updated.
+int Reflection::GetEnumValue(const Message& message,
+ const FieldDescriptor* field) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+ return 0;
+}
+void Reflection::SetEnumValue(Message* message,
+ const FieldDescriptor* field,
+ int value) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+}
+int Reflection::GetRepeatedEnumValue(
+ const Message& message,
+ const FieldDescriptor* field, int index) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+ return 0;
+}
+void Reflection::SetRepeatedEnumValue(Message* message,
+ const FieldDescriptor* field, int index,
+ int value) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+}
+void Reflection::AddEnumValue(Message* message,
+ const FieldDescriptor* field,
+ int value) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
+}
+
// =============================================================================
// MessageFactory
@@ -354,5 +388,60 @@ void MessageFactory::InternalRegisterGeneratedMessage(
}
+MessageFactory* Reflection::GetMessageFactory() const {
+ GOOGLE_LOG(FATAL) << "Not implemented.";
+ return NULL;
+}
+
+void* Reflection::RepeatedFieldData(
+ Message* message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpp_type,
+ const Descriptor* message_type) const {
+ GOOGLE_LOG(FATAL) << "Not implemented.";
+ return NULL;
+}
+
+namespace internal {
+RepeatedFieldAccessor::~RepeatedFieldAccessor() {
+}
+} // namespace internal
+
+const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
+ const FieldDescriptor* field) const {
+ GOOGLE_CHECK(field->is_repeated());
+ switch (field->cpp_type()) {
+#define HANDLE_PRIMITIVE_TYPE(TYPE, type) \
+ case FieldDescriptor::CPPTYPE_ ## TYPE: \
+ return internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<type> >::get();
+ HANDLE_PRIMITIVE_TYPE(INT32, int32)
+ HANDLE_PRIMITIVE_TYPE(UINT32, uint32)
+ HANDLE_PRIMITIVE_TYPE(INT64, int64)
+ HANDLE_PRIMITIVE_TYPE(UINT64, uint64)
+ HANDLE_PRIMITIVE_TYPE(FLOAT, float)
+ HANDLE_PRIMITIVE_TYPE(DOUBLE, double)
+ HANDLE_PRIMITIVE_TYPE(BOOL, bool)
+ HANDLE_PRIMITIVE_TYPE(ENUM, int32)
+#undef HANDLE_PRIMITIVE_TYPE
+ case FieldDescriptor::CPPTYPE_STRING:
+ switch (field->options().ctype()) {
+ default:
+ case FieldOptions::STRING:
+ return internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::get();
+ }
+ break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::get();
+ }
+ GOOGLE_LOG(FATAL) << "Should not reach here.";
+ return NULL;
+}
+
+namespace internal {
+// Macro defined in repeated_field.h. We can only define the Message-specific
+// GenericTypeHandler specializations here because we depend on Message, which
+// is not part of proto2-lite hence is not available in repeated_field.h.
+DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES_NOINLINE(Message);
+} // namespace internal
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 67d45493..1d8f2499 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -112,8 +112,10 @@
#include <iosfwd>
#include <string>
+#include <google/protobuf/stubs/type_traits.h>
#include <vector>
+#include <google/protobuf/arena.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/stubs/common.h>
@@ -121,6 +123,7 @@
#define GOOGLE_PROTOBUF_HAS_ONEOF
+#define GOOGLE_PROTOBUF_HAS_ARENAS
namespace google {
namespace protobuf {
@@ -174,6 +177,17 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// for return-type covariance.)
virtual Message* New() const = 0;
+ // Construct a new instance on the arena. Ownership is passed to the caller
+ // if arena is a NULL. Default implementation allows for API compatibility
+ // during the Arena transition.
+ virtual Message* New(::google::protobuf::Arena* arena) const {
+ Message* message = New();
+ if (arena != NULL) {
+ arena->Own(message);
+ }
+ return message;
+ }
+
// Make this message into a copy of the given message. The given message
// must have the same descriptor, but need not necessarily be the same class.
// By default this is just implemented as "Clear(); MergeFrom(from);".
@@ -313,6 +327,20 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
};
+namespace internal {
+// Forward-declare interfaces used to implement RepeatedFieldRef.
+// These are protobuf internals that users shouldn't care about.
+class RepeatedFieldAccessor;
+} // namespace internal
+
+// Forward-declare RepeatedFieldRef templates. The second type parameter is
+// used for SFINAE tricks. Users should ignore it.
+template<typename T, typename Enable = void>
+class RepeatedFieldRef;
+
+template<typename T, typename Enable = void>
+class MutableRepeatedFieldRef;
+
// This interface contains methods that can be used to dynamically access
// and modify the fields of a protocol message. Their semantics are
// similar to the accessors the protocol compiler generates.
@@ -361,12 +389,15 @@ class LIBPROTOBUF_EXPORT Reflection {
// Get the UnknownFieldSet for the message. This contains fields which
// were seen when the Message was parsed but were not recognized according
- // to the Message's definition.
+ // to the Message's definition. For proto3 protos, this method will always
+ // return an empty UnknownFieldSet.
virtual const UnknownFieldSet& GetUnknownFields(
const Message& message) const = 0;
// Get a mutable pointer to the UnknownFieldSet for the message. This
// contains fields which were seen when the Message was parsed but were not
- // recognized according to the Message's definition.
+ // recognized according to the Message's definition. For proto3 protos, this
+ // method will return a valid mutable UnknownFieldSet pointer but modifying
+ // it won't affect the serialized bytes of the message.
virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0;
// Estimate the amount of memory used by the message object.
@@ -385,7 +416,7 @@ 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
+ // Check if the oneof is set. Returns true if any field in oneof
// is set, false otherwise.
// TODO(jieluo) - make it pure virtual after updating all
// the subclasses.
@@ -464,6 +495,15 @@ class LIBPROTOBUF_EXPORT Reflection {
const FieldDescriptor* field) const = 0;
virtual const EnumValueDescriptor* GetEnum(
const Message& message, const FieldDescriptor* field) const = 0;
+
+ // GetEnumValue() returns an enum field's value as an integer rather than
+ // an EnumValueDescriptor*. If the integer value does not correspond to a
+ // known value descriptor, a new value descriptor is created. (Such a value
+ // will only be present when the new unknown-enum-value semantics are enabled
+ // for a message.)
+ virtual int GetEnumValue(
+ const Message& message, const FieldDescriptor* field) const;
+
// See MutableMessage() for the meaning of the "factory" parameter.
virtual const Message& GetMessage(const Message& message,
const FieldDescriptor* field,
@@ -512,6 +552,14 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void SetEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
+ // Set an enum field's value with an integer rather than EnumValueDescriptor.
+ // If the value does not correspond to a known enum value, either behavior is
+ // undefined (for proto2 messages), or the value is accepted silently for
+ // messages with new unknown-enum-value semantics.
+ virtual void SetEnumValue(Message* message,
+ const FieldDescriptor* field,
+ int value) const;
+
// Get a mutable pointer to a field with a message type. If a MessageFactory
// is provided, it will be used to construct instances of the sub-message;
// otherwise, the default factory is used. If the field is an extension that
@@ -574,6 +622,14 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual const EnumValueDescriptor* GetRepeatedEnum(
const Message& message,
const FieldDescriptor* field, int index) const = 0;
+ // GetRepeatedEnumValue() returns an enum field's value as an integer rather
+ // than an EnumValueDescriptor*. If the integer value does not correspond to a
+ // known value descriptor, a new value descriptor is created. (Such a value
+ // will only be present when the new unknown-enum-value semantics are enabled
+ // for a message.)
+ virtual int GetRepeatedEnumValue(
+ const Message& message,
+ const FieldDescriptor* field, int index) const;
virtual const Message& GetRepeatedMessage(
const Message& message,
const FieldDescriptor* field, int index) const = 0;
@@ -614,6 +670,13 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void SetRepeatedEnum(Message* message,
const FieldDescriptor* field, int index,
const EnumValueDescriptor* value) const = 0;
+ // Set an enum field's value with an integer rather than EnumValueDescriptor.
+ // If the value does not correspond to a known enum value, either behavior is
+ // undefined (for proto2 messages), or the value is accepted silently for
+ // messages with new unknown-enum-value semantics.
+ virtual void SetRepeatedEnumValue(Message* message,
+ const FieldDescriptor* field, int index,
+ int value) const;
// Get a mutable pointer to an element of a repeated field with a message
// type.
virtual Message* MutableRepeatedMessage(
@@ -643,12 +706,57 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual void AddEnum (Message* message,
const FieldDescriptor* field,
const EnumValueDescriptor* value) const = 0;
+ // Set an enum field's value with an integer rather than EnumValueDescriptor.
+ // If the value does not correspond to a known enum value, either behavior is
+ // undefined (for proto2 messages), or the value is accepted silently for
+ // messages with new unknown-enum-value semantics.
+ virtual void AddEnumValue(Message* message,
+ const FieldDescriptor* field,
+ int value) const;
// See MutableMessage() for comments on the "factory" parameter.
virtual Message* AddMessage(Message* message,
const FieldDescriptor* field,
MessageFactory* factory = NULL) const = 0;
+ // Get a RepeatedFieldRef object that can be used to read the underlying
+ // repeated field. The type parameter T must be set according to the
+ // field's cpp type. The following table shows the mapping from cpp type
+ // to acceptable T.
+ //
+ // field->cpp_type() T
+ // CPPTYPE_INT32 int32
+ // CPPTYPE_UINT32 uint32
+ // CPPTYPE_INT64 int64
+ // CPPTYPE_UINT64 uint64
+ // CPPTYPE_DOUBLE double
+ // CPPTYPE_FLOAT float
+ // CPPTYPE_BOOL bool
+ // CPPTYPE_ENUM generated enum type or int32
+ // CPPTYPE_STRING string
+ // CPPTYPE_MESSAGE generated message type or google::protobuf::Message
+ //
+ // A RepeatedFieldRef object can be copied and the resulted object will point
+ // to the same repeated field in the same message. The object can be used as
+ // long as the message is not destroyed.
+ //
+ // Note that to use this method users need to include the header file
+ // "google/protobuf/reflection.h" (which defines the RepeatedFieldRef
+ // class templates).
+ template<typename T>
+ RepeatedFieldRef<T> GetRepeatedFieldRef(
+ const Message& message, const FieldDescriptor* field) const;
+
+ // Like GetRepeatedFieldRef() but return an object that can also be used
+ // manipulate the underlying repeated field.
+ template<typename T>
+ MutableRepeatedFieldRef<T> GetMutableRepeatedFieldRef(
+ Message* message, const FieldDescriptor* field) const;
+
+ // DEPRECATED. Please use Get(Mutable)RepeatedFieldRef() for repeated field
+ // access. The following repeated field accesors will be removed in the
+ // future.
+ //
// Repeated field accessors -------------------------------------------------
// The methods above, e.g. GetRepeatedInt32(msg, fd, index), provide singular
// access to the data in a RepeatedField. The methods below provide aggregate
@@ -659,22 +767,30 @@ class LIBPROTOBUF_EXPORT Reflection {
//
// Usage example: my_doubs = refl->GetRepeatedField<double>(msg, fd);
+ // DEPRECATED. Please use GetRepeatedFieldRef().
+ //
// for T = Cord and all protobuf scalar types except enums.
template<typename T>
const RepeatedField<T>& GetRepeatedField(
const Message&, const FieldDescriptor*) const;
+ // DEPRECATED. Please use GetMutableRepeatedFieldRef().
+ //
// for T = Cord and all protobuf scalar types except enums.
template<typename T>
RepeatedField<T>* MutableRepeatedField(
Message*, const FieldDescriptor*) const;
+ // DEPRECATED. Please use GetRepeatedFieldRef().
+ //
// for T = string, google::protobuf::internal::StringPieceField
// google::protobuf::Message & descendants.
template<typename T>
const RepeatedPtrField<T>& GetRepeatedPtrField(
const Message&, const FieldDescriptor*) const;
+ // DEPRECATED. Please use GetMutableRepeatedFieldRef().
+ //
// for T = string, google::protobuf::internal::StringPieceField
// google::protobuf::Message & descendants.
template<typename T>
@@ -693,6 +809,39 @@ class LIBPROTOBUF_EXPORT Reflection {
virtual const FieldDescriptor* FindKnownExtensionByNumber(
int number) const = 0;
+ // Feature Flags -------------------------------------------------------------
+
+ // Does this message support storing arbitrary integer values in enum fields?
+ // If |true|, GetEnumValue/SetEnumValue and associated repeated-field versions
+ // take arbitrary integer values, and the legacy GetEnum() getter will
+ // dynamically create an EnumValueDescriptor for any integer value without
+ // one. If |false|, setting an unknown enum value via the integer-based
+ // setters results in undefined behavior (in practice, GOOGLE_DCHECK-fails).
+ //
+ // Generic code that uses reflection to handle messages with enum fields
+ // should check this flag before using the integer-based setter, and either
+ // downgrade to a compatible value or use the UnknownFieldSet if not. For
+ // example:
+ //
+ // int new_value = GetValueFromApplicationLogic();
+ // if (reflection->SupportsUnknownEnumValues()) {
+ // reflection->SetEnumValue(message, field, new_value);
+ // } else {
+ // if (field_descriptor->enum_type()->
+ // FindValueByNumver(new_value) != NULL) {
+ // reflection->SetEnumValue(message, field, new_value);
+ // } else if (emit_unknown_enum_values) {
+ // reflection->MutableUnknownFields(message)->AddVarint(
+ // field->number(),
+ // new_value);
+ // } else {
+ // // convert value to a compatible/default value.
+ // new_value = CompatibleDowngrade(new_value);
+ // reflection->SetEnumValue(message, field, new_value);
+ // }
+ // }
+ virtual bool SupportsUnknownEnumValues() const { return false; }
+
// ---------------------------------------------------------------------------
protected:
@@ -705,7 +854,38 @@ class LIBPROTOBUF_EXPORT Reflection {
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
int ctype, const Descriptor* message_type) const = 0;
+ virtual MessageFactory* GetMessageFactory() const;
+
+ // The following methods are used to implement (Mutable)RepeatedFieldRef.
+ // A Ref object will store a raw pointer to the repeated field data (obtained
+ // from RepeatedFieldData()) and a pointer to a Accessor (obtained from
+ // RepeatedFieldAccessor) which will be used to access the raw data.
+ //
+ // TODO(xiaofeng): Make these methods pure-virtual.
+
+ // Returns a raw pointer to the repeated field
+ //
+ // "cpp_type" and "message_type" are decuded from the type parameter T passed
+ // to Get(Mutable)RepeatedFieldRef. If T is a generated message type,
+ // "message_type" should be set to its descriptor. Otherwise "message_type"
+ // should be set to NULL. Implementations of this method should check whether
+ // "cpp_type"/"message_type" is consistent with the actual type of the field.
+ virtual void* RepeatedFieldData(
+ Message* message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpp_type,
+ const Descriptor* message_type) const;
+
+ // The returned pointer should point to a singleton instance which implements
+ // the RepeatedFieldAccessor interface.
+ virtual const internal::RepeatedFieldAccessor* RepeatedFieldAccessor(
+ const FieldDescriptor* field) const;
+
private:
+ template<typename T, typename Enable>
+ friend class RepeatedFieldRef;
+ template<typename T, typename Enable>
+ friend class MutableRepeatedFieldRef;
+
// Special version for specialized implementations of string. We can't call
// MutableRawRepeatedField directly here because we don't have access to
// FieldOptions::* which are defined in descriptor.pb.h. Including that
@@ -859,7 +1039,6 @@ inline RepeatedPtrField<PB>* Reflection::MutableRepeatedPtrField(
FieldDescriptor::CPPTYPE_MESSAGE, -1,
PB::default_instance().GetDescriptor()));
}
-
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 14cdc91f..63be0e9b 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -34,6 +34,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/message_lite.h>
+#include <google/protobuf/arena.h>
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
@@ -153,6 +154,15 @@ bool InlineParsePartialFromArray(const void* data, int size,
} // namespace
+
+MessageLite* MessageLite::New(::google::protobuf::Arena* arena) const {
+ MessageLite* message = New();
+ if (arena != NULL) {
+ arena->Own(message);
+ }
+ return message;
+}
+
bool MessageLite::MergeFromCodedStream(io::CodedInputStream* input) {
return InlineMergeFromCodedStream(input, this);
}
@@ -233,6 +243,12 @@ bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
bool MessageLite::SerializePartialToCodedStream(
io::CodedOutputStream* output) const {
const int size = ByteSize(); // Force size to be cached.
+ if (size < 0) {
+ // Messages >2G cannot be serialized due to overflow computing ByteSize.
+ GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
+ return false;
+ }
+
uint8* buffer = output->GetDirectBufferForNBytesAndAdvance(size);
if (buffer != NULL) {
uint8* end = SerializeWithCachedSizesToArray(buffer);
@@ -277,6 +293,12 @@ bool MessageLite::AppendToString(string* output) const {
bool MessageLite::AppendPartialToString(string* output) const {
int old_size = output->size();
int byte_size = ByteSize();
+ if (byte_size < 0) {
+ // Messages >2G cannot be serialized due to overflow computing ByteSize.
+ GOOGLE_LOG(ERROR) << "Error computing ByteSize (possible overflow?).";
+ return false;
+ }
+
STLStringResizeUninitialized(output, old_size + byte_size);
uint8* start =
reinterpret_cast<uint8*>(io::mutable_string_data(output) + old_size);
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 027cabf9..106982cc 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -43,7 +43,7 @@
namespace google {
namespace protobuf {
-
+ class Arena;
namespace io {
class CodedInputStream;
class CodedOutputStream;
@@ -88,6 +88,27 @@ class LIBPROTOBUF_EXPORT MessageLite {
// caller.
virtual MessageLite* New() const = 0;
+ // Construct a new instance on the arena. Ownership is passed to the caller
+ // if arena is a NULL. Default implementation for backwards compatibility.
+ virtual MessageLite* New(::google::protobuf::Arena* arena) const;
+
+ // Get the arena, if any, associated with this message. Virtual method
+ // required for generic operations but most arena-related operations should
+ // use the GetArenaNoVirtual() generated-code method. Default implementation
+ // to reduce code size by avoiding the need for per-type implementations when
+ // types do not implement arena support.
+ virtual ::google::protobuf::Arena* GetArena() const { return NULL; }
+
+ // Get a pointer that may be equal to this message's arena, or may not be. If
+ // the value returned by this method is equal to some arena pointer, then this
+ // message is on that arena; however, if this message is on some arena, this
+ // method may or may not return that arena's pointer. As a tradeoff, this
+ // method may be more efficient than GetArena(). The intent is to allow
+ // underlying representations that use e.g. tagged pointers to sometimes store
+ // the arena pointer directly, and sometimes in a more indirect way, and allow
+ // a fastpath comparison against the arena pointer when it's easy to obtain.
+ virtual void* GetMaybeArenaPointer() const { return GetArena(); }
+
// Clear all fields of the message and set them to their default values.
// Clear() avoids freeing memory, assuming that any memory allocated
// to hold parts of the message will be needed again to hold the next
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index a5f339f1..ebfb4321 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -242,6 +242,25 @@ TEST(MessageTest, CheckOverflow) {
#endif // PROTOBUF_HAS_DEATH_TEST
+namespace {
+
+class NegativeByteSize : public unittest::TestRequired {
+ public:
+ virtual int ByteSize() const { return -1; }
+};
+
+} // namespace
+
+TEST(MessageTest, SerializationFailsOnNegativeByteSize) {
+ NegativeByteSize message;
+ string string_output;
+ EXPECT_FALSE(message.AppendPartialToString(&string_output));
+
+ io::ArrayOutputStream coded_raw_output(NULL, 100);
+ io::CodedOutputStream coded_output(&coded_raw_output);
+ EXPECT_FALSE(message.SerializePartialToCodedStream(&coded_output));
+}
+
TEST(MessageTest, BypassInitializationCheckOnSerialize) {
unittest::TestRequired message;
io::ArrayOutputStream raw_output(NULL, 0);
diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h
new file mode 100644
index 00000000..30b2a6ee
--- /dev/null
+++ b/src/google/protobuf/metadata.h
@@ -0,0 +1,164 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header file defines an internal class that encapsulates internal message
+// metadata (Unknown-field set, Arena pointer, ...) and allows its
+// representation to be made more space-efficient via various optimizations.
+//
+// Note that this is distinct from google::protobuf::Metadata, which encapsulates
+// Descriptor and Reflection pointers.
+
+#ifndef GOOGLE_PROTOBUF_METADATA_H__
+#define GOOGLE_PROTOBUF_METADATA_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/unknown_field_set.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This is the representation for messages that support arena allocation. It
+// uses a tagged pointer to either store the Arena pointer, if there are no
+// unknown fields, or a pointer to a block of memory with both the Arena pointer
+// and the UnknownFieldSet, if there are unknown fields. This optimization
+// allows for "zero-overhead" storage of the Arena pointer, relative to the
+// above baseline implementation.
+//
+// The tagged pointer uses the LSB to disambiguate cases, and uses bit 0 == 0 to
+// indicate an arena pointer and bit 0 == 1 to indicate a UFS+Arena-container
+// pointer.
+class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
+ public:
+ InternalMetadataWithArena() : ptr_(NULL) {}
+ explicit InternalMetadataWithArena(Arena* arena)
+ : ptr_ (arena) {}
+
+ ~InternalMetadataWithArena() {
+ if (have_unknown_fields() && arena() == NULL) {
+ delete PtrValue<Container>();
+ }
+ ptr_ = NULL;
+ }
+
+ inline const UnknownFieldSet& unknown_fields() const
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
+ return PtrValue<Container>()->unknown_fields_;
+ } else {
+ return *UnknownFieldSet::default_instance();
+ }
+ }
+
+ inline UnknownFieldSet* mutable_unknown_fields() GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) {
+ return &PtrValue<Container>()->unknown_fields_;
+ } else {
+ return mutable_unknown_fields_slow();
+ }
+ }
+
+ inline Arena* arena() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
+ return PtrValue<Container>()->arena_;
+ } else {
+ return PtrValue<Arena>();
+ }
+ }
+
+ inline bool have_unknown_fields() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ return PtrTag() == kTagContainer;
+ }
+
+ inline void Swap(InternalMetadataWithArena* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ // Semantics here are that we swap only the unknown fields, not the arena
+ // pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
+ // maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
+ // different states (direct arena pointer vs. container with UFS) so we
+ // cannot simply swap ptr_ and then restore the arena pointers. We reuse
+ // UFS's swap implementation instead.
+ if (have_unknown_fields() || other->have_unknown_fields()) {
+ mutable_unknown_fields()->Swap(other->mutable_unknown_fields());
+ }
+ }
+
+ inline void* raw_arena_ptr() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ return ptr_;
+ }
+
+ private:
+ void* ptr_;
+
+ // Tagged pointer implementation.
+ enum {
+ // ptr_ is an Arena*.
+ kTagArena = 0,
+ // ptr_ is a Container*.
+ kTagContainer = 1,
+ };
+ static const intptr_t kPtrTagMask = 1;
+ static const intptr_t kPtrValueMask = ~kPtrTagMask;
+
+ // Accessors for pointer tag and pointer value.
+ inline int PtrTag() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
+ }
+
+ template<typename T> T* PtrValue() const {
+ return reinterpret_cast<T*>(
+ reinterpret_cast<intptr_t>(ptr_) & kPtrValueMask);
+ }
+
+ // If ptr_'s tag is kTagContainer, it points to an instance of this struct.
+ struct Container {
+ UnknownFieldSet unknown_fields_;
+ Arena* arena_;
+ };
+
+ UnknownFieldSet* mutable_unknown_fields_slow() GOOGLE_ATTRIBUTE_NOINLINE {
+ Arena* my_arena = arena();
+ Container* container = Arena::Create<Container>(my_arena);
+ ptr_ = reinterpret_cast<void*>(
+ reinterpret_cast<intptr_t>(container) | kTagContainer);
+ container->arena_ = my_arena;
+ return &(container->unknown_fields_);
+ }
+};
+
+// Temporary compatibility typedef. Remove once this is released in components
+// and upb CL is submitted.
+typedef InternalMetadataWithArena InternalMetadata;
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_METADATA_H__
diff --git a/src/google/protobuf/new_delete_capture.cc b/src/google/protobuf/new_delete_capture.cc
new file mode 100644
index 00000000..baf42ffe
--- /dev/null
+++ b/src/google/protobuf/new_delete_capture.cc
@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file exists for testing allocation behavior when using arenas by hooking
+// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.cc.
+
+#include <google/protobuf/new_delete_capture.h>
+
+#include <pthread.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/malloc_hook.h>
+#include <google/protobuf/stubs/spinlock.h>
+
+namespace google {
+namespace {
+
+pthread_t gthread;
+protobuf_unittest::NewDeleteCapture *ghooked_instance = NULL;
+SpinLock gspinlock(base::LINKER_INITIALIZED);
+
+} // namespace
+
+namespace protobuf_unittest {
+
+NewDeleteCapture::NewDeleteCapture()
+ : alloc_count_(0),
+ alloc_size_(0),
+ alloc_ptr_(NULL),
+ free_count_(0),
+ free_ptr_(NULL) {}
+
+NewDeleteCapture::~NewDeleteCapture() { Unhook(); }
+
+void NewDeleteCapture::Reset() {
+ alloc_count_ = 0;
+ alloc_size_ = 0;
+ free_count_ = 0;
+ alloc_ptr_ = NULL;
+ free_ptr_ = NULL;
+}
+
+bool NewDeleteCapture::Hook(bool reset) {
+ SpinLockHolder spinlock(&gspinlock);
+ if (ghooked_instance != this) {
+ GOOGLE_CHECK(ghooked_instance == NULL)
+ << " NewDeleteCapture can have only 1 active instance";
+ GOOGLE_CHECK(MallocHook::AddNewHook(NewHook));
+ GOOGLE_CHECK(MallocHook::AddDeleteHook(DeleteHook));
+ gthread = pthread_self();
+ ghooked_instance = this;
+ if (reset) {
+ Reset();
+ }
+ return true;
+ }
+ return false;
+}
+
+bool NewDeleteCapture::Unhook() {
+ SpinLockHolder spinlock(&gspinlock);
+ if (ghooked_instance == this) {
+ gthread = pthread_t();
+ ghooked_instance = NULL;
+ GOOGLE_CHECK(MallocHook::RemoveDeleteHook(DeleteHook));
+ GOOGLE_CHECK(MallocHook::RemoveNewHook(NewHook));
+ return true;
+ }
+ return false;
+}
+
+void NewDeleteCapture::NewHook(const void *ptr, size_t size) {
+ SpinLockHolder spinlock(&gspinlock);
+ if (gthread == pthread_self()) {
+ auto &rthis = *ghooked_instance;
+ if (++rthis.alloc_count_ == 1) {
+ rthis.alloc_size_ = size;
+ rthis.alloc_ptr_ = ptr;
+ }
+ }
+}
+
+void NewDeleteCapture::DeleteHook(const void *ptr) {
+ SpinLockHolder spinlock(&gspinlock);
+ if (gthread == pthread_self()) {
+ auto &rthis = *ghooked_instance;
+ if (++rthis.free_count_ == 1) {
+ rthis.free_ptr_ = ptr;
+ }
+ }
+}
+
+} // namespace protobuf_unittest
+} // namespace google
diff --git a/src/google/protobuf/new_delete_capture.h b/src/google/protobuf/new_delete_capture.h
new file mode 100644
index 00000000..4ab550cd
--- /dev/null
+++ b/src/google/protobuf/new_delete_capture.h
@@ -0,0 +1,175 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file exists for testing allocation behavior when using arenas by hooking
+// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.h.
+//
+// Copyright 2014 Google Inc.
+//
+// Author: Martijn Vels
+//
+// A simple class that captures memory allocations and deletes.
+//
+// This class is private to //strings and only intended to be used inside
+// unit tests. It uses the MallocHook functionality to capture memory
+// allocation and delete operations performed by the thread that activated
+// a hook on a specific instance.
+//
+// The class captures the following information:
+// - Total allocation count (new, malloc(), etc).
+// - Total delete count (delete, free(), etc).
+// - The size and returned pointer for the first memory allocation.
+// - The pointer for the first delete operation.
+//
+// The latter 2 infos (size and pointer of first new/delete) are usefull in
+// cases where you can closely scope a Hook() / Unhook sequence around a
+// specific piece of code where you expect no more than 1 pair of new / delete
+// operations.
+//
+// Sample usage where we expect a single unique alloc / free:
+//
+// NewDeleteCapture capture_alloc;
+// const void *ptr;
+// {
+// capture_alloc.Hook();
+// MyAllocationClass my_instance(size);
+// capture_alloc.Unhook();
+//
+// ptr = my_instance.ptr();
+// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
+// GOOGLE_CHECK_EQ(0, capture_alloc.free_count());
+// GOOGLE_CHECK_EQ(size, capture_alloc.alloc_size());
+// GOOGLE_CHECK_EQ(ptr, capture_alloc.alloc_ptr());
+//
+// capture_alloc.Hook();
+// }
+// capture_alloc.Unhook();
+// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
+// GOOGLE_CHECK_EQ(1, capture_alloc.free_count());
+// GOOGLE_CHECK_EQ(ptr, capture_alloc.free_ptr());
+//
+// You can only have one NewDeleteCapture instance active at the time. It is
+// total valid to have many instances in different threads, but only one
+// instance can have a hook active.
+//
+// Legal:
+//
+// NewDeleteCapture capture_alloc1;
+// NewDeleteCapture capture_alloc2;
+// const void *ptr;
+// {
+// capture_alloc1.Hook();
+// MyAllocationClass my_instance(size);
+// capture_alloc1.Unhook();
+//
+// capture_alloc2.Hook();
+// my_instance.reset(size);
+// capture_alloc2.Unhook();
+// }
+//
+// Illegal:
+//
+// NewDeleteCapture capture_alloc1;
+// NewDeleteCapture capture_alloc2;
+// const void *ptr;
+// {
+// capture_alloc1.Hook();
+// MyAllocationClass my_instance(size);
+//
+// capture_alloc2.Hook();
+// my_instance.reset(size);
+//
+// capture_alloc1.Unhook();
+// capture_alloc2.Unhook();
+// }
+//
+#ifndef GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
+#define GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
+
+#include <stddef.h>
+
+namespace google {
+namespace protobuf_unittest {
+
+class NewDeleteCapture {
+ public:
+ // Creates a new inactive capture instance
+ NewDeleteCapture();
+
+ // Destroys this capture instance. Active hooks are automatically removed.
+ ~NewDeleteCapture();
+
+ // Activates a hook on this instance. If reset is true (the default), all
+ // internal counters will be reset to 0.
+ // Returns true if the hook was activated, false if this instance already
+ // owned the hook.
+ // Requires no other instance owning the hook (check fails)
+ bool Hook(bool reset = true);
+
+ // De-activate the hook on this instance.
+ // Returns true if the hook was removed, false if this instance did not own
+ // the hook.
+ bool Unhook();
+
+ // Resets all counters to 0
+ void Reset();
+
+ // Returns the total number of allocations (new, malloc(), etc)
+ size_t alloc_count() const { return alloc_count_; }
+
+ // Returns the total number of deletes (delete, free(), etc)
+ size_t free_count() const { return free_count_; }
+
+ // Returns the size of the first observed allocation
+ size_t alloc_size() const { return alloc_size_; }
+
+ // Returns the allocated ptr of the first observed allocation
+ const void *alloc_ptr() const { return alloc_ptr_; }
+
+ // Returns the ptr of the first observed delete
+ const void* free_ptr() const { return free_ptr_; }
+
+ private:
+ static void NewHook(const void *ptr, size_t size);
+ static void DeleteHook(const void *ptr);
+
+ private:
+ size_t alloc_count_;
+ size_t alloc_size_;
+ const void *alloc_ptr_;
+
+ size_t free_count_;
+ const void *free_ptr_;
+};
+
+} // namespace protobuf_unittest
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc
new file mode 100644
index 00000000..f248327c
--- /dev/null
+++ b/src/google/protobuf/no_field_presence_test.cc
@@ -0,0 +1,526 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string>
+
+#include <google/protobuf/unittest_no_field_presence.pb.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+// Helper: checks that all fields have default (zero/empty) values.
+void CheckDefaultValues(
+ const proto2_nofieldpresence_unittest::TestAllTypes& m) {
+ EXPECT_EQ(0, m.optional_int32());
+ EXPECT_EQ(0, m.optional_int64());
+ EXPECT_EQ(0, m.optional_uint32());
+ EXPECT_EQ(0, m.optional_uint64());
+ EXPECT_EQ(0, m.optional_sint32());
+ EXPECT_EQ(0, m.optional_sint64());
+ EXPECT_EQ(0, m.optional_fixed32());
+ EXPECT_EQ(0, m.optional_fixed64());
+ EXPECT_EQ(0, m.optional_sfixed32());
+ EXPECT_EQ(0, m.optional_sfixed64());
+ EXPECT_EQ(0, m.optional_float());
+ EXPECT_EQ(0, m.optional_double());
+ EXPECT_EQ(false, m.optional_bool());
+ EXPECT_EQ(0, m.optional_string().size());
+ EXPECT_EQ(0, m.optional_bytes().size());
+
+ EXPECT_EQ(false, m.has_optional_nested_message());
+ // accessor for message fields returns default instance when not present
+ EXPECT_EQ(0, m.optional_nested_message().bb());
+ EXPECT_EQ(false, m.has_optional_proto2_message());
+ // Embedded proto2 messages still have proto2 semantics, e.g. non-zero default
+ // values. Here the submessage is not present but its accessor returns the
+ // default instance.
+ EXPECT_EQ(41, m.optional_proto2_message().default_int32());
+ EXPECT_EQ(false, m.has_optional_foreign_message());
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_FOO,
+ m.optional_nested_enum());
+ EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_FOO,
+ m.optional_foreign_enum());
+
+
+ EXPECT_EQ(0, m.repeated_int32_size());
+ EXPECT_EQ(0, m.repeated_int64_size());
+ EXPECT_EQ(0, m.repeated_uint32_size());
+ EXPECT_EQ(0, m.repeated_uint64_size());
+ EXPECT_EQ(0, m.repeated_sint32_size());
+ EXPECT_EQ(0, m.repeated_sint64_size());
+ EXPECT_EQ(0, m.repeated_fixed32_size());
+ EXPECT_EQ(0, m.repeated_fixed64_size());
+ EXPECT_EQ(0, m.repeated_sfixed32_size());
+ EXPECT_EQ(0, m.repeated_sfixed64_size());
+ EXPECT_EQ(0, m.repeated_float_size());
+ EXPECT_EQ(0, m.repeated_double_size());
+ EXPECT_EQ(0, m.repeated_bool_size());
+ EXPECT_EQ(0, m.repeated_string_size());
+ EXPECT_EQ(0, m.repeated_bytes_size());
+ EXPECT_EQ(0, m.repeated_nested_message_size());
+ EXPECT_EQ(0, m.repeated_foreign_message_size());
+ EXPECT_EQ(0, m.repeated_proto2_message_size());
+ EXPECT_EQ(0, m.repeated_nested_enum_size());
+ EXPECT_EQ(0, m.repeated_foreign_enum_size());
+ EXPECT_EQ(0, m.repeated_lazy_message_size());
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::ONEOF_FIELD_NOT_SET,
+ m.oneof_field_case());
+}
+
+void FillValues(proto2_nofieldpresence_unittest::TestAllTypes* m) {
+ m->set_optional_int32(100);
+ m->set_optional_int64(101);
+ m->set_optional_uint32(102);
+ m->set_optional_uint64(103);
+ m->set_optional_sint32(104);
+ m->set_optional_sint64(105);
+ m->set_optional_fixed32(106);
+ m->set_optional_fixed64(107);
+ m->set_optional_sfixed32(108);
+ m->set_optional_sfixed64(109);
+ m->set_optional_float(110.0);
+ m->set_optional_double(111.0);
+ m->set_optional_bool(true);
+ m->set_optional_string("asdf");
+ m->set_optional_bytes("jkl;");
+ m->mutable_optional_nested_message()->set_bb(42);
+ m->mutable_optional_foreign_message()->set_c(43);
+ m->mutable_optional_proto2_message()->set_optional_int32(44);
+ m->set_optional_nested_enum(
+ proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->set_optional_foreign_enum(
+ proto2_nofieldpresence_unittest::FOREIGN_BAZ);
+ m->mutable_optional_lazy_message()->set_bb(45);
+ m->add_repeated_int32(100);
+ m->add_repeated_int64(101);
+ m->add_repeated_uint32(102);
+ m->add_repeated_uint64(103);
+ m->add_repeated_sint32(104);
+ m->add_repeated_sint64(105);
+ m->add_repeated_fixed32(106);
+ m->add_repeated_fixed64(107);
+ m->add_repeated_sfixed32(108);
+ m->add_repeated_sfixed64(109);
+ m->add_repeated_float(110.0);
+ m->add_repeated_double(111.0);
+ m->add_repeated_bool(true);
+ m->add_repeated_string("asdf");
+ m->add_repeated_bytes("jkl;");
+ m->add_repeated_nested_message()->set_bb(46);
+ m->add_repeated_foreign_message()->set_c(47);
+ m->add_repeated_proto2_message()->set_optional_int32(48);
+ m->add_repeated_nested_enum(
+ proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->add_repeated_foreign_enum(
+ proto2_nofieldpresence_unittest::FOREIGN_BAZ);
+ m->add_repeated_lazy_message()->set_bb(49);
+
+ m->set_oneof_uint32(1);
+ m->mutable_oneof_nested_message()->set_bb(50);
+ m->set_oneof_string("test"); // only this one remains set
+}
+
+void CheckNonDefaultValues(
+const proto2_nofieldpresence_unittest::TestAllTypes& m) {
+ EXPECT_EQ(100, m.optional_int32());
+ EXPECT_EQ(101, m.optional_int64());
+ EXPECT_EQ(102, m.optional_uint32());
+ EXPECT_EQ(103, m.optional_uint64());
+ EXPECT_EQ(104, m.optional_sint32());
+ EXPECT_EQ(105, m.optional_sint64());
+ EXPECT_EQ(106, m.optional_fixed32());
+ EXPECT_EQ(107, m.optional_fixed64());
+ EXPECT_EQ(108, m.optional_sfixed32());
+ EXPECT_EQ(109, m.optional_sfixed64());
+ EXPECT_EQ(110.0, m.optional_float());
+ EXPECT_EQ(111.0, m.optional_double());
+ EXPECT_EQ(true, m.optional_bool());
+ EXPECT_EQ("asdf", m.optional_string());
+ EXPECT_EQ("jkl;", m.optional_bytes());
+ EXPECT_EQ(true, m.has_optional_nested_message());
+ EXPECT_EQ(42, m.optional_nested_message().bb());
+ EXPECT_EQ(true, m.has_optional_foreign_message());
+ EXPECT_EQ(43, m.optional_foreign_message().c());
+ EXPECT_EQ(true, m.has_optional_proto2_message());
+ EXPECT_EQ(44, m.optional_proto2_message().optional_int32());
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.optional_nested_enum());
+ EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ,
+ m.optional_foreign_enum());
+ EXPECT_EQ(true, m.has_optional_lazy_message());
+ EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+ EXPECT_EQ(1, m.repeated_int32_size());
+ EXPECT_EQ(100, m.repeated_int32(0));
+ EXPECT_EQ(1, m.repeated_int64_size());
+ EXPECT_EQ(101, m.repeated_int64(0));
+ EXPECT_EQ(1, m.repeated_uint32_size());
+ EXPECT_EQ(102, m.repeated_uint32(0));
+ EXPECT_EQ(1, m.repeated_uint64_size());
+ EXPECT_EQ(103, m.repeated_uint64(0));
+ EXPECT_EQ(1, m.repeated_sint32_size());
+ EXPECT_EQ(104, m.repeated_sint32(0));
+ EXPECT_EQ(1, m.repeated_sint64_size());
+ EXPECT_EQ(105, m.repeated_sint64(0));
+ EXPECT_EQ(1, m.repeated_fixed32_size());
+ EXPECT_EQ(106, m.repeated_fixed32(0));
+ EXPECT_EQ(1, m.repeated_fixed64_size());
+ EXPECT_EQ(107, m.repeated_fixed64(0));
+ EXPECT_EQ(1, m.repeated_sfixed32_size());
+ EXPECT_EQ(108, m.repeated_sfixed32(0));
+ EXPECT_EQ(1, m.repeated_sfixed64_size());
+ EXPECT_EQ(109, m.repeated_sfixed64(0));
+ EXPECT_EQ(1, m.repeated_float_size());
+ EXPECT_EQ(110.0, m.repeated_float(0));
+ EXPECT_EQ(1, m.repeated_double_size());
+ EXPECT_EQ(111.0, m.repeated_double(0));
+ EXPECT_EQ(1, m.repeated_bool_size());
+ EXPECT_EQ(true, m.repeated_bool(0));
+ EXPECT_EQ(1, m.repeated_string_size());
+ EXPECT_EQ("asdf", m.repeated_string(0));
+ EXPECT_EQ(1, m.repeated_bytes_size());
+ EXPECT_EQ("jkl;", m.repeated_bytes(0));
+ EXPECT_EQ(1, m.repeated_nested_message_size());
+ EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+ EXPECT_EQ(1, m.repeated_foreign_message_size());
+ EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+ EXPECT_EQ(1, m.repeated_proto2_message_size());
+ EXPECT_EQ(48, m.repeated_proto2_message(0).optional_int32());
+ EXPECT_EQ(1, m.repeated_nested_enum_size());
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.repeated_nested_enum(0));
+ EXPECT_EQ(1, m.repeated_foreign_enum_size());
+ EXPECT_EQ(proto2_nofieldpresence_unittest::FOREIGN_BAZ,
+ m.repeated_foreign_enum(0));
+ EXPECT_EQ(1, m.repeated_lazy_message_size());
+ EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofString,
+ m.oneof_field_case());
+ EXPECT_EQ("test", m.oneof_string());
+}
+
+TEST(NoFieldPresenceTest, BasicMessageTest) {
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+ // Check default values, fill all fields, check values. We just want to
+ // exercise the basic getters/setter paths here to make sure no
+ // field-presence-related changes broke these.
+ CheckDefaultValues(message);
+ FillValues(&message);
+ CheckNonDefaultValues(message);
+
+ // Clear() should be equivalent to getting a freshly-constructed message.
+ message.Clear();
+ CheckDefaultValues(message);
+}
+
+TEST(NoFieldPresenceTest, MessageFieldPresenceTest) {
+ // check that presence still works properly for message fields.
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+ EXPECT_EQ(false, message.has_optional_nested_message());
+ // Getter should fetch default instance, and not cause the field to become
+ // present.
+ EXPECT_EQ(0, message.optional_nested_message().bb());
+ EXPECT_EQ(false, message.has_optional_nested_message());
+ message.mutable_optional_nested_message()->set_bb(42);
+ EXPECT_EQ(true, message.has_optional_nested_message());
+ message.clear_optional_nested_message();
+ EXPECT_EQ(false, message.has_optional_nested_message());
+
+ // Likewise for a lazy message field.
+ EXPECT_EQ(false, message.has_optional_lazy_message());
+ // Getter should fetch default instance, and not cause the field to become
+ // present.
+ EXPECT_EQ(0, message.optional_lazy_message().bb());
+ EXPECT_EQ(false, message.has_optional_lazy_message());
+ message.mutable_optional_lazy_message()->set_bb(42);
+ EXPECT_EQ(true, message.has_optional_lazy_message());
+ message.clear_optional_lazy_message();
+ EXPECT_EQ(false, message.has_optional_lazy_message());
+}
+
+TEST(NoFieldPresenceTest, ReflectionHasFieldTest) {
+ // check that HasField reports true on all scalar fields. Check that it
+ // behaves properly for message fields.
+
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* desc = message.GetDescriptor();
+
+ // Check initial state: scalars not present (due to need to be consistent with
+ // MergeFrom()), message fields not present, oneofs not present.
+ for (int i = 0; i < desc->field_count(); i++) {
+ const google::protobuf::FieldDescriptor* field = desc->field(i);
+ if (field->is_repeated()) continue;
+ EXPECT_EQ(false, r->HasField(message, field));
+ }
+
+ // Fill all fields, expect everything to report true (check oneofs below).
+ FillValues(&message);
+ for (int i = 0; i < desc->field_count(); i++) {
+ const google::protobuf::FieldDescriptor* field = desc->field(i);
+ if (field->is_repeated() || field->containing_oneof()) {
+ continue;
+ }
+ if (field->options().ctype() != google::protobuf::FieldOptions::STRING) {
+ continue;
+ }
+ EXPECT_EQ(true, r->HasField(message, field));
+ }
+
+ message.Clear();
+
+ // Check zero/empty-means-not-present semantics.
+ const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName(
+ "optional_int32");
+ const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName(
+ "optional_double");
+ const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName(
+ "optional_string");
+
+ EXPECT_EQ(false, r->HasField(message, field_int32));
+ EXPECT_EQ(false, r->HasField(message, field_double));
+ EXPECT_EQ(false, r->HasField(message, field_string));
+
+ message.set_optional_int32(42);
+ EXPECT_EQ(true, r->HasField(message, field_int32));
+ message.set_optional_int32(0);
+ EXPECT_EQ(false, r->HasField(message, field_int32));
+
+ message.set_optional_double(42.0);
+ EXPECT_EQ(true, r->HasField(message, field_double));
+ message.set_optional_double(0.0);
+ EXPECT_EQ(false, r->HasField(message, field_double));
+
+ message.set_optional_string("test");
+ EXPECT_EQ(true, r->HasField(message, field_string));
+ message.set_optional_string("");
+ EXPECT_EQ(false, r->HasField(message, field_string));
+}
+
+TEST(NoFieldPresenceTest, HasFieldOneofsTest) {
+ // check that HasField behaves properly for oneofs.
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* desc = message.GetDescriptor();
+ const google::protobuf::FieldDescriptor* desc_oneof_uint32 =
+ desc->FindFieldByName("oneof_uint32");
+ const google::protobuf::FieldDescriptor* desc_oneof_nested_message =
+ desc->FindFieldByName("oneof_nested_message");
+ const google::protobuf::FieldDescriptor* desc_oneof_string =
+ desc->FindFieldByName("oneof_string");
+ GOOGLE_CHECK_NOTNULL(desc_oneof_uint32);
+ GOOGLE_CHECK_NOTNULL(desc_oneof_nested_message);
+ GOOGLE_CHECK_NOTNULL(desc_oneof_string);
+
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_nested_message));
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_string));
+
+ message.set_oneof_string("test");
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_nested_message));
+ EXPECT_EQ(true, r->HasField(message, desc_oneof_string));
+ message.mutable_oneof_nested_message()->set_bb(42);
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+ EXPECT_EQ(true, r->HasField(message, desc_oneof_nested_message));
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_string));
+
+ message.Clear();
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_uint32));
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_nested_message));
+ EXPECT_EQ(false, r->HasField(message, desc_oneof_string));
+}
+
+TEST(NoFieldPresenceTest, DontSerializeDefaultValuesTest) {
+ // check that serialized data contains only non-zero numeric fields/non-empty
+ // string/byte fields.
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+ string output;
+
+ // All default values -> no output.
+ message.SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+
+ // Zero values -> still no output.
+ message.set_optional_int32(0);
+ message.set_optional_int64(0);
+ message.set_optional_uint32(0);
+ message.set_optional_uint64(0);
+ message.set_optional_sint32(0);
+ message.set_optional_sint64(0);
+ message.set_optional_fixed32(0);
+ message.set_optional_fixed64(0);
+ message.set_optional_sfixed32(0);
+ message.set_optional_sfixed64(0);
+ message.set_optional_float(0);
+ message.set_optional_double(0);
+ message.set_optional_bool(0);
+ message.set_optional_string("");
+ message.set_optional_bytes("");
+ message.set_optional_nested_enum(
+ proto2_nofieldpresence_unittest::TestAllTypes_NestedEnum_FOO); // first enum entry
+ message.set_optional_foreign_enum(
+ proto2_nofieldpresence_unittest::FOREIGN_FOO); // first enum entry
+
+ message.SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+
+ message.set_optional_int32(1);
+ message.SerializeToString(&output);
+ EXPECT_EQ(2, output.size());
+ EXPECT_EQ("\x08\x01", output);
+
+ message.set_optional_int32(0);
+ message.SerializeToString(&output);
+ EXPECT_EQ(0, output.size());
+}
+
+TEST(NoFieldPresenceTest, MergeFromIfNonzeroTest) {
+ // check that MergeFrom copies if nonzero/nondefault only.
+ proto2_nofieldpresence_unittest::TestAllTypes source;
+ proto2_nofieldpresence_unittest::TestAllTypes dest;
+
+ dest.set_optional_int32(42);
+ dest.set_optional_string("test");
+ source.set_optional_int32(0);
+ source.set_optional_string("");
+ // MergeFrom() copies only if present in serialization, i.e., non-zero.
+ dest.MergeFrom(source);
+ EXPECT_EQ(42, dest.optional_int32());
+ EXPECT_EQ("test", dest.optional_string());
+
+ source.set_optional_int32(84);
+ source.set_optional_string("test2");
+ dest.MergeFrom(source);
+ EXPECT_EQ(84, dest.optional_int32());
+ EXPECT_EQ("test2", dest.optional_string());
+}
+
+TEST(NoFieldPresenceTest, IsInitializedTest) {
+ // Check that IsInitialized works properly.
+ proto2_nofieldpresence_unittest::TestProto2Required message;
+
+ EXPECT_EQ(true, message.IsInitialized());
+ message.mutable_proto2()->set_a(1);
+ EXPECT_EQ(false, message.IsInitialized());
+ message.mutable_proto2()->set_b(1);
+ EXPECT_EQ(false, message.IsInitialized());
+ message.mutable_proto2()->set_c(1);
+ EXPECT_EQ(true, message.IsInitialized());
+}
+
+TEST(NoFieldPresenceTest, LazyMessageFieldHasBit) {
+ // Check that has-bit interaction with lazy message works (has-bit before and
+ // after lazy decode).
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* desc = message.GetDescriptor();
+ const google::protobuf::FieldDescriptor* field = desc->FindFieldByName(
+ "optional_lazy_message");
+ GOOGLE_CHECK_NOTNULL(field);
+
+ EXPECT_EQ(false, message.has_optional_lazy_message());
+ EXPECT_EQ(false, r->HasField(message, field));
+
+ message.mutable_optional_lazy_message()->set_bb(42);
+ EXPECT_EQ(true, message.has_optional_lazy_message());
+ EXPECT_EQ(true, r->HasField(message, field));
+
+ // Serialize and parse with a new message object so that lazy field on new
+ // object is in unparsed state.
+ string output;
+ message.SerializeToString(&output);
+ proto2_nofieldpresence_unittest::TestAllTypes message2;
+ message2.ParseFromString(output);
+
+ EXPECT_EQ(true, message2.has_optional_lazy_message());
+ EXPECT_EQ(true, r->HasField(message2, field));
+
+ // Access field to force lazy parse.
+ EXPECT_EQ(42, message.optional_lazy_message().bb());
+ EXPECT_EQ(true, message2.has_optional_lazy_message());
+ EXPECT_EQ(true, r->HasField(message2, field));
+}
+
+TEST(NoFieldPresenceTest, OneofPresence) {
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+ // oneof fields still have field presence -- ensure that this goes on the wire
+ // even though its value is the empty string.
+ message.set_oneof_string("");
+ string serialized;
+ message.SerializeToString(&serialized);
+ // Tag: 113 --> tag is (113 << 3) | 2 (length delimited) = 906
+ // varint: 0x8a 0x07
+ // Length: 0x00
+ EXPECT_EQ(3, serialized.size());
+ EXPECT_EQ(static_cast<char>(0x8a), serialized.at(0));
+ EXPECT_EQ(static_cast<char>(0x07), serialized.at(1));
+ EXPECT_EQ(static_cast<char>(0x00), serialized.at(2));
+
+ message.Clear();
+ EXPECT_TRUE(message.ParseFromString(serialized));
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofString,
+ message.oneof_field_case());
+
+ // Also test int32 and enum fields.
+ message.Clear();
+ message.set_oneof_uint32(0); // would not go on wire if ordinary field.
+ message.SerializeToString(&serialized);
+ EXPECT_EQ(3, serialized.size());
+ EXPECT_TRUE(message.ParseFromString(serialized));
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofUint32,
+ message.oneof_field_case());
+
+ message.Clear();
+ message.set_oneof_enum(proto2_nofieldpresence_unittest::
+ TestAllTypes_NestedEnum_FOO); // default value.
+ message.SerializeToString(&serialized);
+ EXPECT_EQ(3, serialized.size());
+ EXPECT_TRUE(message.ParseFromString(serialized));
+ EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofEnum,
+ message.oneof_field_case());
+
+ message.Clear();
+ message.set_oneof_string("test");
+ message.clear_oneof_string();
+ EXPECT_EQ(0, message.ByteSize());
+}
+
+} // namespace
+} // namespace protobuf
+
+} // namespace google
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
new file mode 100644
index 00000000..e988a5cb
--- /dev/null
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -0,0 +1,230 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_preserve_unknown_enum.pb.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/descriptor.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+void FillMessage(
+ proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
+ message->set_e(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ message->add_repeated_e(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ message->add_repeated_packed_e(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ message->set_oneof_e_1(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA);
+}
+
+void CheckMessage(
+ const proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
+ EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ message.e());
+ EXPECT_EQ(1, message.repeated_e_size());
+ EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ message.repeated_e(0));
+ EXPECT_EQ(1, message.repeated_packed_e_size());
+ EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ message.repeated_packed_e(0));
+ EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ message.oneof_e_1());
+}
+
+void CheckMessage(
+ const proto2_preserve_unknown_enum_unittest::MyMessage& message) {
+ EXPECT_EQ(static_cast<int>(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ static_cast<int>(message.e()));
+ EXPECT_EQ(1, message.repeated_e_size());
+ EXPECT_EQ(static_cast<int>(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ static_cast<int>(message.repeated_e(0)));
+ EXPECT_EQ(1, message.repeated_packed_e_size());
+ EXPECT_EQ(static_cast<int>(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ static_cast<int>(message.repeated_packed_e(0)));
+ EXPECT_EQ(static_cast<int>(
+ proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ static_cast<int>(message.oneof_e_1()));
+}
+
+} // anonymous namespace
+
+// Test that parsing preserves an unknown value in the enum field and does not
+// punt it to the UnknownFieldSet.
+TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) {
+ proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ FillMessage(&orig_message);
+ string serialized;
+ orig_message.SerializeToString(&serialized);
+
+ proto2_preserve_unknown_enum_unittest::MyMessage message;
+ EXPECT_EQ(true, message.ParseFromString(serialized));
+ CheckMessage(message);
+
+ serialized.clear();
+ message.SerializeToString(&serialized);
+ EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+ CheckMessage(orig_message);
+}
+
+// Test that reflection based implementation also keeps unknown enum values and
+// doesn't put them into UnknownFieldSet.
+TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
+ proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ FillMessage(&orig_message);
+ string serialized = orig_message.SerializeAsString();
+
+ google::protobuf::DynamicMessageFactory factory;
+ scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
+ proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+ EXPECT_EQ(true, message->ParseFromString(serialized));
+ message->DiscardUnknownFields();
+
+ serialized = message->SerializeAsString();
+ EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+ CheckMessage(orig_message);
+}
+
+// Test that reflection provides EnumValueDescriptors for unknown values.
+TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
+ proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ FillMessage(&orig_message);
+ string serialized;
+ orig_message.SerializeToString(&serialized);
+
+ proto2_preserve_unknown_enum_unittest::MyMessage message;
+ EXPECT_EQ(true, message.ParseFromString(serialized));
+ CheckMessage(message);
+
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* d = message.GetDescriptor();
+ const google::protobuf::FieldDescriptor* field = d->FindFieldByName("e");
+
+ // This should dynamically create an EnumValueDescriptor.
+ const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field);
+ EXPECT_EQ(enum_value->number(),
+ static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+
+ // Fetching value for a second time should return the same pointer.
+ const google::protobuf::EnumValueDescriptor* enum_value_second =
+ r->GetEnum(message, field);
+ EXPECT_EQ(enum_value, enum_value_second);
+
+ // Check the repeated case too.
+ const google::protobuf::FieldDescriptor* repeated_field =
+ d->FindFieldByName("repeated_e");
+ enum_value = r->GetRepeatedEnum(message, repeated_field, 0);
+ EXPECT_EQ(enum_value->number(),
+ static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+ // Should reuse the same EnumValueDescriptor, even for a different field.
+ EXPECT_EQ(enum_value, enum_value_second);
+
+ // We should be able to use the returned value descriptor to set a value on
+ // another message.
+ google::protobuf::Message* m = message.New();
+ r->SetEnum(m, field, enum_value);
+ EXPECT_EQ(enum_value, r->GetEnum(*m, field));
+ delete m;
+}
+
+// Test that the new integer-based enum reflection API works.
+TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) {
+ proto2_preserve_unknown_enum_unittest::MyMessage message;
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* d = message.GetDescriptor();
+
+ const google::protobuf::FieldDescriptor* singular_field = d->FindFieldByName("e");
+ const google::protobuf::FieldDescriptor* repeated_field =
+ d->FindFieldByName("repeated_e");
+
+ r->SetEnumValue(&message, singular_field, 42);
+ EXPECT_EQ(42, r->GetEnumValue(message, singular_field));
+ r->AddEnumValue(&message, repeated_field, 42);
+ r->AddEnumValue(&message, repeated_field, 42);
+ EXPECT_EQ(42, r->GetRepeatedEnumValue(message, repeated_field, 0));
+ r->SetRepeatedEnumValue(&message, repeated_field, 1, 84);
+ EXPECT_EQ(84, r->GetRepeatedEnumValue(message, repeated_field, 1));
+ const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message,
+ singular_field);
+ EXPECT_EQ(42, enum_value->number());
+}
+
+// Test that the EnumValue API works properly for proto2 messages as well.
+TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
+ protobuf_unittest::TestAllTypes message; // proto2 message
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* d = message.GetDescriptor();
+ const google::protobuf::FieldDescriptor* singular_field =
+ d->FindFieldByName("optional_nested_enum");
+ const google::protobuf::FieldDescriptor* repeated_field =
+ d->FindFieldByName("repeated_nested_enum");
+ // Add one element to the repeated field so that we can test
+ // SetRepeatedEnumValue.
+ const google::protobuf::EnumValueDescriptor* enum_value =
+ repeated_field->enum_type()->FindValueByName("BAR");
+ EXPECT_TRUE(enum_value != NULL);
+ r->AddEnum(&message, repeated_field, enum_value);
+
+ // Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to
+ // remain consistent with proto2 generated code.
+ EXPECT_DEBUG_DEATH({
+ r->SetEnumValue(&message, singular_field, 4242);
+ r->GetEnum(message, singular_field)->number();
+ }, "SetEnumValue accepts only valid integer values");
+ EXPECT_DEBUG_DEATH({
+ r->SetRepeatedEnumValue(&message, repeated_field, 0, 4242);
+ r->GetRepeatedEnum(message, repeated_field, 0);
+ }, "SetRepeatedEnumValue accepts only valid integer values");
+ EXPECT_DEBUG_DEATH({
+ r->AddEnumValue(&message, repeated_field, 4242);
+ r->GetRepeatedEnum(message, repeated_field, 1);
+ }, "AddEnumValue accepts only valid integer values");
+}
+
+TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) {
+ protobuf_unittest::TestAllTypes proto2_message;
+ proto2_preserve_unknown_enum_unittest::MyMessage new_message;
+
+ const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection();
+ const google::protobuf::Reflection* new_reflection = new_message.GetReflection();
+
+ EXPECT_FALSE(proto2_reflection->SupportsUnknownEnumValues());
+ EXPECT_TRUE(new_reflection->SupportsUnknownEnumValues());
+}
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
new file mode 100644
index 00000000..123e21ab
--- /dev/null
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -0,0 +1,185 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string>
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+#include <vector>
+
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_arena.pb.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+using proto3_arena_unittest::TestAllTypes;
+
+namespace protobuf {
+namespace {
+// We selectively set/check a few representative fields rather than all fields
+// as this test is only expected to cover the basics of arena support.
+void SetAllFields(TestAllTypes* m) {
+ m->set_optional_int32(100);
+ m->set_optional_string("asdf");
+ m->set_optional_bytes("jkl;");
+ m->mutable_optional_nested_message()->set_bb(42);
+ m->mutable_optional_foreign_message()->set_c(43);
+ m->set_optional_nested_enum(
+ proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->set_optional_foreign_enum(
+ proto3_arena_unittest::FOREIGN_BAZ);
+ m->mutable_optional_lazy_message()->set_bb(45);
+ m->add_repeated_int32(100);
+ m->add_repeated_string("asdf");
+ m->add_repeated_bytes("jkl;");
+ m->add_repeated_nested_message()->set_bb(46);
+ m->add_repeated_foreign_message()->set_c(47);
+ m->add_repeated_nested_enum(
+ proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ);
+ m->add_repeated_foreign_enum(
+ proto3_arena_unittest::FOREIGN_BAZ);
+ m->add_repeated_lazy_message()->set_bb(49);
+
+ m->set_oneof_uint32(1);
+ m->mutable_oneof_nested_message()->set_bb(50);
+ m->set_oneof_string("test"); // only this one remains set
+}
+
+void ExpectAllFieldsSet(const TestAllTypes& m) {
+ EXPECT_EQ(100, m.optional_int32());
+ EXPECT_EQ("asdf", m.optional_string());
+ EXPECT_EQ("jkl;", m.optional_bytes());
+ EXPECT_EQ(true, m.has_optional_nested_message());
+ EXPECT_EQ(42, m.optional_nested_message().bb());
+ EXPECT_EQ(true, m.has_optional_foreign_message());
+ EXPECT_EQ(43, m.optional_foreign_message().c());
+ EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.optional_nested_enum());
+ EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ,
+ m.optional_foreign_enum());
+ EXPECT_EQ(true, m.has_optional_lazy_message());
+ EXPECT_EQ(45, m.optional_lazy_message().bb());
+
+ EXPECT_EQ(1, m.repeated_int32_size());
+ EXPECT_EQ(100, m.repeated_int32(0));
+ EXPECT_EQ(1, m.repeated_string_size());
+ EXPECT_EQ("asdf", m.repeated_string(0));
+ EXPECT_EQ(1, m.repeated_bytes_size());
+ EXPECT_EQ("jkl;", m.repeated_bytes(0));
+ EXPECT_EQ(1, m.repeated_nested_message_size());
+ EXPECT_EQ(46, m.repeated_nested_message(0).bb());
+ EXPECT_EQ(1, m.repeated_foreign_message_size());
+ EXPECT_EQ(47, m.repeated_foreign_message(0).c());
+ EXPECT_EQ(1, m.repeated_nested_enum_size());
+ EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ,
+ m.repeated_nested_enum(0));
+ EXPECT_EQ(1, m.repeated_foreign_enum_size());
+ EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ,
+ m.repeated_foreign_enum(0));
+ EXPECT_EQ(1, m.repeated_lazy_message_size());
+ EXPECT_EQ(49, m.repeated_lazy_message(0).bb());
+
+ EXPECT_EQ(proto3_arena_unittest::TestAllTypes::kOneofString,
+ m.oneof_field_case());
+ EXPECT_EQ("test", m.oneof_string());
+}
+
+// In this file we only test some basic functionalities of arena support in
+// proto3 and expect the arena support to be fully tested in proto2 unittests
+// because proto3 shares most code with proto2.
+
+TEST(ArenaTest, Parsing) {
+ TestAllTypes original;
+ SetAllFields(&original);
+
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->ParseFromString(original.SerializeAsString());
+ ExpectAllFieldsSet(*arena_message);
+}
+
+TEST(ArenaTest, UnknownFields) {
+ TestAllTypes original;
+ SetAllFields(&original);
+
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->ParseFromString(original.SerializeAsString());
+ ExpectAllFieldsSet(*arena_message);
+
+ // In proto3 we can still get a pointer to the UnknownFieldSet through
+ // reflection API.
+ UnknownFieldSet* unknown_fields =
+ arena_message->GetReflection()->MutableUnknownFields(arena_message);
+ // We can modify this UnknownFieldSet.
+ unknown_fields->AddVarint(1, 2);
+ // But the change will never will serialized back.
+ ASSERT_EQ(original.ByteSize(), arena_message->ByteSize());
+ ASSERT_TRUE(
+ arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
+}
+
+TEST(ArenaTest, Swap) {
+ Arena arena1;
+ Arena arena2;
+
+ // Test Swap().
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ TestAllTypes* arena2_message = Arena::CreateMessage<TestAllTypes>(&arena2);
+ arena1_message->Swap(arena2_message);
+ EXPECT_EQ(&arena1, arena1_message->GetArena());
+ EXPECT_EQ(&arena2, arena2_message->GetArena());
+}
+
+TEST(ArenaTest, SetAllocatedMessage) {
+ Arena arena;
+ TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
+ nested->set_bb(118);
+ arena_message->set_allocated_optional_nested_message(nested);
+ EXPECT_EQ(118, arena_message->optional_nested_message().bb());
+}
+
+TEST(ArenaTest, ReleaseMessage) {
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->mutable_optional_nested_message()->set_bb(118);
+ scoped_ptr<TestAllTypes::NestedMessage> nested(
+ arena_message->release_optional_nested_message());
+ EXPECT_EQ(118, nested->bb());
+}
+
+} // namespace
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/proto_cast.h b/src/google/protobuf/proto_cast.h
new file mode 100644
index 00000000..e25c219f
--- /dev/null
+++ b/src/google/protobuf/proto_cast.h
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_PROTO_CAST_H__
+#define GOOGLE_PROTOBUF_UTIL_PROTO_CAST_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+// proto_cast<> is used to simulate over-the-wire conversion of one
+// proto message into another. This is primarily useful for unit tests
+// which validate the version-compatibility semantics of protobufs.
+// Usage is similar to C++-style typecasts:
+//
+// OldMessage old_message = /*...*/;
+// NewMessage new_message = proto_cast<NewMessage>(old_message);
+namespace google {
+template<typename NewProto,
+ typename OldProto>
+NewProto proto_cast(const OldProto& old_proto) {
+ string wire_format;
+ GOOGLE_CHECK(old_proto.SerializeToString(&wire_format));
+
+ NewProto new_proto;
+ GOOGLE_CHECK(new_proto.ParseFromString(wire_format));
+ return new_proto;
+}
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_PROTO_CAST_H__
diff --git a/src/google/protobuf/proto_cast_test.cc b/src/google/protobuf/proto_cast_test.cc
new file mode 100644
index 00000000..eb101eb6
--- /dev/null
+++ b/src/google/protobuf/proto_cast_test.cc
@@ -0,0 +1,60 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/util/proto_cast.h>
+
+#include <google/protobuf/util/unknown_enum_test.pb.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/gmock.h>
+
+namespace google {
+using google::protobuf::util::UpRevision;
+using google::protobuf::util::DownRevision;
+
+namespace {
+
+TEST(ProtoCastTest, V2KnownValue) {
+ UpRevision sender;
+ sender.set_value(UpRevision::NONDEFAULT_VALUE);
+
+ DownRevision receiver = proto_cast<DownRevision>(sender);
+ ASSERT_EQ(DownRevision::NONDEFAULT_VALUE, receiver.value());
+}
+
+TEST(ProtoCastTest, V2UnknownValue) {
+ UpRevision sender;
+ sender.set_value(UpRevision::NEW_VALUE);
+
+ DownRevision receiver = proto_cast<DownRevision>(sender);
+ ASSERT_EQ(DownRevision::DEFAULT_VALUE, receiver.value());
+}
+
+} // namespace
+} // namespace google
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
new file mode 100644
index 00000000..17d89a18
--- /dev/null
+++ b/src/google/protobuf/reflection.h
@@ -0,0 +1,306 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header defines the RepeatedFieldRef class template used to access
+// repeated fields with protobuf reflection API.
+#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
+#define GOOGLE_PROTOBUF_REFLECTION_H__
+
+#include <google/protobuf/message.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<typename T, typename Enable = void>
+struct RefTypeTraits;
+} // namespace internal
+
+template<typename T>
+RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
+ const Message& message, const FieldDescriptor* field) const {
+ return RepeatedFieldRef<T>(message, field);
+}
+
+template<typename T>
+MutableRepeatedFieldRef<T> Reflection::GetMutableRepeatedFieldRef(
+ Message* message, const FieldDescriptor* field) const {
+ return MutableRepeatedFieldRef<T>(message, field);
+}
+
+// RepeatedFieldRef definition for non-message types.
+template<typename T>
+class RepeatedFieldRef<
+ T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
+ typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
+ typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+ bool empty() const {
+ return accessor_->IsEmpty(data_);
+ }
+ int size() const {
+ return accessor_->Size(data_);
+ }
+ T Get(int index) const {
+ return accessor_->template Get<T>(data_, index);
+ }
+
+ typedef IteratorType iterator;
+ typedef IteratorType const_iterator;
+ iterator begin() const {
+ return iterator(data_, accessor_, true);
+ }
+ iterator end() const {
+ return iterator(data_, accessor_, false);
+ }
+
+ private:
+ friend class Reflection;
+ RepeatedFieldRef(
+ const Message& message,
+ const FieldDescriptor* field) {
+ const Reflection* reflection = message.GetReflection();
+ data_ = reflection->RepeatedFieldData(
+ const_cast<Message*>(&message), field,
+ internal::RefTypeTraits<T>::cpp_type, NULL);
+ accessor_ = reflection->RepeatedFieldAccessor(field);
+ }
+
+ const void* data_;
+ const AccessorType* accessor_;
+};
+
+// MutableRepeatedFieldRef definition for non-message types.
+template<typename T>
+class MutableRepeatedFieldRef<
+ T, typename internal::enable_if<!internal::is_base_of<Message, T>::value>::type> {
+ typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+ bool empty() const {
+ return accessor_->IsEmpty(data_);
+ }
+ int size() const {
+ return accessor_->Size(data_);
+ }
+ T Get(int index) const {
+ return accessor_->template Get<T>(data_, index);
+ }
+
+ void Set(int index, const T& value) const {
+ accessor_->template Set<T>(data_, index, value);
+ }
+ void Add(const T& value) const {
+ accessor_->template Add<T>(data_, value);
+ }
+ void RemoveLast() const {
+ accessor_->RemoveLast(data_);
+ }
+ void SwapElements(int index1, int index2) const {
+ accessor_->SwapElements(data_, index1, index2);
+ }
+ void Clear() const {
+ accessor_->Clear(data_);
+ }
+
+ void Swap(const MutableRepeatedFieldRef& other) const {
+ accessor_->Swap(data_, other.accessor_, other.data_);
+ }
+
+ template<typename Container>
+ void MergeFrom(const Container& container) const {
+ typedef typename Container::const_iterator Iterator;
+ for (Iterator it = container.begin(); it != container.end(); ++it) {
+ Add(*it);
+ }
+ }
+ template<typename Container>
+ void CopyFrom(const Container& container) const {
+ Clear();
+ MergeFrom(container);
+ }
+
+ private:
+ friend class Reflection;
+ MutableRepeatedFieldRef(
+ Message* message,
+ const FieldDescriptor* field) {
+ const Reflection* reflection = message->GetReflection();
+ data_ = reflection->RepeatedFieldData(
+ message, field, internal::RefTypeTraits<T>::cpp_type, NULL);
+ accessor_ = reflection->RepeatedFieldAccessor(field);
+ }
+
+ void* data_;
+ const AccessorType* accessor_;
+};
+
+// RepeatedFieldRef definition for message types.
+template<typename T>
+class RepeatedFieldRef<
+ T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+ typedef typename internal::RefTypeTraits<T>::iterator IteratorType;
+ typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+ bool empty() const {
+ return accessor_->IsEmpty(data_);
+ }
+ int size() const {
+ return accessor_->Size(data_);
+ }
+ // This method returns a reference to the underlying message object if it
+ // exists. If a message object doesn't exist (e.g., data stored in serialized
+ // form), scratch_space will be filled with the data and a reference to it
+ // will be returned.
+ //
+ // Example:
+ // RepeatedFieldRef<Message> h = ...
+ // unique_ptr<Message> scratch_space(h.NewMessage());
+ // const Message& item = h.Get(index, scratch_space.get());
+ const T& Get(int index, T* scratch_space) const {
+ return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
+ }
+ // Create a new message of the same type as the messages stored in this
+ // repeated field. Caller takes ownership of the returned object.
+ T* NewMessage() const {
+ return static_cast<T*>(default_instance_->New());
+ }
+
+ typedef IteratorType iterator;
+ typedef IteratorType const_iterator;
+ iterator begin() const {
+ return iterator(data_, accessor_, true, NewMessage());
+ }
+ iterator end() const {
+ return iterator(data_, accessor_, false, NewMessage());
+ }
+
+ private:
+ friend class Reflection;
+ RepeatedFieldRef(
+ const Message& message,
+ const FieldDescriptor* field) {
+ const Reflection* reflection = message.GetReflection();
+ data_ = reflection->RepeatedFieldData(
+ const_cast<Message*>(&message), field,
+ internal::RefTypeTraits<T>::cpp_type,
+ internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
+ accessor_ = reflection->RepeatedFieldAccessor(field);
+ default_instance_ =
+ reflection->GetMessageFactory()->GetPrototype(field->message_type());
+ }
+
+ const void* data_;
+ const AccessorType* accessor_;
+ const Message* default_instance_;
+};
+
+// MutableRepeatedFieldRef definition for non-message types.
+template<typename T>
+class MutableRepeatedFieldRef<
+ T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+ typedef typename internal::RefTypeTraits<T>::AccessorType AccessorType;
+
+ public:
+ bool empty() const {
+ return accessor_->IsEmpty(data_);
+ }
+ int size() const {
+ return accessor_->Size(data_);
+ }
+ // See comments for RepeatedFieldRef<Message>::Get()
+ const T& Get(int index, T* scratch_space) const {
+ return *static_cast<const T*>(accessor_->Get(data_, index, scratch_space));
+ }
+ // Create a new message of the same type as the messages stored in this
+ // repeated field. Caller takes ownership of the returned object.
+ T* NewMessage() const {
+ return static_cast<T*>(default_instance_->New());
+ }
+
+ void Set(int index, const T& value) const {
+ accessor_->Set(data_, index, &value);
+ }
+ void Add(const T& value) const {
+ accessor_->Add(data_, &value);
+ }
+ void RemoveLast() const {
+ accessor_->RemoveLast(data_);
+ }
+ void SwapElements(int index1, int index2) const {
+ accessor_->SwapElements(data_, index1, index2);
+ }
+ void Clear() const {
+ accessor_->Clear(data_);
+ }
+
+ void Swap(const MutableRepeatedFieldRef& other) const {
+ accessor_->Swap(data_, other.accessor_, other.data_);
+ }
+
+ template<typename Container>
+ void MergeFrom(const Container& container) const {
+ typedef typename Container::const_iterator Iterator;
+ for (Iterator it = container.begin(); it != container.end(); ++it) {
+ Add(*it);
+ }
+ }
+ template<typename Container>
+ void CopyFrom(const Container& container) const {
+ Clear();
+ MergeFrom(container);
+ }
+
+ private:
+ friend class Reflection;
+ MutableRepeatedFieldRef(
+ Message* message,
+ const FieldDescriptor* field) {
+ const Reflection* reflection = message->GetReflection();
+ data_ = reflection->RepeatedFieldData(
+ message, field, internal::RefTypeTraits<T>::cpp_type,
+ internal::RefTypeTraits<T>::GetMessageFieldDescriptor());
+ accessor_ = reflection->RepeatedFieldAccessor(field);
+ default_instance_ =
+ reflection->GetMessageFactory()->GetPrototype(field->message_type());
+ }
+
+ void* data_;
+ const AccessorType* accessor_;
+ const Message* default_instance_;
+};
+} // namespace protobuf
+} // namespace google
+
+// Implementation details for (Mutable)RepeatedFieldRef.
+#include <google/protobuf/repeated_field_reflection.h>
+
+#endif // GOOGLE_PROTOBUF_REFLECTION_H__
diff --git a/src/google/protobuf/reflection_internal.h b/src/google/protobuf/reflection_internal.h
new file mode 100644
index 00000000..e25e193c
--- /dev/null
+++ b/src/google/protobuf/reflection_internal.h
@@ -0,0 +1,310 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
+#define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
+
+#include <google/protobuf/reflection.h>
+#include <google/protobuf/repeated_field.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// A base class for RepeatedFieldAccessor implementations that can support
+// random-access efficiently. All iterator methods delegates the work to
+// corresponding random-access methods.
+class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor {
+ public:
+ virtual ~RandomAccessRepeatedFieldAccessor() {}
+
+ virtual Iterator* BeginIterator(const Field* data) const {
+ return PositionToIterator(0);
+ }
+ virtual Iterator* EndIterator(const Field* data) const {
+ return PositionToIterator(this->Size(data));
+ }
+ virtual Iterator* CopyIterator(const Field* data,
+ const Iterator* iterator) const {
+ return const_cast<Iterator*>(iterator);
+ }
+ virtual Iterator* AdvanceIterator(const Field* data,
+ Iterator* iterator) const {
+ return PositionToIterator(IteratorToPosition(iterator) + 1);
+ }
+ virtual bool EqualsIterator(const Field* data,
+ const Iterator* a,
+ const Iterator* b) const {
+ return a == b;
+ }
+ virtual void DeleteIterator(const Field* data, Iterator* iterator) const {
+ }
+ virtual const Value* GetIteratorValue(const Field* data,
+ const Iterator* iterator,
+ Value* scratch_space) const {
+ return Get(data, static_cast<int>(IteratorToPosition(iterator)),
+ scratch_space);
+ }
+
+ private:
+ static intptr_t IteratorToPosition(const Iterator* iterator) {
+ return reinterpret_cast<intptr_t>(iterator);
+ }
+ static Iterator* PositionToIterator(intptr_t position) {
+ return reinterpret_cast<Iterator*>(position);
+ }
+};
+
+// Base class for RepeatedFieldAccessor implementations that manipulates
+// RepeatedField<T>.
+template<typename T>
+class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor {
+ public:
+ RepeatedFieldWrapper() {}
+ virtual ~RepeatedFieldWrapper() {}
+ virtual bool IsEmpty(const Field* data) const {
+ return GetRepeatedField(data)->empty();
+ }
+ virtual int Size(const Field* data) const {
+ return GetRepeatedField(data)->size();
+ }
+ virtual const Value* Get(const Field* data, int index,
+ Value* scratch_space) const {
+ return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
+ }
+ virtual void Clear(Field* data) const {
+ MutableRepeatedField(data)->Clear();
+ }
+ virtual void Set(Field* data, int index, const Value* value) const {
+ MutableRepeatedField(data)->Set(index, ConvertToT(value));
+ }
+ virtual void Add(Field* data, const Value* value) const {
+ MutableRepeatedField(data)->Add(ConvertToT(value));
+ }
+ virtual void RemoveLast(Field* data) const {
+ MutableRepeatedField(data)->RemoveLast();
+ }
+ virtual void SwapElements(Field* data, int index1, int index2) const {
+ MutableRepeatedField(data)->SwapElements(index1, index2);
+ }
+
+ protected:
+ typedef RepeatedField<T> RepeatedFieldType;
+ static const RepeatedFieldType* GetRepeatedField(const Field* data) {
+ return reinterpret_cast<const RepeatedFieldType*>(data);
+ }
+ static RepeatedFieldType* MutableRepeatedField(Field* data) {
+ return reinterpret_cast<RepeatedFieldType*>(data);
+ }
+
+ // Convert an object recevied by this accessor to an object to be stored in
+ // the underlying RepeatedField.
+ virtual T ConvertToT(const Value* value) const = 0;
+
+ // Convert an object stored in RepeatedPtrField to an object that will be
+ // returned by this accessor. If the two objects have the same type (true
+ // for string fields with ctype=STRING), a pointer to the source object can
+ // be returned directly. Otherwise, data should be copied from value to
+ // scratch_space and scratch_space should be returned.
+ virtual const Value* ConvertFromT(const T& value,
+ Value* scratch_space) const = 0;
+};
+
+// Base class for RepeatedFieldAccessor implementations that manipulates
+// RepeatedPtrField<T>.
+template<typename T>
+class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor {
+ public:
+ RepeatedPtrFieldWrapper() {}
+ virtual ~RepeatedPtrFieldWrapper() {}
+ virtual bool IsEmpty(const Field* data) const {
+ return GetRepeatedField(data)->empty();
+ }
+ virtual int Size(const Field* data) const {
+ return GetRepeatedField(data)->size();
+ }
+ virtual const Value* Get(const Field* data, int index,
+ Value* scratch_space) const {
+ return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space);
+ }
+ virtual void Clear(Field* data) const {
+ MutableRepeatedField(data)->Clear();
+ }
+ virtual void Set(Field* data, int index, const Value* value) const {
+ ConvertToT(value, MutableRepeatedField(data)->Mutable(index));
+ }
+ virtual void Add(Field* data, const Value* value) const {
+ T* allocated = New(value);
+ ConvertToT(value, allocated);
+ MutableRepeatedField(data)->AddAllocated(allocated);
+ }
+ virtual void RemoveLast(Field* data) const {
+ MutableRepeatedField(data)->RemoveLast();
+ }
+ virtual void SwapElements(Field* data, int index1, int index2) const {
+ MutableRepeatedField(data)->SwapElements(index1, index2);
+ }
+
+ protected:
+ typedef RepeatedPtrField<T> RepeatedFieldType;
+ static const RepeatedFieldType* GetRepeatedField(const Field* data) {
+ return reinterpret_cast<const RepeatedFieldType*>(data);
+ }
+ static RepeatedFieldType* MutableRepeatedField(Field* data) {
+ return reinterpret_cast<RepeatedFieldType*>(data);
+ }
+
+ // Create a new T instance. For repeated message fields, T can be specified
+ // as google::protobuf::Message so we can't use "new T()" directly. In that case, value
+ // should be a message of the same type (it's ensured by the caller) and a
+ // new message object will be created using it.
+ virtual T* New(const Value* value) const = 0;
+
+ // Convert an object received by this accessor to an object that will be
+ // stored in the underlying RepeatedPtrField.
+ virtual void ConvertToT(const Value* value, T* result) const = 0;
+
+ // Convert an object stored in RepeatedPtrField to an object that will be
+ // returned by this accessor. If the two objects have the same type (true
+ // for string fields with ctype=STRING), a pointer to the source object can
+ // be returned directly. Otherwise, data should be copied from value to
+ // scratch_space and scratch_space should be returned.
+ virtual const Value* ConvertFromT(const T& value,
+ Value* scratch_space) const = 0;
+};
+
+// Default implementations of RepeatedFieldAccessor for primitive types.
+template<typename T>
+class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper<T> {
+ typedef void Field;
+ typedef void Value;
+ using RepeatedFieldWrapper<T>::MutableRepeatedField;
+
+ public:
+ RepeatedFieldPrimitiveAccessor() {}
+ virtual ~RepeatedFieldPrimitiveAccessor() {}
+ virtual void Swap(
+ Field* data,
+ const internal::RepeatedFieldAccessor* other_mutator,
+ Field* other_data) const {
+ // Currently RepeatedFieldPrimitiveAccessor is the only implementation of
+ // RepeatedFieldAccessor for primitive types. As we are using singletons
+ // for these accessors, here "other_mutator" must be "this".
+ GOOGLE_CHECK(this == other_mutator);
+ MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+ }
+
+ protected:
+ virtual T ConvertToT(const Value* value) const {
+ return *static_cast<const T*>(value);
+ }
+ virtual const Value* ConvertFromT(const T& value,
+ Value* scratch_space) const {
+ return static_cast<const Value*>(&value);
+ }
+};
+
+// Default implementation of RepeatedFieldAccessor for string fields with
+// ctype=STRING.
+class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper<string> {
+ typedef void Field;
+ typedef void Value;
+ using RepeatedFieldAccessor::Add;
+
+ public:
+ RepeatedPtrFieldStringAccessor() {}
+ virtual ~RepeatedPtrFieldStringAccessor() {}
+ virtual void Swap(
+ Field* data,
+ const internal::RepeatedFieldAccessor* other_mutator,
+ Field* other_data) const {
+ if (this == other_mutator) {
+ MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+ } else {
+ RepeatedPtrField<string> tmp;
+ tmp.Swap(MutableRepeatedField(data));
+ int other_size = other_mutator->Size(other_data);
+ for (int i = 0; i < other_size; ++i) {
+ Add<string>(data, other_mutator->Get<string>(other_data, i));
+ }
+ int size = Size(data);
+ other_mutator->Clear(other_data);
+ for (int i = 0; i < size; ++i) {
+ other_mutator->Add<string>(other_data, tmp.Get(i));
+ }
+ }
+ }
+
+ protected:
+ virtual string* New(const Value*) const {
+ return new string();
+ }
+ virtual void ConvertToT(const Value* value, string* result) const {
+ *result = *static_cast<const string*>(value);
+ }
+ virtual const Value* ConvertFromT(const string& value,
+ Value* scratch_space) const {
+ return static_cast<const Value*>(&value);
+ }
+};
+
+
+class RepeatedPtrFieldMessageAccessor
+ : public RepeatedPtrFieldWrapper<Message> {
+ typedef void Field;
+ typedef void Value;
+
+ public:
+ RepeatedPtrFieldMessageAccessor() {}
+ virtual ~RepeatedPtrFieldMessageAccessor() {}
+ virtual void Swap(
+ Field* data,
+ const internal::RepeatedFieldAccessor* other_mutator,
+ Field* other_data) const {
+ GOOGLE_CHECK(this == other_mutator);
+ MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data));
+ }
+
+ protected:
+ virtual Message* New(const Value* value) const {
+ return static_cast<const Message*>(value)->New();
+ }
+ virtual void ConvertToT(const Value* value, Message* result) const {
+ result->CopyFrom(*static_cast<const Message*>(value));
+ }
+ virtual const Value* ConvertFromT(const Message& value,
+ Value* scratch_space) const {
+ return static_cast<const Value*>(&value);
+ }
+};
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index b400732f..e5aedadc 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -42,42 +42,52 @@ namespace protobuf {
namespace internal {
-void RepeatedPtrFieldBase::Reserve(int new_size) {
- if (total_size_ >= new_size) return;
-
- void** old_elements = elements_;
- total_size_ = max(kMinRepeatedFieldAllocationSize,
- max(total_size_ * 2, new_size));
- elements_ = new void*[total_size_];
- if (old_elements != NULL) {
- memcpy(elements_, old_elements, allocated_size_ * sizeof(elements_[0]));
- delete [] old_elements;
+void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
+ int new_size = current_size_ + extend_amount;
+ if (total_size_ >= new_size) {
+ // N.B.: rep_ is non-NULL because extend_amount is always > 0, hence
+ // total_size must be non-zero since it is lower-bounded by new_size.
+ return &rep_->elements[current_size_];
+ }
+ Rep* old_rep = rep_;
+ Arena* arena = GetArenaNoVirtual();
+ new_size = max(kMinRepeatedFieldAllocationSize,
+ max(total_size_ * 2, new_size));
+ if (arena == NULL) {
+ rep_ = reinterpret_cast<Rep*>(
+ new char[kRepHeaderSize + sizeof(old_rep->elements[0])*new_size]);
+ } else {
+ rep_ = reinterpret_cast<Rep*>(
+ ::google::protobuf::Arena::CreateArray<char>(arena,
+ kRepHeaderSize + sizeof(old_rep->elements[0])*new_size));
+ }
+ total_size_ = new_size;
+ if (old_rep && old_rep->allocated_size > 0) {
+ memcpy(rep_->elements, old_rep->elements,
+ old_rep->allocated_size * sizeof(rep_->elements[0]));
+ rep_->allocated_size = old_rep->allocated_size;
+ } else {
+ rep_->allocated_size = 0;
+ }
+ if (arena == NULL) {
+ delete [] reinterpret_cast<char*>(old_rep);
}
+ return &rep_->elements[current_size_];
}
-void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
- if (this == other) return;
- void** swap_elements = elements_;
- int swap_current_size = current_size_;
- int swap_allocated_size = allocated_size_;
- int swap_total_size = total_size_;
-
- elements_ = other->elements_;
- current_size_ = other->current_size_;
- allocated_size_ = other->allocated_size_;
- total_size_ = other->total_size_;
-
- other->elements_ = swap_elements;
- other->current_size_ = swap_current_size;
- other->allocated_size_ = swap_allocated_size;
- other->total_size_ = swap_total_size;
+void RepeatedPtrFieldBase::Reserve(int new_size) {
+ if (new_size > current_size_) {
+ InternalExtend(new_size - current_size_);
+ }
}
-string* StringTypeHandlerBase::New() {
- return new string;
-}
-void StringTypeHandlerBase::Delete(string* value) {
- delete value;
+void RepeatedPtrFieldBase::CloseGap(int start, int num) {
+ if (rep_ == NULL) return;
+ // Close up a gap of "num" elements starting at offset "start".
+ for (int i = start + num; i < rep_->allocated_size; ++i)
+ rep_->elements[i - num] = rep_->elements[i];
+ current_size_ -= num;
+ rep_->allocated_size -= num;
}
} // namespace internal
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 816ea684..c21ba97f 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -53,8 +53,10 @@
#include <string>
#include <iterator>
+#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/type_traits.h>
+#include <google/protobuf/arena.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/message_lite.h>
@@ -104,6 +106,7 @@ template <typename Element>
class RepeatedField {
public:
RepeatedField();
+ explicit RepeatedField(Arena* arena);
RepeatedField(const RepeatedField& other);
template <typename Iter>
RepeatedField(Iter begin, const Iter& end);
@@ -153,9 +156,16 @@ class RepeatedField {
Element* mutable_data();
const Element* data() const;
- // Swap entire contents with "other".
+ // Swap entire contents with "other". If they are separate arenas then, copies
+ // data between each other.
void Swap(RepeatedField* other);
+ // Swap entire contents with "other". Should be called only if the caller can
+ // guarantee that both repeated fields are on the same arena or are on the
+ // heap. Swapping between different arenas is disallowed and caught by a
+ // GOOGLE_DCHECK (see API docs for details).
+ void UnsafeArenaSwap(RepeatedField* other);
+
// Swap two elements.
void SwapElements(int index1, int index2);
@@ -172,8 +182,10 @@ class RepeatedField {
iterator begin();
const_iterator begin() const;
+ const_iterator cbegin() const;
iterator end();
const_iterator end() const;
+ const_iterator cend() const;
// Reverse iterator support
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
@@ -195,20 +207,60 @@ class RepeatedField {
// sizeof(*this)
int SpaceUsedExcludingSelf() const;
+ // Remove the element referenced by position.
+ iterator erase(const_iterator position);
+
+ // Remove the elements in the range [first, last).
+ iterator erase(const_iterator first, const_iterator last);
+
+ // Get the Arena on which this RepeatedField stores its elements.
+ ::google::protobuf::Arena* GetArena() const {
+ return GetArenaNoVirtual();
+ }
+
private:
static const int kInitialSize = 0;
-
- Element* elements_;
- int current_size_;
- int total_size_;
+ // A note on the representation here (see also comment below for
+ // RepeatedPtrFieldBase's struct Rep):
+ //
+ // We maintain the same sizeof(RepeatedField) as before we added arena support
+ // so that we do not degrade performance by bloating memory usage. Directly
+ // adding an arena_ element to RepeatedField is quite costly. By using
+ // indirection in this way, we keep the same size when the RepeatedField is
+ // empty (common case), and add only an 8-byte header to the elements array
+ // when non-empty. We make sure to place the size fields directly in the
+ // RepeatedField class to avoid costly cache misses due to the indirection.
+ int current_size_;
+ int total_size_;
+ struct Rep {
+ Arena* arena;
+ Element elements[1];
+ };
+ // Why not sizeof(Rep) - sizeof(Element)? Because this is not accurate w.r.t.
+ // trailing padding on the struct -- e.g. if Element is int, this would yield
+ // 12 on x86-64, not 8 as we want.
+ static const size_t kRepHeaderSize = sizeof(Arena*);
+ // Contains arena ptr and the elements array. We also keep the invariant that
+ // if rep_ is NULL, then arena is NULL.
+ Rep* rep_;
+
+ friend class Arena;
+ typedef void InternalArenaConstructable_;
// Move the contents of |from| into |to|, possibly clobbering |from| in the
// process. For primitive types this is just a memcpy(), but it could be
// specialized for non-primitive types to, say, swap each element instead.
- void MoveArray(Element to[], Element from[], int size);
+ void MoveArray(Element* to, Element* from, int size);
// Copy the elements of |from| into |to|.
- void CopyArray(Element to[], const Element from[], int size);
+ void CopyArray(Element* to, const Element* from, int size);
+
+ inline void InternalSwap(RepeatedField* other);
+
+ // Internal helper expected by Arena methods.
+ inline Arena* GetArenaNoVirtual() const {
+ return (rep_ == NULL) ? NULL : rep_->arena;
+ }
};
namespace internal {
@@ -225,13 +277,48 @@ namespace internal {
template <typename Element,
bool HasTrivialCopy = has_trivial_copy<Element>::value>
struct ElementCopier {
- void operator()(Element to[], const Element from[], int array_size);
+ void operator()(Element* to, const Element* from, int array_size);
};
} // namespace internal
namespace internal {
+// type-traits helper for RepeatedPtrFieldBase: we only want to invoke
+// arena-related "copy if on different arena" behavior if the necessary methods
+// exist on the contained type. In particular, we rely on MergeFrom() existing
+// as a general proxy for the fact that a copy will work, and we also provide a
+// specific override for string*.
+template<typename T>
+struct TypeImplementsMergeBehavior {
+ typedef char HasMerge;
+ typedef long HasNoMerge;
+
+ // We accept either of:
+ // - void MergeFrom(const T& other)
+ // - bool MergeFrom(const T& other)
+ //
+ // We mangle these names a bit to avoid compatibility issues in 'unclean'
+ // include environments that may have, e.g., "#define test ..." (yes, this
+ // exists).
+ template<typename U, typename RetType, RetType (U::*)(const U& arg)>
+ struct CheckType;
+ template<typename U> static HasMerge Check(
+ CheckType<U, void, &U::MergeFrom>*);
+ template<typename U> static HasMerge Check(
+ CheckType<U, bool, &U::MergeFrom>*);
+ template<typename U> static HasNoMerge Check(...);
+
+ // Resovles to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
+ typedef google::protobuf::internal::integral_constant<bool,
+ (sizeof(Check<T>(0)) == sizeof(HasMerge))> type;
+};
+
+template<>
+struct TypeImplementsMergeBehavior< ::std::string > {
+ typedef google::protobuf::internal::true_type type;
+};
+
// This is the common base class for RepeatedPtrFields. It deals only in void*
// pointers. Users should not use this interface directly.
//
@@ -267,6 +354,8 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
RepeatedPtrFieldBase();
+ explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena);
+ ~RepeatedPtrFieldBase() {}
// Must be called from destructor.
template <typename TypeHandler>
@@ -280,7 +369,10 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
typename TypeHandler::Type* Mutable(int index);
template <typename TypeHandler>
- typename TypeHandler::Type* Add();
+ void Delete(int index);
+ template <typename TypeHandler>
+ typename TypeHandler::Type* Add(typename TypeHandler::Type* prototype = NULL);
+
template <typename TypeHandler>
void RemoveLast();
template <typename TypeHandler>
@@ -290,13 +382,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
void CopyFrom(const RepeatedPtrFieldBase& other);
- void CloseGap(int start, int num) {
- // Close up a gap of "num" elements starting at offset "start".
- for (int i = start + num; i < allocated_size_; ++i)
- elements_[i - num] = elements_[i];
- current_size_ -= num;
- allocated_size_ -= num;
- }
+ void CloseGap(int start, int num);
void Reserve(int new_size);
@@ -311,7 +397,8 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
const typename TypeHandler::Type* const* data() const;
- void Swap(RepeatedPtrFieldBase* other);
+ template <typename TypeHandler>
+ inline void Swap(RepeatedPtrFieldBase* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
void SwapElements(int index1, int index2);
@@ -325,10 +412,25 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
typename TypeHandler::Type* AddFromCleared();
+ template<typename TypeHandler>
+ void AddAllocated(typename TypeHandler::Type* value) {
+ typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
+ AddAllocatedInternal<TypeHandler>(value, t);
+ }
+
template <typename TypeHandler>
- void AddAllocated(typename TypeHandler::Type* value);
+ void UnsafeArenaAddAllocated(typename TypeHandler::Type* value);
+
template <typename TypeHandler>
- typename TypeHandler::Type* ReleaseLast();
+ typename TypeHandler::Type* ReleaseLast() {
+ typename TypeImplementsMergeBehavior<typename TypeHandler::Type>::type t;
+ return ReleaseLastInternal<TypeHandler>(t);
+ }
+
+ // Releases last element and returns it, but does not do out-of-arena copy.
+ // And just returns the raw pointer to the contained element in the arena.
+ template <typename TypeHandler>
+ typename TypeHandler::Type* UnsafeArenaReleaseLast();
int ClearedCount() const;
template <typename TypeHandler>
@@ -336,13 +438,61 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
template <typename TypeHandler>
typename TypeHandler::Type* ReleaseCleared();
+ protected:
+ inline void InternalSwap(RepeatedPtrFieldBase* other);
+
+ template <typename TypeHandler>
+ void AddAllocatedInternal(typename TypeHandler::Type* value,
+ google::protobuf::internal::true_type);
+ template <typename TypeHandler>
+ void AddAllocatedInternal(typename TypeHandler::Type* value,
+ google::protobuf::internal::false_type);
+
+ template <typename TypeHandler>
+ void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value,
+ Arena* value_arena,
+ Arena* my_arena)
+ GOOGLE_ATTRIBUTE_NOINLINE;
+ template <typename TypeHandler>
+ void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value)
+ GOOGLE_ATTRIBUTE_NOINLINE;
+
+ template <typename TypeHandler>
+ typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::true_type);
+ template <typename TypeHandler>
+ typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type);
+
+ template<typename TypeHandler>
+ inline void SwapFallback(RepeatedPtrFieldBase* other) GOOGLE_ATTRIBUTE_NOINLINE;
+
+ inline Arena* GetArenaNoVirtual() const {
+ return arena_;
+ }
+
private:
static const int kInitialSize = 0;
-
- void** elements_;
+ // A few notes on internal representation:
+ //
+ // We use an indirected approach, with struct Rep, to keep
+ // sizeof(RepeatedPtrFieldBase) equivalent to what it was before arena support
+ // was added, namely, 3 8-byte machine words on x86-64. An instance of Rep is
+ // allocated only when the repeated field is non-empty, and it is a
+ // dynamically-sized struct (the header is directly followed by elements[]).
+ // We place arena_ and current_size_ directly in the object to avoid cache
+ // misses due to the indirection, because these fields are checked frequently.
+ // Placing all fields directly in the RepeatedPtrFieldBase instance costs
+ // significant performance for memory-sensitive workloads.
+ Arena* arena_;
int current_size_;
- int allocated_size_;
int total_size_;
+ struct Rep {
+ int allocated_size;
+ void* elements[1];
+ };
+ static const size_t kRepHeaderSize = sizeof(Rep) - sizeof(void*);
+ // Contains arena ptr and the elements array. We also keep the invariant that
+ // if rep_ is NULL, then arena is NULL.
+ Rep* rep_;
template <typename TypeHandler>
static inline typename TypeHandler::Type* cast(void* element) {
@@ -353,6 +503,22 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
return reinterpret_cast<const typename TypeHandler::Type*>(element);
}
+ // Non-templated inner function to avoid code duplication. Takes a function
+ // pointer to the type-specific (templated) inner allocate/merge loop.
+ void MergeFromInternal(
+ const RepeatedPtrFieldBase& other,
+ void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int));
+
+ template<typename TypeHandler>
+ void MergeFromInnerLoop(
+ void** our_elems, void** other_elems, int length, int already_allocated);
+
+ // Internal helper: extend array space if necessary to contain |extend_amount|
+ // more elements, and return a pointer to the element immediately following
+ // the old list of elements. This interface factors out common behavior from
+ // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0.
+ void** InternalExtend(int extend_amount);
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
};
@@ -360,22 +526,98 @@ template <typename GenericType>
class GenericTypeHandler {
public:
typedef GenericType Type;
- static GenericType* New() { return new GenericType; }
- static void Delete(GenericType* value) { delete value; }
- static void Clear(GenericType* value) { value->Clear(); }
- static void Merge(const GenericType& from, GenericType* to) {
+ static inline GenericType* New(Arena* arena) {
+ return ::google::protobuf::Arena::CreateMaybeMessage<Type>(
+ arena, static_cast<GenericType*>(0));
+ }
+ // We force NewFromPrototype() and Delete() to be non-inline to reduce code
+ // size: else, several other methods get inlined copies of message types'
+ // constructors and destructors. Note that the GOOGLE_ATTRIBUTE_NOINLINE macro
+ // requires the 'inline' storage class here, which is somewhat confusing, but
+ // the compiler does the right thing.
+ static inline GenericType* NewFromPrototype(const GenericType* prototype,
+ ::google::protobuf::Arena* arena = NULL)
+ GOOGLE_ATTRIBUTE_NOINLINE {
+ return New(arena);
+ }
+ static inline void Delete(GenericType* value, Arena* arena)
+ GOOGLE_ATTRIBUTE_NOINLINE {
+ if (arena == NULL) {
+ delete value;
+ }
+ }
+ static inline ::google::protobuf::Arena* GetArena(GenericType* value) {
+ return ::google::protobuf::Arena::GetArena<Type>(value);
+ }
+ static inline void* GetMaybeArenaPointer(GenericType* value) {
+ return ::google::protobuf::Arena::GetArena<Type>(value);
+ }
+
+ static inline void Clear(GenericType* value) { value->Clear(); }
+ static inline void Merge(const GenericType& from, GenericType* to)
+ GOOGLE_ATTRIBUTE_NOINLINE {
to->MergeFrom(from);
}
- static int SpaceUsed(const GenericType& value) { return value.SpaceUsed(); }
- static const Type& default_instance() { return Type::default_instance(); }
+ static inline int SpaceUsed(const GenericType& value) {
+ return value.SpaceUsed();
+ }
+ static inline const Type& default_instance() {
+ return Type::default_instance();
+ }
};
+// Macros for specializing GenericTypeHandler for base proto types, these are
+// are defined here, to allow inlining them at their callsites.
+#define DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Inline, TypeName) \
+ template<> \
+ Inline TypeName* GenericTypeHandler<TypeName>::NewFromPrototype( \
+ const TypeName* prototype, google::protobuf::Arena* arena) { \
+ return prototype->New(arena); \
+ } \
+ template<> \
+ Inline google::protobuf::Arena* GenericTypeHandler<TypeName>::GetArena( \
+ TypeName* value) { \
+ return value->GetArena(); \
+ } \
+ template<> \
+ Inline void* GenericTypeHandler<TypeName>::GetMaybeArenaPointer( \
+ TypeName* value) { \
+ return value->GetMaybeArenaPointer(); \
+ }
+#define DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES_NOINLINE(TypeName) \
+ DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(, TypeName)
+
+// Implements GenericTypeHandler specialization required by RepeatedPtrFields
+// to work with MessageLite type.
template <>
inline void GenericTypeHandler<MessageLite>::Merge(
const MessageLite& from, MessageLite* to) {
to->CheckTypeAndMergeFrom(from);
}
+DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(inline, MessageLite);
+
+// Declarations of the specialization as we cannot define them here, as the
+// header that defines ProtocolMessage depends on types defined in this header.
+#define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName) \
+ template<> \
+ TypeName* GenericTypeHandler<TypeName>::NewFromPrototype( \
+ const TypeName* prototype, google::protobuf::Arena* arena); \
+ template<> \
+ google::protobuf::Arena* GenericTypeHandler<TypeName>::GetArena( \
+ TypeName* value); \
+ template<> \
+ void* GenericTypeHandler<TypeName>::GetMaybeArenaPointer( \
+ TypeName* value);
+
+// Message specialization bodies defined in message.cc. This split is necessary
+// to allow proto2-lite (which includes this header) to be independent of
+// Message.
+DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message);
+
+
+#undef DECLARE_SPECIALIZATIONS_FOR_BASE_CLASSES
+
template <>
inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
// Yes, the behavior of the code is undefined, but this function is only
@@ -406,11 +648,28 @@ inline const Message& GenericTypeHandler<Message>::default_instance() {
class LIBPROTOBUF_EXPORT StringTypeHandlerBase {
public:
typedef string Type;
- static string* New();
- static void Delete(string* value);
- static void Clear(string* value) { value->clear(); }
- static void Merge(const string& from, string* to) { *to = from; }
- static const Type& default_instance() {
+
+ static inline string* New(Arena* arena) {
+ return Arena::Create<string>(arena);
+ }
+ static inline string* NewFromPrototype(const string*,
+ ::google::protobuf::Arena* arena) {
+ return New(arena);
+ }
+ static inline ::google::protobuf::Arena* GetArena(string*) {
+ return NULL;
+ }
+ static inline void* GetMaybeArenaPointer(string* value) {
+ return NULL;
+ }
+ static inline void Delete(string* value, Arena* arena) {
+ if (arena == NULL) {
+ delete value;
+ }
+ }
+ static inline void Clear(string* value) { value->clear(); }
+ static inline void Merge(const string& from, string* to) { *to = from; }
+ static inline const Type& default_instance() {
return ::google::protobuf::internal::GetEmptyString();
}
};
@@ -431,6 +690,8 @@ template <typename Element>
class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
public:
RepeatedPtrField();
+ explicit RepeatedPtrField(::google::protobuf::Arena* arena);
+
RepeatedPtrField(const RepeatedPtrField& other);
template <typename Iter>
RepeatedPtrField(Iter begin, const Iter& end);
@@ -470,9 +731,16 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
Element** mutable_data();
const Element* const* data() const;
- // Swap entire contents with "other".
+ // Swap entire contents with "other". If they are on separate arenas, then
+ // copies data.
void Swap(RepeatedPtrField* other);
+ // Swap entire contents with "other". Caller should guarantee that either both
+ // fields are on the same arena or both are on the heap. Swapping between
+ // different arenas with this function is disallowed and is caught via
+ // GOOGLE_DCHECK.
+ void UnsafeArenaSwap(RepeatedPtrField* other);
+
// Swap two elements.
void SwapElements(int index1, int index2);
@@ -489,8 +757,10 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
iterator begin();
const_iterator begin() const;
+ const_iterator cbegin() const;
iterator end();
const_iterator end() const;
+ const_iterator cend() const;
// Reverse iterator support
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
@@ -529,11 +799,36 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// Add an already-allocated object, passing ownership to the
// RepeatedPtrField.
+ //
+ // Note that some special behavior occurs with respect to arenas:
+ //
+ // (i) if this field holds submessages, the new submessage will be copied if
+ // the original is in an arena and this RepeatedPtrField is either in a
+ // different arena, or on the heap.
+ // (ii) if this field holds strings, the passed-in string *must* be
+ // heap-allocated, not arena-allocated. There is no way to dynamically check
+ // this at runtime, so User Beware.
void AddAllocated(Element* value);
+
// Remove the last element and return it, passing ownership to the caller.
// Requires: size() > 0
+ //
+ // If this RepeatedPtrField is on an arena, an object copy is required to pass
+ // ownership back to the user (for compatible semantics). Use
+ // UnsafeArenaReleaseLast() if this behavior is undesired.
Element* ReleaseLast();
+ // Add an already-allocated object, skipping arena-ownership checks. The user
+ // must guarantee that the given object is in the same arena as this
+ // RepeatedPtrField.
+ void UnsafeArenaAddAllocated(Element* value);
+
+ // Remove the last element and return it. Works only when operating on an
+ // arena. The returned pointer is to the original object in the arena, hence
+ // has the arena's lifetime.
+ // Requires: current_size_ > 0
+ Element* UnsafeArenaReleaseLast();
+
// Extract elements with indices in the range "[start .. start+num-1]".
// The caller assumes ownership of the extracted elements and is responsible
// for deleting them when they are no longer needed.
@@ -543,8 +838,20 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// to perform any further operations (like deletion) on these elements.
// Caution: implementation also moves elements with indices [start+num ..].
// Calling this routine inside a loop can cause quadratic behavior.
+ //
+ // Memory copying behavior is identical to ReleaseLast(), described above: if
+ // this RepeatedPtrField is on an arena, an object copy is performed for each
+ // returned element, so that all returned element pointers are to
+ // heap-allocated copies. If this copy is not desired, the user should call
+ // UnsafeArenaExtractSubrange().
void ExtractSubrange(int start, int num, Element** elements);
+ // Identical to ExtractSubrange() described above, except that when this
+ // repeated field is on an arena, no object copies are performed. Instead, the
+ // raw object pointers are returned. Thus, if on an arena, the returned
+ // objects must not be freed, because they will not be heap-allocated objects.
+ void UnsafeArenaExtractSubrange(int start, int num, Element** elements);
+
// When elements are removed by calls to RemoveLast() or Clear(), they
// are not actually freed. Instead, they are cleared and kept so that
// they can be reused later. This can save lots of CPU time when
@@ -559,12 +866,30 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// Add an element to the pool of cleared objects, passing ownership to
// the RepeatedPtrField. The element must be cleared prior to calling
// this method.
+ //
+ // This method cannot be called when the repeated field is on an arena or when
+ // |value| is; both cases will trigger a GOOGLE_DCHECK-failure.
void AddCleared(Element* value);
// Remove a single element from the cleared pool and return it, passing
// ownership to the caller. The element is guaranteed to be cleared.
// Requires: ClearedCount() > 0
+ //
+ //
+ // This method cannot be called when the repeated field is on an arena; doing
+ // so will trigger a GOOGLE_DCHECK-failure.
Element* ReleaseCleared();
+ // Remove the element referenced by position.
+ iterator erase(const_iterator position);
+
+ // Removes the elements in the range [first, last).
+ iterator erase(const_iterator first, const_iterator last);
+
+ // Gets the arena on which this RepeatedPtrField stores its elements.
+ ::google::protobuf::Arena* GetArena() const {
+ return GetArenaNoVirtual();
+ }
+
protected:
// Note: RepeatedPtrField SHOULD NOT be subclassed by users. We only
// subclass it in one place as a hack for compatibility with proto1. The
@@ -572,31 +897,61 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase {
// methods on RepeatedPtrFieldBase.
class TypeHandler;
+ // Internal arena accessor expected by helpers in Arena.
+ inline Arena* GetArenaNoVirtual() const;
+
+ private:
+ // Implementations for ExtractSubrange(). The copying behavior must be
+ // included only if the type supports the necessary operations (e.g.,
+ // MergeFrom()), so we must resolve this at compile time. ExtractSubrange()
+ // uses SFINAE to choose one of the below implementations.
+ void ExtractSubrangeInternal(int start, int num, Element** elements,
+ google::protobuf::internal::true_type);
+ void ExtractSubrangeInternal(int start, int num, Element** elements,
+ google::protobuf::internal::false_type);
+
+ friend class Arena;
+ typedef void InternalArenaConstructable_;
+
};
// implementation ====================================================
template <typename Element>
inline RepeatedField<Element>::RepeatedField()
- : elements_(NULL),
- current_size_(0),
- total_size_(kInitialSize) {
+ : current_size_(0),
+ total_size_(0),
+ rep_(NULL) {
+}
+
+template <typename Element>
+inline RepeatedField<Element>::RepeatedField(Arena* arena)
+ : current_size_(0),
+ total_size_(0),
+ rep_(NULL) {
+ // In case arena is NULL, then we do not create rep_, as code has an invariant
+ // `rep_ == NULL then arena == NULL`.
+ if (arena != NULL) {
+ rep_ = reinterpret_cast<Rep*>(
+ ::google::protobuf::Arena::CreateArray<char>(arena, kRepHeaderSize));
+ rep_->arena = arena;
+ }
}
template <typename Element>
inline RepeatedField<Element>::RepeatedField(const RepeatedField& other)
- : elements_(NULL),
- current_size_(0),
- total_size_(kInitialSize) {
+ : current_size_(0),
+ total_size_(0),
+ rep_(NULL) {
CopyFrom(other);
}
template <typename Element>
template <typename Iter>
-inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
- : elements_(NULL),
- current_size_(0),
- total_size_(kInitialSize) {
+RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
+ : current_size_(0),
+ total_size_(0),
+ rep_(NULL) {
int reserve = internal::CalculateReserve(begin, end);
if (reserve != -1) {
Reserve(reserve);
@@ -612,7 +967,20 @@ inline RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
template <typename Element>
RepeatedField<Element>::~RepeatedField() {
- delete [] elements_;
+ // See explanation in Reserve(): we need to invoke destructors here for the
+ // case that Element has a non-trivial destructor. If Element has a trivial
+ // destructor (for example, if it's a primitive type, like int32), this entire
+ // loop will be removed by the optimizer.
+ if (rep_ != NULL) {
+ Element* e = &rep_->elements[0];
+ Element* limit = &rep_->elements[total_size_];
+ for (; e < limit; e++) {
+ e->Element::~Element();
+ }
+ if (rep_->arena == NULL) {
+ delete[] reinterpret_cast<char*>(rep_);
+ }
+ }
}
template <typename Element>
@@ -640,22 +1008,23 @@ inline int RepeatedField<Element>::Capacity() const {
template<typename Element>
inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) {
- GOOGLE_DCHECK_LT(size(), Capacity());
- elements_[current_size_++] = value;
+ GOOGLE_DCHECK_LT(current_size_, total_size_);
+ rep_->elements[current_size_++] = value;
}
template<typename Element>
inline Element* RepeatedField<Element>::AddAlreadyReserved() {
- GOOGLE_DCHECK_LT(size(), Capacity());
- return &elements_[current_size_++];
+ GOOGLE_DCHECK_LT(current_size_, total_size_);
+ return &rep_->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()) {
+ if (new_size > current_size_) {
Reserve(new_size);
- std::fill(&elements_[current_size_], &elements_[new_size], value);
+ std::fill(&rep_->elements[current_size_],
+ &rep_->elements[new_size], value);
}
current_size_ = new_size;
}
@@ -663,40 +1032,40 @@ inline void RepeatedField<Element>::Resize(int new_size, const Element& value) {
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];
+ GOOGLE_DCHECK_LT(index, current_size_);
+ return rep_->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;
+ GOOGLE_DCHECK_LT(index, current_size_);
+ return &rep_->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;
+ GOOGLE_DCHECK_LT(index, current_size_);
+ rep_->elements[index] = value;
}
template <typename Element>
inline void RepeatedField<Element>::Add(const Element& value) {
if (current_size_ == total_size_) Reserve(total_size_ + 1);
- elements_[current_size_++] = value;
+ rep_->elements[current_size_++] = value;
}
template <typename Element>
inline Element* RepeatedField<Element>::Add() {
if (current_size_ == total_size_) Reserve(total_size_ + 1);
- return &elements_[current_size_++];
+ return &rep_->elements[current_size_++];
}
template <typename Element>
inline void RepeatedField<Element>::RemoveLast() {
GOOGLE_DCHECK_GT(current_size_, 0);
- --current_size_;
+ current_size_--;
}
template <typename Element>
@@ -704,7 +1073,7 @@ void RepeatedField<Element>::ExtractSubrange(
int start, int num, Element* elements) {
GOOGLE_DCHECK_GE(start, 0);
GOOGLE_DCHECK_GE(num, 0);
- GOOGLE_DCHECK_LE(start + num, this->size());
+ GOOGLE_DCHECK_LE(start + num, this->current_size_);
// Save the values of the removed elements if requested.
if (elements != NULL) {
@@ -714,9 +1083,9 @@ void RepeatedField<Element>::ExtractSubrange(
// Slide remaining elements down to fill the gap.
if (num > 0) {
- for (int i = start + num; i < this->size(); ++i)
+ for (int i = start + num; i < this->current_size_; ++i)
this->Set(i - num, this->Get(i));
- this->Truncate(this->size() - num);
+ this->Truncate(this->current_size_ - num);
}
}
@@ -730,7 +1099,8 @@ 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_);
+ CopyArray(rep_->elements + current_size_,
+ other.rep_->elements, other.current_size_);
current_size_ += other.current_size_;
}
}
@@ -743,62 +1113,98 @@ inline void RepeatedField<Element>::CopyFrom(const RepeatedField& other) {
}
template <typename Element>
+inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
+ const_iterator position) {
+ return erase(position, position + 1);
+}
+
+template <typename Element>
+inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
+ const_iterator first, const_iterator last) {
+ size_type first_offset = first - cbegin();
+ Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin());
+ return begin() + first_offset;
+}
+
+template <typename Element>
inline Element* RepeatedField<Element>::mutable_data() {
- return elements_;
+ return rep_ ? rep_->elements : NULL;
}
template <typename Element>
inline const Element* RepeatedField<Element>::data() const {
- return elements_;
+ return rep_ ? rep_->elements : NULL;
}
template <typename Element>
+inline void RepeatedField<Element>::InternalSwap(RepeatedField* other) {
+ std::swap(rep_, other->rep_);
+ std::swap(current_size_, other->current_size_);
+ std::swap(total_size_, other->total_size_);
+}
+
+template <typename Element>
void RepeatedField<Element>::Swap(RepeatedField* other) {
if (this == other) return;
- Element* swap_elements = elements_;
- int swap_current_size = current_size_;
- int swap_total_size = total_size_;
-
- elements_ = other->elements_;
- current_size_ = other->current_size_;
- total_size_ = other->total_size_;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ RepeatedField<Element> temp(other->GetArenaNoVirtual());
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->UnsafeArenaSwap(&temp);
+ }
+}
- other->elements_ = swap_elements;
- other->current_size_ = swap_current_size;
- other->total_size_ = swap_total_size;
+template <typename Element>
+void RepeatedField<Element>::UnsafeArenaSwap(RepeatedField* other) {
+ if (this == other) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
}
template <typename Element>
void RepeatedField<Element>::SwapElements(int index1, int index2) {
using std::swap; // enable ADL with fallback
- swap(elements_[index1], elements_[index2]);
+ swap(rep_->elements[index1], rep_->elements[index2]);
}
template <typename Element>
inline typename RepeatedField<Element>::iterator
RepeatedField<Element>::begin() {
- return elements_;
+ return rep_ ? rep_->elements : NULL;
}
template <typename Element>
inline typename RepeatedField<Element>::const_iterator
RepeatedField<Element>::begin() const {
- return elements_;
+ return rep_ ? rep_->elements : NULL;
+}
+template <typename Element>
+inline typename RepeatedField<Element>::const_iterator
+RepeatedField<Element>::cbegin() const {
+ return rep_ ? rep_->elements : NULL;
}
template <typename Element>
inline typename RepeatedField<Element>::iterator
RepeatedField<Element>::end() {
- return elements_ + current_size_;
+ return rep_ ? rep_->elements + current_size_ : NULL;
}
template <typename Element>
inline typename RepeatedField<Element>::const_iterator
RepeatedField<Element>::end() const {
- return elements_ + current_size_;
+ return rep_ ? rep_->elements + current_size_ : NULL;
+}
+template <typename Element>
+inline typename RepeatedField<Element>::const_iterator
+RepeatedField<Element>::cend() const {
+ return rep_ ? rep_->elements + current_size_ : NULL;
}
template <typename Element>
inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
- return (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
+ return rep_ ?
+ (total_size_ * sizeof(Element) + kRepHeaderSize) : 0;
}
// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant
@@ -806,32 +1212,66 @@ inline int RepeatedField<Element>::SpaceUsedExcludingSelf() const {
template <typename Element>
void RepeatedField<Element>::Reserve(int new_size) {
if (total_size_ >= new_size) return;
-
- Element* old_elements = elements_;
- total_size_ = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
- max(total_size_ * 2, new_size));
- elements_ = new Element[total_size_];
- if (old_elements != NULL) {
- MoveArray(elements_, old_elements, current_size_);
- delete [] old_elements;
+ Rep* old_rep = rep_;
+ Arena* arena = GetArenaNoVirtual();
+ new_size = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
+ max(total_size_ * 2, new_size));
+ if (arena == NULL) {
+ rep_ = reinterpret_cast<Rep*>(
+ new char[kRepHeaderSize + sizeof(Element)*new_size]);
+ } else {
+ rep_ = reinterpret_cast<Rep*>(
+ ::google::protobuf::Arena::CreateArray<char>(arena,
+ kRepHeaderSize + sizeof(Element)*new_size));
+ }
+ rep_->arena = arena;
+ total_size_ = new_size;
+ // Invoke placement-new on newly allocated elements. We shouldn't have to do
+ // this, since Element is supposed to be POD, but a previous version of this
+ // code allocated storage with "new Element[size]" and some code uses
+ // RepeatedField with non-POD types, relying on constructor invocation. If
+ // Element has a trivial constructor (e.g., int32), gcc (tested with -O2)
+ // completely removes this loop because the loop body is empty, so this has no
+ // effect unless its side-effects are required for correctness.
+ // Note that we do this before MoveArray() below because Element's copy
+ // assignment implementation will want an initialized instance first.
+ Element* e = &rep_->elements[0];
+ Element* limit = &rep_->elements[total_size_];
+ for (; e < limit; e++) {
+ new (e) Element();
+ }
+ if (current_size_ > 0) {
+ MoveArray(rep_->elements, old_rep->elements, current_size_);
+ }
+ // Likewise, we need to invoke destructors on the old array. If Element has no
+ // destructor, this loop will disappear.
+ e = &old_rep->elements[0];
+ limit = &old_rep->elements[current_size_];
+ for (; e < limit; e++) {
+ e->Element::~Element();
+ }
+ if (arena == NULL) {
+ delete[] reinterpret_cast<char*>(old_rep);
}
}
template <typename Element>
inline void RepeatedField<Element>::Truncate(int new_size) {
GOOGLE_DCHECK_LE(new_size, current_size_);
- current_size_ = new_size;
+ if (current_size_ > 0) {
+ current_size_ = new_size;
+ }
}
template <typename Element>
inline void RepeatedField<Element>::MoveArray(
- Element to[], Element from[], int array_size) {
+ Element* to, Element* from, int array_size) {
CopyArray(to, from, array_size);
}
template <typename Element>
inline void RepeatedField<Element>::CopyArray(
- Element to[], const Element from[], int array_size) {
+ Element* to, const Element* from, int array_size) {
internal::ElementCopier<Element>()(to, from, array_size);
}
@@ -839,13 +1279,13 @@ namespace internal {
template <typename Element, bool HasTrivialCopy>
void ElementCopier<Element, HasTrivialCopy>::operator()(
- Element to[], const Element from[], int array_size) {
+ Element* to, const Element* from, int array_size) {
std::copy(from, from + array_size, to);
}
template <typename Element>
struct ElementCopier<Element, true> {
- void operator()(Element to[], const Element from[], int array_size) {
+ void operator()(Element* to, const Element* from, int array_size) {
memcpy(to, from, array_size * sizeof(Element));
}
};
@@ -858,18 +1298,55 @@ struct ElementCopier<Element, true> {
namespace internal {
inline RepeatedPtrFieldBase::RepeatedPtrFieldBase()
- : elements_(NULL),
+ : arena_(NULL),
current_size_(0),
- allocated_size_(0),
- total_size_(kInitialSize) {
+ total_size_(0),
+ rep_(NULL) {
+}
+
+inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(::google::protobuf::Arena* arena)
+ : arena_(arena),
+ current_size_(0),
+ total_size_(0),
+ rep_(NULL) {
}
template <typename TypeHandler>
void RepeatedPtrFieldBase::Destroy() {
- for (int i = 0; i < allocated_size_; i++) {
- TypeHandler::Delete(cast<TypeHandler>(elements_[i]));
+ if (rep_ != NULL) {
+ for (int i = 0; i < rep_->allocated_size; i++) {
+ TypeHandler::Delete(cast<TypeHandler>(rep_->elements[i]), arena_);
+ }
+ if (arena_ == NULL) {
+ delete [] reinterpret_cast<char*>(rep_);
+ }
}
- delete [] elements_;
+ rep_ = NULL;
+}
+
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
+ if (other->GetArenaNoVirtual() == GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ SwapFallback<TypeHandler>(other);
+ }
+}
+
+template <typename TypeHandler>
+inline void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
+ GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual());
+
+ // Copy semantics in this case. We try to improve efficiency by placing the
+ // temporary on |other|'s arena so that messages are copied cross-arena only
+ // once, not twice.
+ RepeatedPtrFieldBase temp(other->GetArenaNoVirtual());
+ temp.MergeFrom<TypeHandler>(*this);
+ this->Clear<TypeHandler>();
+ this->MergeFrom<TypeHandler>(*other);
+ other->Clear<TypeHandler>();
+ other->InternalSwap(&temp);
+ temp.Destroy<TypeHandler>(); // Frees rep_ if `other` had no arena.
}
inline bool RepeatedPtrFieldBase::empty() const {
@@ -884,8 +1361,8 @@ 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]);
+ GOOGLE_DCHECK_LT(index, current_size_);
+ return *cast<TypeHandler>(rep_->elements[index]);
}
@@ -893,42 +1370,106 @@ 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]);
+ GOOGLE_DCHECK_LT(index, current_size_);
+ return cast<TypeHandler>(rep_->elements[index]);
}
template <typename TypeHandler>
-inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add() {
- if (current_size_ < allocated_size_) {
- return cast<TypeHandler>(elements_[current_size_++]);
- }
- if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
- typename TypeHandler::Type* result = TypeHandler::New();
- ++allocated_size_;
- elements_[current_size_++] = result;
+inline void RepeatedPtrFieldBase::Delete(int index) {
+ GOOGLE_DCHECK_GE(index, 0);
+ GOOGLE_DCHECK_LT(index, current_size_);
+ TypeHandler::Delete(cast<TypeHandler>(rep_->elements[index]), arena_);
+}
+
+template <typename TypeHandler>
+inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add(
+ typename TypeHandler::Type* prototype) {
+ if (rep_ != NULL && current_size_ < rep_->allocated_size) {
+ return cast<TypeHandler>(rep_->elements[current_size_++]);
+ }
+ if (!rep_ || rep_->allocated_size == total_size_) {
+ Reserve(total_size_ + 1);
+ }
+ ++rep_->allocated_size;
+ typename TypeHandler::Type* result =
+ TypeHandler::NewFromPrototype(prototype, arena_);
+ rep_->elements[current_size_++] = result;
return result;
}
template <typename TypeHandler>
inline void RepeatedPtrFieldBase::RemoveLast() {
GOOGLE_DCHECK_GT(current_size_, 0);
- TypeHandler::Clear(cast<TypeHandler>(elements_[--current_size_]));
+ TypeHandler::Clear(cast<TypeHandler>(rep_->elements[--current_size_]));
}
template <typename TypeHandler>
void RepeatedPtrFieldBase::Clear() {
- for (int i = 0; i < current_size_; i++) {
- TypeHandler::Clear(cast<TypeHandler>(elements_[i]));
+ const int n = current_size_;
+ GOOGLE_DCHECK_GE(n, 0);
+ if (n > 0) {
+ void* const* elements = raw_data();
+ int i = 0;
+ do {
+ TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
+ } while (i < n);
+ current_size_ = 0;
}
- current_size_ = 0;
}
+// To avoid unnecessary code duplication and reduce binary size, we use a
+// layered approach to implementing MergeFrom(). The toplevel method is
+// templated, so we get a small thunk per concrete message type in the binary.
+// This calls a shared implementation with most of the logic, passing a function
+// pointer to another type-specific piece of code that calls the object-allocate
+// and merge handlers.
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>());
+ GOOGLE_DCHECK_NE(&other, this);
+ if (other.current_size_ == 0) return;
+ MergeFromInternal(
+ other, &RepeatedPtrFieldBase::MergeFromInnerLoop<TypeHandler>);
+}
+
+inline void RepeatedPtrFieldBase::MergeFromInternal(
+ const RepeatedPtrFieldBase& other,
+ void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int)) {
+ // Note: wrapper has already guaranteed that other.rep_ != NULL here.
+ int other_size = other.current_size_;
+ void** other_elements = other.rep_->elements;
+ void** new_elements = InternalExtend(other_size);
+ int allocated_elems = rep_->allocated_size - current_size_;
+ (this->*inner_loop)(new_elements, other_elements,
+ other_size, allocated_elems);
+ current_size_ += other_size;
+ if (rep_->allocated_size < current_size_) {
+ rep_->allocated_size = current_size_;
+ }
+}
+
+// Merges other_elems to our_elems.
+template<typename TypeHandler>
+void RepeatedPtrFieldBase::MergeFromInnerLoop(
+ void** our_elems, void** other_elems, int length, int already_allocated) {
+ // Split into two loops, over ranges [0, allocated) and [allocated, length),
+ // to avoid a branch within the loop.
+ for (int i = 0; i < already_allocated && i < length; i++) {
+ // Already allocated: use existing element.
+ typename TypeHandler::Type* other_elem =
+ reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
+ typename TypeHandler::Type* new_elem =
+ reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]);
+ TypeHandler::Merge(*other_elem, new_elem);
+ }
+ Arena* arena = GetArenaNoVirtual();
+ for (int i = already_allocated; i < length; i++) {
+ // Not allocated: alloc a new element first, then merge it.
+ typename TypeHandler::Type* other_elem =
+ reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
+ typename TypeHandler::Type* new_elem =
+ TypeHandler::NewFromPrototype(other_elem, arena);
+ TypeHandler::Merge(*other_elem, new_elem);
+ our_elems[i] = new_elem;
}
}
@@ -944,18 +1485,18 @@ inline int RepeatedPtrFieldBase::Capacity() const {
}
inline void* const* RepeatedPtrFieldBase::raw_data() const {
- return elements_;
+ return rep_ ? rep_->elements : NULL;
}
inline void** RepeatedPtrFieldBase::raw_mutable_data() const {
- return elements_;
+ return rep_ ? const_cast<void**>(rep_->elements) : NULL;
}
template <typename TypeHandler>
inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() {
// TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
// method entirely.
- return reinterpret_cast<typename TypeHandler::Type**>(elements_);
+ return reinterpret_cast<typename TypeHandler::Type**>(raw_mutable_data());
}
template <typename TypeHandler>
@@ -963,89 +1504,212 @@ inline const typename TypeHandler::Type* const*
RepeatedPtrFieldBase::data() const {
// TODO(kenton): Breaks C++ aliasing rules. We should probably remove this
// method entirely.
- return reinterpret_cast<const typename TypeHandler::Type* const*>(elements_);
+ return reinterpret_cast<const typename TypeHandler::Type* const*>(raw_data());
}
inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) {
using std::swap; // enable ADL with fallback
- swap(elements_[index1], elements_[index2]);
+ swap(rep_->elements[index1], rep_->elements[index2]);
}
template <typename TypeHandler>
inline int RepeatedPtrFieldBase::SpaceUsedExcludingSelf() const {
- int allocated_bytes =
- (elements_ != NULL) ? total_size_ * sizeof(elements_[0]) : 0;
- for (int i = 0; i < allocated_size_; ++i) {
- allocated_bytes += TypeHandler::SpaceUsed(*cast<TypeHandler>(elements_[i]));
+ int allocated_bytes = total_size_ * sizeof(void*);
+ if (rep_ != NULL) {
+ for (int i = 0; i < rep_->allocated_size; ++i) {
+ allocated_bytes += TypeHandler::SpaceUsed(
+ *cast<TypeHandler>(rep_->elements[i]));
+ }
+ allocated_bytes += kRepHeaderSize;
}
return allocated_bytes;
}
template <typename TypeHandler>
inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() {
- if (current_size_ < allocated_size_) {
- return cast<TypeHandler>(elements_[current_size_++]);
+ if (rep_ != NULL && current_size_ < rep_->allocated_size) {
+ return cast<TypeHandler>(rep_->elements[current_size_++]);
} else {
return NULL;
}
}
+// AddAllocated version that implements arena-safe copying behavior.
template <typename TypeHandler>
-void RepeatedPtrFieldBase::AddAllocated(
+void RepeatedPtrFieldBase::AddAllocatedInternal(
+ typename TypeHandler::Type* value,
+ google::protobuf::internal::true_type) {
+ Arena* element_arena = reinterpret_cast<Arena*>(
+ TypeHandler::GetMaybeArenaPointer(value));
+ Arena* arena = GetArenaNoVirtual();
+ if (arena == element_arena && rep_ &&
+ rep_->allocated_size < total_size_) {
+ // Fast path: underlying arena representation (tagged pointer) is equal to
+ // our arena pointer, and we can add to array without resizing it (at least
+ // one slot that is not allocated).
+ void** elems = rep_->elements;
+ if (current_size_ < rep_->allocated_size) {
+ // Make space at [current] by moving first allocated element to end of
+ // allocated list.
+ elems[rep_->allocated_size] = elems[current_size_];
+ }
+ elems[current_size_] = value;
+ current_size_ = current_size_ + 1;
+ rep_->allocated_size = rep_->allocated_size + 1;
+ return;
+ } else {
+ AddAllocatedSlowWithCopy<TypeHandler>(
+ value, TypeHandler::GetArena(value), arena);
+ }
+}
+
+// Slowpath handles all cases, copying if necessary.
+template<typename TypeHandler>
+void RepeatedPtrFieldBase::AddAllocatedSlowWithCopy(
+ // Pass value_arena and my_arena to avoid duplicate virtual call (value) or
+ // load (mine).
+ typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena) {
+ // Ensure that either the value is in the same arena, or if not, we do the
+ // appropriate thing: Own() it (if it's on heap and we're in an arena) or copy
+ // it to our arena/heap (otherwise).
+ if (my_arena != NULL && value_arena == NULL) {
+ my_arena->Own(value);
+ } else if (my_arena != value_arena) {
+ typename TypeHandler::Type* new_value =
+ TypeHandler::NewFromPrototype(value, my_arena);
+ TypeHandler::Merge(*value, new_value);
+ TypeHandler::Delete(value, value_arena);
+ value = new_value;
+ }
+
+ UnsafeArenaAddAllocated<TypeHandler>(value);
+}
+
+// AddAllocated version that does not implement arena-safe copying behavior.
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::AddAllocatedInternal(
+ typename TypeHandler::Type* value,
+ google::protobuf::internal::false_type) {
+ if (rep_ && rep_->allocated_size < total_size_) {
+ // Fast path: underlying arena representation (tagged pointer) is equal to
+ // our arena pointer, and we can add to array without resizing it (at least
+ // one slot that is not allocated).
+ void** elems = rep_->elements;
+ if (current_size_ < rep_->allocated_size) {
+ // Make space at [current] by moving first allocated element to end of
+ // allocated list.
+ elems[rep_->allocated_size] = elems[current_size_];
+ }
+ elems[current_size_] = value;
+ current_size_ = current_size_ + 1;
+ ++rep_->allocated_size;
+ return;
+ } else {
+ UnsafeArenaAddAllocated<TypeHandler>(value);
+ }
+}
+
+template <typename TypeHandler>
+void RepeatedPtrFieldBase::UnsafeArenaAddAllocated(
typename TypeHandler::Type* value) {
// Make room for the new pointer.
- if (current_size_ == total_size_) {
+ if (!rep_ || current_size_ == total_size_) {
// The array is completely full with no cleared objects, so grow it.
Reserve(total_size_ + 1);
- ++allocated_size_;
- } else if (allocated_size_ == total_size_) {
+ ++rep_->allocated_size;
+ } else if (rep_->allocated_size == total_size_) {
// There is no more space in the pointer array because it contains some
// cleared objects awaiting reuse. We don't want to grow the array in this
// case because otherwise a loop calling AddAllocated() followed by Clear()
// would leak memory.
- TypeHandler::Delete(cast<TypeHandler>(elements_[current_size_]));
- } else if (current_size_ < allocated_size_) {
+ TypeHandler::Delete(
+ cast<TypeHandler>(rep_->elements[current_size_]), arena_);
+ } else if (current_size_ < rep_->allocated_size) {
// We have some cleared objects. We don't care about their order, so we
// can just move the first one to the end to make space.
- elements_[allocated_size_] = elements_[current_size_];
- ++allocated_size_;
+ rep_->elements[rep_->allocated_size] = rep_->elements[current_size_];
+ ++rep_->allocated_size;
} else {
// There are no cleared objects.
- ++allocated_size_;
+ ++rep_->allocated_size;
+ }
+
+ rep_->elements[current_size_++] = value;
+}
+
+// ReleaseLast() for types that implement merge/copy behavior.
+template <typename TypeHandler>
+inline typename TypeHandler::Type*
+RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::true_type) {
+ // First, release an element.
+ typename TypeHandler::Type* result = UnsafeArenaReleaseLast<TypeHandler>();
+ // Now perform a copy if we're on an arena.
+ Arena* arena = GetArenaNoVirtual();
+ if (arena == NULL) {
+ return result;
+ } else {
+ typename TypeHandler::Type* new_result =
+ TypeHandler::NewFromPrototype(result, NULL);
+ TypeHandler::Merge(*result, new_result);
+ return new_result;
}
+}
- elements_[current_size_++] = value;
+// ReleaseLast() for types that *do not* implement merge/copy behavior -- this
+// is the same as UnsafeArenaReleaseLast(). Note that we GOOGLE_DCHECK-fail if we're on
+// an arena, since the user really should implement the copy operation in this
+// case.
+template <typename TypeHandler>
+inline typename TypeHandler::Type*
+RepeatedPtrFieldBase::ReleaseLastInternal(google::protobuf::internal::false_type) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+ << "ReleaseLast() called on a RepeatedPtrField that is on an arena, "
+ << "with a type that does not implement MergeFrom. This is unsafe; "
+ << "please implement MergeFrom for your type.";
+ return UnsafeArenaReleaseLast<TypeHandler>();
}
template <typename TypeHandler>
-inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseLast() {
+inline typename TypeHandler::Type*
+ RepeatedPtrFieldBase::UnsafeArenaReleaseLast() {
GOOGLE_DCHECK_GT(current_size_, 0);
typename TypeHandler::Type* result =
- cast<TypeHandler>(elements_[--current_size_]);
- --allocated_size_;
- if (current_size_ < allocated_size_) {
+ cast<TypeHandler>(rep_->elements[--current_size_]);
+ --rep_->allocated_size;
+ if (current_size_ < rep_->allocated_size) {
// There are cleared elements on the end; replace the removed element
// with the last allocated element.
- elements_[current_size_] = elements_[allocated_size_];
+ rep_->elements[current_size_] = rep_->elements[rep_->allocated_size];
}
return result;
}
inline int RepeatedPtrFieldBase::ClearedCount() const {
- return allocated_size_ - current_size_;
+ return rep_ ? (rep_->allocated_size - current_size_) : 0;
}
template <typename TypeHandler>
inline void RepeatedPtrFieldBase::AddCleared(
typename TypeHandler::Type* value) {
- if (allocated_size_ == total_size_) Reserve(total_size_ + 1);
- elements_[allocated_size_++] = value;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+ << "AddCleared() can only be used on a RepeatedPtrField not on an arena.";
+ GOOGLE_DCHECK(TypeHandler::GetArena(value) == NULL)
+ << "AddCleared() can only accept values not on an arena.";
+ if (!rep_ || rep_->allocated_size == total_size_) {
+ Reserve(total_size_ + 1);
+ }
+ rep_->elements[rep_->allocated_size++] = value;
}
template <typename TypeHandler>
inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() {
- GOOGLE_DCHECK_GT(allocated_size_, current_size_);
- return cast<TypeHandler>(elements_[--allocated_size_]);
+ GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+ << "ReleaseCleared() can only be used on a RepeatedPtrField not on "
+ << "an arena.";
+ GOOGLE_DCHECK(GetArenaNoVirtual() == NULL);
+ GOOGLE_DCHECK(rep_ != NULL);
+ GOOGLE_DCHECK_GT(rep_->allocated_size, current_size_);
+ return cast<TypeHandler>(rep_->elements[--rep_->allocated_size]);
}
} // namespace internal
@@ -1064,12 +1728,17 @@ class RepeatedPtrField<string>::TypeHandler
template <typename Element>
-inline RepeatedPtrField<Element>::RepeatedPtrField() {}
+inline RepeatedPtrField<Element>::RepeatedPtrField()
+ : RepeatedPtrFieldBase() {}
+
+template <typename Element>
+inline RepeatedPtrField<Element>::RepeatedPtrField(::google::protobuf::Arena* arena) :
+ RepeatedPtrFieldBase(arena) {}
template <typename Element>
inline RepeatedPtrField<Element>::RepeatedPtrField(
const RepeatedPtrField& other)
- : RepeatedPtrFieldBase() {
+ : RepeatedPtrFieldBase() {
CopyFrom(other);
}
@@ -1135,14 +1804,25 @@ inline void RepeatedPtrField<Element>::DeleteSubrange(int start, int num) {
GOOGLE_DCHECK_GE(start, 0);
GOOGLE_DCHECK_GE(num, 0);
GOOGLE_DCHECK_LE(start + num, size());
- for (int i = 0; i < num; ++i)
- delete RepeatedPtrFieldBase::Mutable<TypeHandler>(start + i);
+ for (int i = 0; i < num; ++i) {
+ RepeatedPtrFieldBase::Delete<TypeHandler>(start + i);
+ }
ExtractSubrange(start, num, NULL);
}
template <typename Element>
inline void RepeatedPtrField<Element>::ExtractSubrange(
int start, int num, Element** elements) {
+ typename internal::TypeImplementsMergeBehavior<
+ typename TypeHandler::Type>::type t;
+ ExtractSubrangeInternal(start, num, elements, t);
+}
+
+// ExtractSubrange() implementation for types that implement merge/copy
+// behavior.
+template <typename Element>
+inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
+ int start, int num, Element** elements, google::protobuf::internal::true_type) {
GOOGLE_DCHECK_GE(start, 0);
GOOGLE_DCHECK_GE(num, 0);
GOOGLE_DCHECK_LE(start + num, size());
@@ -1150,8 +1830,55 @@ inline void RepeatedPtrField<Element>::ExtractSubrange(
if (num > 0) {
// Save the values of the removed elements if requested.
if (elements != NULL) {
- for (int i = 0; i < num; ++i)
+ if (GetArenaNoVirtual() != NULL) {
+ // If we're on an arena, we perform a copy for each element so that the
+ // returned elements are heap-allocated.
+ for (int i = 0; i < num; ++i) {
+ Element* element = RepeatedPtrFieldBase::
+ Mutable<TypeHandler>(i + start);
+ typename TypeHandler::Type* new_value =
+ TypeHandler::NewFromPrototype(element, NULL);
+ TypeHandler::Merge(*element, new_value);
+ elements[i] = new_value;
+ }
+ } else {
+ for (int i = 0; i < num; ++i) {
+ elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+ }
+ }
+ }
+ CloseGap(start, num);
+ }
+}
+
+// ExtractSubrange() implementation for types that do not implement merge/copy
+// behavior.
+template<typename Element>
+inline void RepeatedPtrField<Element>::ExtractSubrangeInternal(
+ int start, int num, Element** elements, google::protobuf::internal::false_type) {
+ // This case is identical to UnsafeArenaExtractSubrange(). However, since
+ // ExtractSubrange() must return heap-allocated objects by contract, and we
+ // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that
+ // we are not on an arena.
+ GOOGLE_DCHECK(GetArenaNoVirtual() == NULL)
+ << "ExtractSubrange() when arena is non-NULL is only supported when "
+ << "the Element type supplies a MergeFrom() operation to make copies.";
+ UnsafeArenaExtractSubrange(start, num, elements);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::UnsafeArenaExtractSubrange(
+ int start, int num, Element** elements) {
+ GOOGLE_DCHECK_GE(start, 0);
+ GOOGLE_DCHECK_GE(num, 0);
+ GOOGLE_DCHECK_LE(start + num, size());
+
+ if (num > 0) {
+ // Save the values of the removed elements if requested.
+ if (elements != NULL) {
+ for (int i = 0; i < num; ++i) {
elements[i] = RepeatedPtrFieldBase::Mutable<TypeHandler>(i + start);
+ }
}
CloseGap(start, num);
}
@@ -1175,6 +1902,21 @@ inline void RepeatedPtrField<Element>::CopyFrom(
}
template <typename Element>
+inline typename RepeatedPtrField<Element>::iterator
+RepeatedPtrField<Element>::erase(const_iterator position) {
+ return erase(position, position + 1);
+}
+
+template <typename Element>
+inline typename RepeatedPtrField<Element>::iterator
+RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) {
+ size_type pos_offset = std::distance(cbegin(), first);
+ size_type last_offset = std::distance(cbegin(), last);
+ DeleteSubrange(pos_offset, last_offset - pos_offset);
+ return begin() + pos_offset;
+}
+
+template <typename Element>
inline Element** RepeatedPtrField<Element>::mutable_data() {
return RepeatedPtrFieldBase::mutable_data<TypeHandler>();
}
@@ -1185,16 +1927,32 @@ inline const Element* const* RepeatedPtrField<Element>::data() const {
}
template <typename Element>
-void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
- RepeatedPtrFieldBase::Swap(other);
+inline void RepeatedPtrField<Element>::Swap(RepeatedPtrField* other) {
+ if (this == other)
+ return;
+ RepeatedPtrFieldBase::Swap<TypeHandler>(other);
}
template <typename Element>
-void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
+inline void RepeatedPtrField<Element>::UnsafeArenaSwap(
+ RepeatedPtrField* other) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ if (this == other)
+ return;
+ RepeatedPtrFieldBase::InternalSwap(other);
+}
+
+template <typename Element>
+inline void RepeatedPtrField<Element>::SwapElements(int index1, int index2) {
RepeatedPtrFieldBase::SwapElements(index1, index2);
}
template <typename Element>
+inline Arena* RepeatedPtrField<Element>::GetArenaNoVirtual() const {
+ return RepeatedPtrFieldBase::GetArenaNoVirtual();
+}
+
+template <typename Element>
inline int RepeatedPtrField<Element>::SpaceUsedExcludingSelf() const {
return RepeatedPtrFieldBase::SpaceUsedExcludingSelf<TypeHandler>();
}
@@ -1205,10 +1963,19 @@ inline void RepeatedPtrField<Element>::AddAllocated(Element* value) {
}
template <typename Element>
+inline void RepeatedPtrField<Element>::UnsafeArenaAddAllocated(Element* value) {
+ RepeatedPtrFieldBase::UnsafeArenaAddAllocated<TypeHandler>(value);
+}
+
+template <typename Element>
inline Element* RepeatedPtrField<Element>::ReleaseLast() {
return RepeatedPtrFieldBase::ReleaseLast<TypeHandler>();
}
+template <typename Element>
+inline Element* RepeatedPtrField<Element>::UnsafeArenaReleaseLast() {
+ return RepeatedPtrFieldBase::UnsafeArenaReleaseLast<TypeHandler>();
+}
template <typename Element>
inline int RepeatedPtrField<Element>::ClearedCount() const {
@@ -1423,6 +2190,12 @@ class RepeatedPtrOverPtrsIterator
VoidPtr* it_;
};
+void RepeatedPtrFieldBase::InternalSwap(RepeatedPtrFieldBase* other) {
+ std::swap(rep_, other->rep_);
+ std::swap(current_size_, other->current_size_);
+ std::swap(total_size_, other->total_size_);
+}
+
} // namespace internal
template <typename Element>
@@ -1436,6 +2209,11 @@ RepeatedPtrField<Element>::begin() const {
return iterator(raw_data());
}
template <typename Element>
+inline typename RepeatedPtrField<Element>::const_iterator
+RepeatedPtrField<Element>::cbegin() const {
+ return begin();
+}
+template <typename Element>
inline typename RepeatedPtrField<Element>::iterator
RepeatedPtrField<Element>::end() {
return iterator(raw_data() + size());
@@ -1445,6 +2223,11 @@ inline typename RepeatedPtrField<Element>::const_iterator
RepeatedPtrField<Element>::end() const {
return iterator(raw_data() + size());
}
+template <typename Element>
+inline typename RepeatedPtrField<Element>::const_iterator
+RepeatedPtrField<Element>::cend() const {
+ return end();
+}
template <typename Element>
inline typename RepeatedPtrField<Element>::pointer_iterator
diff --git a/src/google/protobuf/repeated_field_reflection.h b/src/google/protobuf/repeated_field_reflection.h
new file mode 100644
index 00000000..08dfa7a5
--- /dev/null
+++ b/src/google/protobuf/repeated_field_reflection.h
@@ -0,0 +1,335 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This header file is protobuf internal. Users should not include this
+// file directly.
+#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
+#define GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// Interfaces used to implement reflection RepeatedFieldRef API.
+// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
+// object that implements the below interface.
+//
+// This interface passes/returns values using void pointers. The actual type
+// of the value depends on the field's cpp_type. Following is a mapping from
+// cpp_type to the type that should be used in this interface:
+//
+// field->cpp_type() T Actual type of void*
+// CPPTYPE_INT32 int32 int32
+// CPPTYPE_UINT32 uint32 uint32
+// CPPTYPE_INT64 int64 int64
+// CPPTYPE_UINT64 uint64 uint64
+// CPPTYPE_DOUBLE double double
+// CPPTYPE_FLOAT float float
+// CPPTYPE_BOOL bool bool
+// CPPTYPE_ENUM generated enum type int32
+// CPPTYPE_STRING string string
+// CPPTYPE_MESSAGE generated message type google::protobuf::Message
+// or google::protobuf::Message
+//
+// Note that for enums we use int32 in the interface.
+//
+// You can map from T to the actual type using RefTypeTraits:
+// typedef RefTypeTraits<T>::AccessorValueType ActualType;
+class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
+ public:
+ // Typedefs for clarity.
+ typedef void Field;
+ typedef void Value;
+ typedef void Iterator;
+
+ virtual ~RepeatedFieldAccessor();
+ virtual bool IsEmpty(const Field* data) const = 0;
+ virtual int Size(const Field* data) const = 0;
+ // Depends on the underlying representation of the repeated field, this
+ // method can return a pointer to the underlying object if such an object
+ // exists, or fill the data into scratch_space and return scratch_space.
+ // Callers of this method must ensure scratch_space is a valid pointer
+ // to a mutable object of the correct type.
+ virtual const Value* Get(
+ const Field* data, int index, Value* scratch_space) const = 0;
+
+ virtual void Clear(Field* data) const = 0;
+ virtual void Set(Field* data, int index, const Value* value) const = 0;
+ virtual void Add(Field* data, const Value* value) const = 0;
+ virtual void RemoveLast(Field* data) const = 0;
+ virtual void SwapElements(Field* data, int index1, int index2) const = 0;
+ virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
+ Field* other_data) const = 0;
+
+ // Create an iterator that points at the begining of the repeated field.
+ virtual Iterator* BeginIterator(const Field* data) const = 0;
+ // Create an iterator that points at the end of the repeated field.
+ virtual Iterator* EndIterator(const Field* data) const = 0;
+ // Make a copy of an iterator and return the new copy.
+ virtual Iterator* CopyIterator(const Field* data,
+ const Iterator* iterator) const = 0;
+ // Move an iterator to point to the next element.
+ virtual Iterator* AdvanceIterator(const Field* data,
+ Iterator* iterator) const = 0;
+ // Compare whether two iterators point to the same element.
+ virtual bool EqualsIterator(const Field* data, const Iterator* a,
+ const Iterator* b) const = 0;
+ // Delete an iterator created by BeginIterator(), EndIterator() and
+ // CopyIterator().
+ virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
+ // Like Get() but for iterators.
+ virtual const Value* GetIteratorValue(const Field* data,
+ const Iterator* iterator,
+ Value* scratch_space) const = 0;
+
+ // Templated methods that make using this interface easier for non-message
+ // types.
+ template<typename T>
+ T Get(const Field* data, int index) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ ActualType scratch_space;
+ return static_cast<T>(
+ *reinterpret_cast<const ActualType*>(
+ Get(data, index, static_cast<Value*>(&scratch_space))));
+ }
+
+ template<typename T, typename ValueType>
+ void Set(Field* data, int index, const ValueType& value) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ // In this RepeatedFieldAccessor interface we pass/return data using
+ // raw pointers. Type of the data these raw pointers point to should
+ // be ActualType. Here we have a ValueType object and want a ActualType
+ // pointer. We can't cast a ValueType pointer to an ActualType pointer
+ // directly because their type might be different (for enums ValueType
+ // may be a generated enum type while ActualType is int32). To be safe
+ // we make a copy to get a temporary ActualType object and use it.
+ ActualType tmp = static_cast<ActualType>(value);
+ Set(data, index, static_cast<const Value*>(&tmp));
+ }
+
+ template<typename T, typename ValueType>
+ void Add(Field* data, const ValueType& value) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ // In this RepeatedFieldAccessor interface we pass/return data using
+ // raw pointers. Type of the data these raw pointers point to should
+ // be ActualType. Here we have a ValueType object and want a ActualType
+ // pointer. We can't cast a ValueType pointer to an ActualType pointer
+ // directly because their type might be different (for enums ValueType
+ // may be a generated enum type while ActualType is int32). To be safe
+ // we make a copy to get a temporary ActualType object and use it.
+ ActualType tmp = static_cast<ActualType>(value);
+ Add(data, static_cast<const Value*>(&tmp));
+ }
+};
+
+// Implement (Mutable)RepeatedFieldRef::iterator
+template<typename T>
+class RepeatedFieldRefIterator
+ : public std::iterator<std::forward_iterator_tag, T> {
+ typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
+ typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
+ typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
+
+ public:
+ // Constructor for non-message fields.
+ RepeatedFieldRefIterator(const void* data,
+ const RepeatedFieldAccessor* accessor,
+ bool begin)
+ : data_(data), accessor_(accessor),
+ iterator_(begin ? accessor->BeginIterator(data) :
+ accessor->EndIterator(data)),
+ scratch_space_(new AccessorValueType) {
+ }
+ // Constructor for message fields.
+ RepeatedFieldRefIterator(const void* data,
+ const RepeatedFieldAccessor* accessor,
+ bool begin,
+ AccessorValueType* scratch_space)
+ : data_(data), accessor_(accessor),
+ iterator_(begin ? accessor->BeginIterator(data) :
+ accessor->EndIterator(data)),
+ scratch_space_(scratch_space) {
+ }
+ ~RepeatedFieldRefIterator() {
+ accessor_->DeleteIterator(data_, iterator_);
+ }
+ RepeatedFieldRefIterator operator++(int) {
+ RepeatedFieldRefIterator tmp(*this);
+ iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+ return tmp;
+ }
+ RepeatedFieldRefIterator& operator++() {
+ iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+ return *this;
+ }
+ IteratorValueType operator*() const {
+ return static_cast<IteratorValueType>(
+ *static_cast<const AccessorValueType*>(
+ accessor_->GetIteratorValue(
+ data_, iterator_, scratch_space_.get())));
+ }
+ IteratorPointerType operator->() const {
+ return static_cast<IteratorPointerType>(
+ accessor_->GetIteratorValue(
+ data_, iterator_, scratch_space_.get()));
+ }
+ bool operator!=(const RepeatedFieldRefIterator& other) const {
+ assert(data_ == other.data_);
+ assert(accessor_ == other.accessor_);
+ return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
+ }
+ bool operator==(const RepeatedFieldRefIterator& other) const {
+ return !this->operator!=(other);
+ }
+
+ RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
+ : data_(other.data_), accessor_(other.accessor_),
+ iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
+ }
+ RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
+ if (this != &other) {
+ accessor_->DeleteIterator(data_, iterator_);
+ data_ = other.data_;
+ accessor_ = other.accessor_;
+ iterator_ = accessor_->CopyIterator(data_, other.iterator_);
+ }
+ return *this;
+ }
+
+ protected:
+ const void* data_;
+ const RepeatedFieldAccessor* accessor_;
+ void* iterator_;
+ scoped_ptr<AccessorValueType> scratch_space_;
+};
+
+// TypeTraits that maps the type parameter T of RepeatedFieldRef or
+// MutableRepeatedFieldRef to corresponding iterator type,
+// RepeatedFieldAccessor type, etc.
+template<typename T>
+struct PrimitiveTraits {
+ static const bool is_primitive = false;
+};
+#define DEFINE_PRIMITIVE(TYPE, type) \
+ template<> struct PrimitiveTraits<type> { \
+ static const bool is_primitive = true; \
+ static const FieldDescriptor::CppType cpp_type = \
+ FieldDescriptor::CPPTYPE_ ## TYPE; \
+ };
+DEFINE_PRIMITIVE(INT32, int32)
+DEFINE_PRIMITIVE(UINT32, uint32)
+DEFINE_PRIMITIVE(INT64, int64)
+DEFINE_PRIMITIVE(UINT64, uint64)
+DEFINE_PRIMITIVE(FLOAT, float)
+DEFINE_PRIMITIVE(DOUBLE, double)
+DEFINE_PRIMITIVE(BOOL, bool)
+#undef DEFINE_PRIMITIVE
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef T AccessorValueType;
+ typedef T IteratorValueType;
+ typedef T* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ PrimitiveTraits<T>::cpp_type;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<internal::is_enum<T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ // We use int32 for repeated enums in RepeatedFieldAccessor.
+ typedef int32 AccessorValueType;
+ typedef T IteratorValueType;
+ typedef int32* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_ENUM;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef string AccessorValueType;
+ typedef string IteratorValueType;
+ typedef string* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_STRING;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct MessageDescriptorGetter {
+ static const Descriptor* get() {
+ return T::default_instance().GetDescriptor();
+ }
+};
+template<>
+struct MessageDescriptorGetter<Message> {
+ static const Descriptor* get() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef Message AccessorValueType;
+ typedef const T& IteratorValueType;
+ typedef const T* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_MESSAGE;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return MessageDescriptorGetter<T>::get();
+ }
+};
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__
diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc
index 62833aab..98c864d3 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.cc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -33,10 +33,12 @@
// Test reflection methods for aggregate access to Repeated[Ptr]Fields.
// This test proto2 methods on a proto2 layout.
-#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/reflection.h>
#include <gtest/gtest.h>
namespace google {
@@ -58,7 +60,6 @@ static string StrFunc(int i, int j) {
return str;
}
-
TEST(RepeatedFieldReflectionTest, RegularFields) {
TestAllTypes message;
const Reflection* refl = message.GetReflection();
@@ -113,7 +114,7 @@ TEST(RepeatedFieldReflectionTest, RegularFields) {
refl->MutableRepeatedPtrField<Message>(
&message, fd_repeated_foreign_message);
- // Make sure we can do get and sets through the Repeated[Ptr]Field objects.
+ // Make sure we can do gets and sets through the Repeated[Ptr]Field objects.
for (int i = 0; i < 10; ++i) {
// Check gets through const objects.
EXPECT_EQ(rf_int32.Get(i), Func(i, 1));
@@ -158,8 +159,6 @@ TEST(RepeatedFieldReflectionTest, RegularFields) {
}
-
-
TEST(RepeatedFieldReflectionTest, ExtensionFields) {
TestAllExtensions extended_message;
const Reflection* refl = extended_message.GetReflection();
@@ -190,6 +189,515 @@ TEST(RepeatedFieldReflectionTest, ExtensionFields) {
}
}
+template<typename Ref, typename MessageType, typename ValueType>
+void TestRepeatedFieldRefIterator(
+ const Ref& handle, const MessageType& message,
+ ValueType (MessageType::*GetFunc)(int) const) {
+ int index = 0;
+ for (typename Ref::const_iterator it = handle.begin();
+ it != handle.end(); ++it) {
+ ValueType value = static_cast<ValueType>(*it);
+ EXPECT_EQ((message.*GetFunc)(index), value);
+ ++index;
+ }
+ EXPECT_EQ(handle.size(), index);
+}
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
+ TestAllTypes message;
+ const Reflection* refl = message.GetReflection();
+ const Descriptor* desc = message.GetDescriptor();
+
+ for (int i = 0; i < 10; ++i) {
+ message.add_repeated_int32(Func(i, 1));
+ message.add_repeated_double(Func(i, 2));
+ message.add_repeated_string(StrFunc(i, 5));
+ message.add_repeated_foreign_message()->set_c(Func(i, 6));
+ }
+
+ // Get FieldDescriptors for all the fields of interest.
+ const FieldDescriptor* fd_repeated_int32 =
+ desc->FindFieldByName("repeated_int32");
+ const FieldDescriptor* fd_repeated_double =
+ desc->FindFieldByName("repeated_double");
+ const FieldDescriptor* fd_repeated_string =
+ desc->FindFieldByName("repeated_string");
+ const FieldDescriptor* fd_repeated_foreign_message =
+ desc->FindFieldByName("repeated_foreign_message");
+
+ // Get RepeatedFieldRef objects for all fields of interest.
+ const RepeatedFieldRef<int32> rf_int32 =
+ refl->GetRepeatedFieldRef<int32>(message, fd_repeated_int32);
+ const RepeatedFieldRef<double> rf_double =
+ refl->GetRepeatedFieldRef<double>(message, fd_repeated_double);
+ const RepeatedFieldRef<string> rf_string =
+ refl->GetRepeatedFieldRef<string>(message, fd_repeated_string);
+ const RepeatedFieldRef<ForeignMessage> rf_foreign_message =
+ refl->GetRepeatedFieldRef<ForeignMessage>(
+ message, fd_repeated_foreign_message);
+ const RepeatedFieldRef<Message> rf_message =
+ refl->GetRepeatedFieldRef<Message>(
+ message, fd_repeated_foreign_message);
+
+ // Get MutableRepeatedFieldRef objects for all fields of interest.
+ const MutableRepeatedFieldRef<int32> mrf_int32 =
+ refl->GetMutableRepeatedFieldRef<int32>(&message, fd_repeated_int32);
+ const MutableRepeatedFieldRef<double> mrf_double =
+ refl->GetMutableRepeatedFieldRef<double>(&message, fd_repeated_double);
+ const MutableRepeatedFieldRef<string> mrf_string =
+ refl->GetMutableRepeatedFieldRef<string>(&message, fd_repeated_string);
+ const MutableRepeatedFieldRef<ForeignMessage> mrf_foreign_message =
+ refl->GetMutableRepeatedFieldRef<ForeignMessage>(
+ &message, fd_repeated_foreign_message);
+ const MutableRepeatedFieldRef<Message> mrf_message =
+ refl->GetMutableRepeatedFieldRef<Message>(
+ &message, fd_repeated_foreign_message);
+
+ EXPECT_EQ(message.repeated_int32_size(), rf_int32.size());
+ EXPECT_EQ(message.repeated_int32_size(), mrf_int32.size());
+ EXPECT_EQ(message.repeated_double_size(), rf_double.size());
+ EXPECT_EQ(message.repeated_double_size(), mrf_double.size());
+ EXPECT_EQ(message.repeated_string_size(), rf_string.size());
+ EXPECT_EQ(message.repeated_string_size(), mrf_string.size());
+ EXPECT_EQ(message.repeated_foreign_message_size(),
+ rf_foreign_message.size());
+ EXPECT_EQ(message.repeated_foreign_message_size(),
+ mrf_foreign_message.size());
+ EXPECT_EQ(message.repeated_foreign_message_size(), rf_message.size());
+ EXPECT_EQ(message.repeated_foreign_message_size(), mrf_message.size());
+
+ EXPECT_FALSE(rf_int32.empty());
+ EXPECT_FALSE(mrf_int32.empty());
+ EXPECT_FALSE(rf_double.empty());
+ EXPECT_FALSE(mrf_double.empty());
+ EXPECT_FALSE(rf_string.empty());
+ EXPECT_FALSE(mrf_string.empty());
+ EXPECT_FALSE(rf_foreign_message.empty());
+ EXPECT_FALSE(mrf_foreign_message.empty());
+ EXPECT_FALSE(rf_message.empty());
+ EXPECT_FALSE(mrf_message.empty());
+
+ // Make sure we can do gets and sets through the RepeatedFieldRef objects.
+ for (int i = 0; i < 10; ++i) {
+ // Check gets through const objects.
+ EXPECT_EQ(rf_int32.Get(i), Func(i, 1));
+ EXPECT_EQ(rf_double.Get(i), Func(i, 2));
+ EXPECT_EQ(rf_string.Get(i), StrFunc(i, 5));
+ ForeignMessage scratch_space;
+ EXPECT_EQ(rf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6));
+ EXPECT_EQ(down_cast<const ForeignMessage&>(
+ rf_message.Get(i, &scratch_space)).c(), Func(i, 6));
+
+ // Check gets through mutable objects.
+ EXPECT_EQ(mrf_int32.Get(i), Func(i, 1));
+ EXPECT_EQ(mrf_double.Get(i), Func(i, 2));
+ EXPECT_EQ(mrf_string.Get(i), StrFunc(i, 5));
+ EXPECT_EQ(mrf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6));
+ EXPECT_EQ(down_cast<const ForeignMessage&>(
+ mrf_message.Get(i, &scratch_space)).c(), Func(i, 6));
+
+ // Check sets through mutable objects.
+ mrf_int32.Set(i, Func(i, -1));
+ mrf_double.Set(i, Func(i, -2));
+ mrf_string.Set(i, StrFunc(i, -5));
+ ForeignMessage foreign_message;
+ foreign_message.set_c(Func(i, -6));
+ mrf_foreign_message.Set(i, foreign_message);
+ EXPECT_EQ(message.repeated_int32(i), Func(i, -1));
+ EXPECT_EQ(message.repeated_double(i), Func(i, -2));
+ EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5));
+ EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6));
+ foreign_message.set_c(Func(i, 7));
+ mrf_message.Set(i, foreign_message);
+ EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7));
+ }
+
+ // Test iterators.
+ TestRepeatedFieldRefIterator(rf_int32, message,
+ &TestAllTypes::repeated_int32);
+ TestRepeatedFieldRefIterator(rf_double, message,
+ &TestAllTypes::repeated_double);
+ TestRepeatedFieldRefIterator(rf_string, message,
+ &TestAllTypes::repeated_string);
+
+ // Test iterators for message fields.
+ typedef RepeatedFieldRef<ForeignMessage>::iterator MessageIterator;
+ int index = 0;
+ for (MessageIterator it = rf_foreign_message.begin();
+ it != rf_foreign_message.end(); ++it) {
+ EXPECT_EQ(message.repeated_foreign_message(index).c(), it->c());
+ ++index;
+ }
+ EXPECT_EQ(10, index);
+
+ // Test iterator operators that are not ususally used in regular for-loops.
+ // Including: post increment, assign, ==.
+ MessageIterator old_it = rf_foreign_message.begin();
+ MessageIterator new_it = old_it++;
+ EXPECT_FALSE(old_it == new_it);
+ // Check that old_it++ increments old_it once.
+ for (index = 1; old_it != rf_foreign_message.end(); ++old_it, ++index) {
+ EXPECT_EQ(message.repeated_foreign_message(index).c(), old_it->c());
+ }
+ EXPECT_EQ(10, index);
+ // Test assign operator.
+ old_it = new_it;
+ for (index = 0; old_it != rf_foreign_message.end(); ++old_it, ++index) {
+ EXPECT_EQ(message.repeated_foreign_message(index).c(), old_it->c());
+ }
+ EXPECT_EQ(10, index);
+ // Check that the returned value of old_it++ is the one before increment.
+ for (index = 0; new_it != rf_foreign_message.end(); ++new_it, ++index) {
+ EXPECT_EQ(message.repeated_foreign_message(index).c(), new_it->c());
+ }
+ EXPECT_EQ(10, index);
+
+ // Test MutableRepeatedFieldRef::Add()
+ mrf_int32.Add(1234);
+ mrf_double.Add(1234.0);
+ mrf_string.Add("1234");
+ ForeignMessage foreign_message;
+ foreign_message.set_c(1234);
+ mrf_foreign_message.Add(foreign_message);
+ EXPECT_EQ(1234, message.repeated_int32(10));
+ EXPECT_EQ(1234.0, message.repeated_double(10));
+ EXPECT_EQ("1234", message.repeated_string(10));
+ EXPECT_EQ(1234, message.repeated_foreign_message(10).c());
+
+ // Test MutableRepeatedFieldRef::RemoveLast()
+ mrf_int32.RemoveLast();
+ mrf_double.RemoveLast();
+ mrf_string.RemoveLast();
+ mrf_foreign_message.RemoveLast();
+ EXPECT_EQ(10, message.repeated_int32_size());
+ EXPECT_EQ(10, message.repeated_double_size());
+ EXPECT_EQ(10, message.repeated_string_size());
+ EXPECT_EQ(10, message.repeated_foreign_message_size());
+
+ // Test MutableRepeatedFieldRef::SwapElements()
+ mrf_int32.SwapElements(0, 9);
+ mrf_double.SwapElements(0, 9);
+ mrf_string.SwapElements(0, 9);
+ mrf_foreign_message.SwapElements(0, 9);
+ EXPECT_EQ(Func(9, -1), message.repeated_int32(0));
+ EXPECT_EQ(Func(0, -1), message.repeated_int32(9));
+ EXPECT_EQ(Func(9, -2), message.repeated_double(0));
+ EXPECT_EQ(Func(0, -2), message.repeated_double(9));
+ EXPECT_EQ(StrFunc(9, -5), message.repeated_string(0));
+ EXPECT_EQ(StrFunc(0, -5), message.repeated_string(9));
+ EXPECT_EQ(Func(9, 7), message.repeated_foreign_message(0).c());
+ EXPECT_EQ(Func(0, 7), message.repeated_foreign_message(9).c());
+
+ // Test MutableRepeatedFieldRef::Clear()
+ mrf_int32.Clear();
+ mrf_double.Clear();
+ mrf_string.Clear();
+ mrf_foreign_message.Clear();
+ EXPECT_EQ(0, message.repeated_int32_size());
+ EXPECT_EQ(0, message.repeated_double_size());
+ EXPECT_EQ(0, message.repeated_string_size());
+ EXPECT_EQ(0, message.repeated_foreign_message_size());
+
+ // Test (Mutable)RepeatedFieldRef::empty()
+ EXPECT_TRUE(rf_int32.empty());
+ EXPECT_TRUE(mrf_int32.empty());
+ EXPECT_TRUE(rf_double.empty());
+ EXPECT_TRUE(mrf_double.empty());
+ EXPECT_TRUE(rf_string.empty());
+ EXPECT_TRUE(mrf_string.empty());
+ EXPECT_TRUE(rf_foreign_message.empty());
+ EXPECT_TRUE(mrf_foreign_message.empty());
+ EXPECT_TRUE(rf_message.empty());
+ EXPECT_TRUE(mrf_message.empty());
+
+ // Make sure types are checked correctly at runtime.
+ const FieldDescriptor* fd_optional_int32 =
+ desc->FindFieldByName("optional_int32");
+ EXPECT_DEATH(refl->GetRepeatedFieldRef<int32>(
+ message, fd_optional_int32), "");
+ EXPECT_DEATH(refl->GetRepeatedFieldRef<double>(
+ message, fd_repeated_int32), "");
+ EXPECT_DEATH(refl->GetRepeatedFieldRef<TestAllTypes>(
+ message, fd_repeated_foreign_message), "");
+}
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForEnums) {
+ TestAllTypes message;
+ const Reflection* refl = message.GetReflection();
+ const Descriptor* desc = message.GetDescriptor();
+
+ for (int i = 0; i < 10; ++i) {
+ message.add_repeated_nested_enum(TestAllTypes::BAR);
+ }
+
+ const FieldDescriptor* fd_repeated_nested_enum =
+ desc->FindFieldByName("repeated_nested_enum");
+ const RepeatedFieldRef<TestAllTypes::NestedEnum> enum_ref =
+ refl->GetRepeatedFieldRef<TestAllTypes::NestedEnum>(
+ message, fd_repeated_nested_enum);
+ const MutableRepeatedFieldRef<TestAllTypes::NestedEnum>
+ mutable_enum_ref =
+ refl->GetMutableRepeatedFieldRef<TestAllTypes::NestedEnum>(
+ &message, fd_repeated_nested_enum);
+ const RepeatedFieldRef<int32> int32_ref =
+ refl->GetRepeatedFieldRef<int32>(
+ message, fd_repeated_nested_enum);
+ const MutableRepeatedFieldRef<int32> mutable_int32_ref =
+ refl->GetMutableRepeatedFieldRef<int32>(
+ &message, fd_repeated_nested_enum);
+
+ EXPECT_EQ(message.repeated_nested_enum_size(), enum_ref.size());
+ EXPECT_EQ(message.repeated_nested_enum_size(), mutable_enum_ref.size());
+ EXPECT_EQ(message.repeated_nested_enum_size(), int32_ref.size());
+ EXPECT_EQ(message.repeated_nested_enum_size(), mutable_int32_ref.size());
+
+ EXPECT_FALSE(enum_ref.empty());
+ EXPECT_FALSE(mutable_enum_ref.empty());
+ EXPECT_FALSE(int32_ref.empty());
+ EXPECT_FALSE(mutable_int32_ref.empty());
+
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(i));
+ EXPECT_EQ(TestAllTypes::BAR, mutable_enum_ref.Get(i));
+ mutable_enum_ref.Set(i, TestAllTypes::BAZ);
+ EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(i));
+ EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(i));
+
+ message.set_repeated_nested_enum(i, TestAllTypes::BAR);
+ EXPECT_EQ(TestAllTypes::BAR, int32_ref.Get(i));
+ EXPECT_EQ(TestAllTypes::BAR, mutable_int32_ref.Get(i));
+ mutable_int32_ref.Set(i, TestAllTypes::BAZ);
+ EXPECT_EQ(TestAllTypes::BAZ, int32_ref.Get(i));
+ EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(i));
+ }
+
+ TestRepeatedFieldRefIterator(enum_ref, message,
+ &TestAllTypes::repeated_nested_enum);
+ TestRepeatedFieldRefIterator(int32_ref, message,
+ &TestAllTypes::repeated_nested_enum);
+
+ // Test Add()
+ mutable_enum_ref.Add(TestAllTypes::FOO);
+ EXPECT_EQ(TestAllTypes::FOO, message.repeated_nested_enum(10));
+ mutable_int32_ref.Add(TestAllTypes::BAR);
+ EXPECT_EQ(TestAllTypes::BAR, message.repeated_nested_enum(11));
+
+ // Test RemoveLast()
+ mutable_enum_ref.RemoveLast();
+ EXPECT_EQ(11, message.repeated_nested_enum_size());
+ mutable_int32_ref.RemoveLast();
+ EXPECT_EQ(10, message.repeated_nested_enum_size());
+
+ // Test SwapElements()
+ mutable_enum_ref.Set(0, TestAllTypes::BAR);
+ mutable_enum_ref.Set(9, TestAllTypes::BAZ);
+ mutable_enum_ref.SwapElements(0, 9);
+ EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(0));
+ EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(9));
+ mutable_int32_ref.SwapElements(0, 9);
+ EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(0));
+ EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(9));
+
+ // Test Clear()
+ mutable_enum_ref.Clear();
+ EXPECT_EQ(0, message.repeated_nested_enum_size());
+ mutable_enum_ref.Add(TestAllTypes::FOO);
+ EXPECT_EQ(1, message.repeated_nested_enum_size());
+ mutable_int32_ref.Clear();
+ EXPECT_EQ(0, message.repeated_nested_enum_size());
+
+ // Test empty()
+ EXPECT_TRUE(enum_ref.empty());
+ EXPECT_TRUE(mutable_enum_ref.empty());
+ EXPECT_TRUE(int32_ref.empty());
+ EXPECT_TRUE(mutable_int32_ref.empty());
+}
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForExtensionFields) {
+ TestAllExtensions extended_message;
+ const Reflection* refl = extended_message.GetReflection();
+ const Descriptor* desc = extended_message.GetDescriptor();
+
+ for (int i = 0; i < 10; ++i) {
+ extended_message.AddExtension(
+ unittest::repeated_int64_extension, Func(i, 1));
+ }
+
+ const FieldDescriptor* fd_repeated_int64_extension =
+ desc->file()->FindExtensionByName("repeated_int64_extension");
+ GOOGLE_CHECK(fd_repeated_int64_extension != NULL);
+
+ const RepeatedFieldRef<int64> rf_int64_extension =
+ refl->GetRepeatedFieldRef<int64>(extended_message,
+ fd_repeated_int64_extension);
+
+ const MutableRepeatedFieldRef<int64> mrf_int64_extension =
+ refl->GetMutableRepeatedFieldRef<int64>(&extended_message,
+ fd_repeated_int64_extension);
+
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i));
+ mrf_int64_extension.Set(i, Func(i, -1));
+ EXPECT_EQ(Func(i, -1),
+ extended_message.GetExtension(unittest::repeated_int64_extension, i));
+ }
+}
+
+
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) {
+ // Set-up message content.
+ TestAllTypes m0, m1, m2;
+ for (int i = 0; i < 10; ++i) {
+ m0.add_repeated_int32(Func(i, 1));
+ m0.add_repeated_double(Func(i, 2));
+ m0.add_repeated_string(StrFunc(i, 5));
+ m0.add_repeated_foreign_message()->set_c(Func(i, 6));
+ m0.add_repeated_nested_enum(TestAllTypes::FOO);
+ m1.add_repeated_int32(Func(i, 11));
+ m1.add_repeated_double(Func(i, 12));
+ m1.add_repeated_string(StrFunc(i, 15));
+ m1.add_repeated_foreign_message()->set_c(Func(i, 16));
+ m1.add_repeated_nested_enum(TestAllTypes::BAR);
+ m2.add_repeated_int32(Func(i, 21));
+ m2.add_repeated_double(Func(i, 22));
+ m2.add_repeated_string(StrFunc(i, 25));
+ m2.add_repeated_foreign_message()->set_c(Func(i, 26));
+ m2.add_repeated_nested_enum(TestAllTypes::BAZ);
+ }
+
+ const Reflection* refl = m0.GetReflection();
+ const Descriptor* desc = m0.GetDescriptor();
+
+ // Get FieldDescriptors for all the fields of interest.
+ const FieldDescriptor* fd_repeated_int32 =
+ desc->FindFieldByName("repeated_int32");
+ const FieldDescriptor* fd_repeated_double =
+ desc->FindFieldByName("repeated_double");
+ const FieldDescriptor* fd_repeated_string =
+ desc->FindFieldByName("repeated_string");
+ const FieldDescriptor* fd_repeated_foreign_message =
+ desc->FindFieldByName("repeated_foreign_message");
+ const FieldDescriptor* fd_repeated_nested_enum =
+ desc->FindFieldByName("repeated_nested_enum");
+
+ // Get MutableRepeatedFieldRef objects for all fields of interest.
+ const MutableRepeatedFieldRef<int32> mrf_int32 =
+ refl->GetMutableRepeatedFieldRef<int32>(&m0, fd_repeated_int32);
+ const MutableRepeatedFieldRef<double> mrf_double =
+ refl->GetMutableRepeatedFieldRef<double>(&m0, fd_repeated_double);
+ const MutableRepeatedFieldRef<string> mrf_string =
+ refl->GetMutableRepeatedFieldRef<string>(&m0, fd_repeated_string);
+ const MutableRepeatedFieldRef<ForeignMessage> mrf_foreign_message =
+ refl->GetMutableRepeatedFieldRef<ForeignMessage>(
+ &m0, fd_repeated_foreign_message);
+ const MutableRepeatedFieldRef<TestAllTypes::NestedEnum>
+ mrf_nested_enum =
+ refl->GetMutableRepeatedFieldRef<TestAllTypes::NestedEnum>(
+ &m0, fd_repeated_nested_enum);
+
+ // Test MutableRepeatedRef::CopyFrom
+ mrf_int32.CopyFrom(
+ refl->GetRepeatedFieldRef<int32>(m1, fd_repeated_int32));
+ mrf_double.CopyFrom(
+ refl->GetRepeatedFieldRef<double>(m1, fd_repeated_double));
+ mrf_string.CopyFrom(
+ refl->GetRepeatedFieldRef<string>(m1, fd_repeated_string));
+ mrf_foreign_message.CopyFrom(
+ refl->GetRepeatedFieldRef<ForeignMessage>(
+ m1, fd_repeated_foreign_message));
+ mrf_nested_enum.CopyFrom(
+ refl->GetRepeatedFieldRef<TestAllTypes::NestedEnum>(
+ m1, fd_repeated_nested_enum));
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(Func(i, 11), m0.repeated_int32(i));
+ EXPECT_EQ(Func(i, 12), m0.repeated_double(i));
+ EXPECT_EQ(StrFunc(i, 15), m0.repeated_string(i));
+ EXPECT_EQ(Func(i, 16), m0.repeated_foreign_message(i).c());
+ EXPECT_EQ(TestAllTypes::BAR, m0.repeated_nested_enum(i));
+ }
+
+ // Test MutableRepeatedRef::MergeFrom
+ mrf_int32.MergeFrom(
+ refl->GetRepeatedFieldRef<int32>(m2, fd_repeated_int32));
+ mrf_double.MergeFrom(
+ refl->GetRepeatedFieldRef<double>(m2, fd_repeated_double));
+ mrf_string.MergeFrom(
+ refl->GetRepeatedFieldRef<string>(m2, fd_repeated_string));
+ mrf_foreign_message.MergeFrom(
+ refl->GetRepeatedFieldRef<ForeignMessage>(
+ m2, fd_repeated_foreign_message));
+ mrf_nested_enum.MergeFrom(
+ refl->GetRepeatedFieldRef<TestAllTypes::NestedEnum>(
+ m2, fd_repeated_nested_enum));
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(Func(i, 21), m0.repeated_int32(i + 10));
+ EXPECT_EQ(Func(i, 22), m0.repeated_double(i + 10));
+ EXPECT_EQ(StrFunc(i, 25), m0.repeated_string(i + 10));
+ EXPECT_EQ(Func(i, 26), m0.repeated_foreign_message(i + 10).c());
+ EXPECT_EQ(TestAllTypes::BAZ, m0.repeated_nested_enum(i + 10));
+ }
+
+ // Test MutableRepeatedRef::Swap
+ // Swap between m0 and m2.
+ mrf_int32.Swap(
+ refl->GetMutableRepeatedFieldRef<int32>(&m2, fd_repeated_int32));
+ mrf_double.Swap(
+ refl->GetMutableRepeatedFieldRef<double>(&m2, fd_repeated_double));
+ mrf_string.Swap(
+ refl->GetMutableRepeatedFieldRef<string>(&m2, fd_repeated_string));
+ mrf_foreign_message.Swap(
+ refl->GetMutableRepeatedFieldRef<ForeignMessage>(
+ &m2, fd_repeated_foreign_message));
+ mrf_nested_enum.Swap(
+ refl->GetMutableRepeatedFieldRef<TestAllTypes::NestedEnum>(
+ &m2, fd_repeated_nested_enum));
+ for (int i = 0; i < 10; ++i) {
+ // Check the content of m0.
+ EXPECT_EQ(Func(i, 21), m0.repeated_int32(i));
+ EXPECT_EQ(Func(i, 22), m0.repeated_double(i));
+ EXPECT_EQ(StrFunc(i, 25), m0.repeated_string(i));
+ EXPECT_EQ(Func(i, 26), m0.repeated_foreign_message(i).c());
+ EXPECT_EQ(TestAllTypes::BAZ, m0.repeated_nested_enum(i));
+
+ // Check the content of m2.
+ EXPECT_EQ(Func(i, 11), m2.repeated_int32(i));
+ EXPECT_EQ(Func(i, 12), m2.repeated_double(i));
+ EXPECT_EQ(StrFunc(i, 15), m2.repeated_string(i));
+ EXPECT_EQ(Func(i, 16), m2.repeated_foreign_message(i).c());
+ EXPECT_EQ(TestAllTypes::BAR, m2.repeated_nested_enum(i));
+ EXPECT_EQ(Func(i, 21), m2.repeated_int32(i + 10));
+ EXPECT_EQ(Func(i, 22), m2.repeated_double(i + 10));
+ EXPECT_EQ(StrFunc(i, 25), m2.repeated_string(i + 10));
+ EXPECT_EQ(Func(i, 26), m2.repeated_foreign_message(i + 10).c());
+ EXPECT_EQ(TestAllTypes::BAZ, m2.repeated_nested_enum(i + 10));
+ }
+}
+
+// Test that GetRepeatedFieldRef/MutableRepeatedFieldRef works with
+// DynamicMessage.
+TEST(RepeatedFieldReflectionTest, RepeatedFieldRefDynamicMessage) {
+ // DynamicMessage shares the same memory layout as generated message
+ // and use the same GeneratedMessageReflection code for reflection.
+ // All code paths should already be covered by the other tests for
+ // generated messages. Here we just test one field.
+
+ const Descriptor* desc = TestAllTypes::descriptor();
+ const FieldDescriptor* fd_repeated_int32 =
+ desc->FindFieldByName("repeated_int32");
+
+ DynamicMessageFactory factory;
+ scoped_ptr<Message> dynamic_message(factory.GetPrototype(desc)->New());
+ const Reflection* refl = dynamic_message->GetReflection();
+
+ MutableRepeatedFieldRef<int32> rf_int32 =
+ refl->GetMutableRepeatedFieldRef<int32>(
+ dynamic_message.get(), fd_repeated_int32);
+ rf_int32.Add(1234);
+ EXPECT_EQ(1, refl->FieldSize(*dynamic_message, fd_repeated_int32));
+ EXPECT_EQ(1234, refl->GetRepeatedInt32(*dynamic_message,
+ fd_repeated_int32, 0));
+}
+
} // namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index f4d48f59..9942af50 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -92,7 +92,8 @@ TEST(RepeatedField, Small) {
EXPECT_TRUE(field.empty());
EXPECT_EQ(field.size(), 0);
- int expected_usage = 4 * sizeof(int);
+ // Additional 8 bytes are for 'struct Rep' header.
+ int expected_usage = 4 * sizeof(int) + 8;
EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage);
}
@@ -295,6 +296,39 @@ TEST(RepeatedField, CopyFromSelf) {
EXPECT_EQ(3, me.Get(0));
}
+TEST(RepeatedField, Erase) {
+ RepeatedField<int> me;
+ RepeatedField<int>::iterator it = me.erase(me.begin(), me.end());
+ EXPECT_TRUE(me.begin() == it);
+ EXPECT_EQ(0, me.size());
+
+ me.Add(1);
+ me.Add(2);
+ me.Add(3);
+ it = me.erase(me.begin(), me.end());
+ EXPECT_TRUE(me.begin() == it);
+ EXPECT_EQ(0, me.size());
+
+ me.Add(4);
+ me.Add(5);
+ me.Add(6);
+ it = me.erase(me.begin() + 2, me.end());
+ EXPECT_TRUE(me.begin() + 2 == it);
+ EXPECT_EQ(2, me.size());
+ EXPECT_EQ(4, me.Get(0));
+ EXPECT_EQ(5, me.Get(1));
+
+ me.Add(6);
+ me.Add(7);
+ me.Add(8);
+ it = me.erase(me.begin() + 1, me.begin() + 3);
+ EXPECT_TRUE(me.begin() + 1 == it);
+ EXPECT_EQ(3, me.size());
+ EXPECT_EQ(4, me.Get(0));
+ EXPECT_EQ(7, me.Get(1));
+ EXPECT_EQ(8, me.Get(2));
+}
+
TEST(RepeatedField, CopyConstruct) {
RepeatedField<int> source;
source.Add(1);
@@ -741,6 +775,39 @@ TEST(RepeatedPtrField, CopyFromSelf) {
EXPECT_EQ("1", me.Get(0));
}
+TEST(RepeatedPtrField, Erase) {
+ RepeatedPtrField<string> me;
+ RepeatedPtrField<string>::iterator it = me.erase(me.begin(), me.end());
+ EXPECT_TRUE(me.begin() == it);
+ EXPECT_EQ(0, me.size());
+
+ *me.Add() = "1";
+ *me.Add() = "2";
+ *me.Add() = "3";
+ it = me.erase(me.begin(), me.end());
+ EXPECT_TRUE(me.begin() == it);
+ EXPECT_EQ(0, me.size());
+
+ *me.Add() = "4";
+ *me.Add() = "5";
+ *me.Add() = "6";
+ it = me.erase(me.begin() + 2, me.end());
+ EXPECT_TRUE(me.begin() + 2 == it);
+ EXPECT_EQ(2, me.size());
+ EXPECT_EQ("4", me.Get(0));
+ EXPECT_EQ("5", me.Get(1));
+
+ *me.Add() = "6";
+ *me.Add() = "7";
+ *me.Add() = "8";
+ it = me.erase(me.begin() + 1, me.begin() + 3);
+ EXPECT_TRUE(me.begin() + 1 == it);
+ EXPECT_EQ(3, me.size());
+ EXPECT_EQ("4", me.Get(0));
+ EXPECT_EQ("7", me.Get(1));
+ EXPECT_EQ("8", me.Get(2));
+}
+
TEST(RepeatedPtrField, CopyConstruct) {
RepeatedPtrField<string> source;
source.Add()->assign("1");
diff --git a/src/google/protobuf/stubs/atomic_sequence_num.h b/src/google/protobuf/stubs/atomic_sequence_num.h
new file mode 100644
index 00000000..bb20942f
--- /dev/null
+++ b/src/google/protobuf/stubs/atomic_sequence_num.h
@@ -0,0 +1,54 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifndef GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_
+#define GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_
+
+#include <google/protobuf/stubs/atomicops.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+class SequenceNumber {
+ public:
+ SequenceNumber() : word_(0) {}
+
+ AtomicWord GetNext() {
+ return NoBarrier_AtomicIncrement(&word_, 1) - 1;
+ }
+ private:
+ AtomicWord word_;
+};
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_ATOMIC_SEQUENCE_NUM_H_
diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h
new file mode 100644
index 00000000..cccf65a1
--- /dev/null
+++ b/src/google/protobuf/stubs/casts.h
@@ -0,0 +1,123 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_CASTS_H__
+#define GOOGLE_PROTOBUF_CASTS_H__
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/type_traits.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+// Use implicit_cast as a safe version of static_cast or const_cast
+// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
+// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
+// a const pointer to Foo).
+// When you use implicit_cast, the compiler checks that the cast is safe.
+// Such explicit implicit_casts are necessary in surprisingly many
+// situations where C++ demands an exact type match instead of an
+// argument type convertable to a target type.
+//
+// The From type can be inferred, so the preferred syntax for using
+// implicit_cast is the same as for static_cast etc.:
+//
+// implicit_cast<ToType>(expr)
+//
+// implicit_cast would have been part of the C++ standard library,
+// but the proposal was submitted too late. It will probably make
+// its way into the language in the future.
+template<typename To, typename From>
+inline To implicit_cast(From const &f) {
+ return f;
+}
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
+// always succeed. When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo? It
+// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
+// when you downcast, you should use this macro. In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not). In normal mode, we do the efficient static_cast<>
+// instead. Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+// This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+
+template<typename To, typename From> // use like this: down_cast<T*>(foo);
+inline To down_cast(From* f) { // so we only accept pointers
+ // Ensures that To is a sub-type of From *. This test is here only
+ // for compile-time type checking, and has no overhead in an
+ // optimized build at run-time, as it will be optimized away
+ // completely.
+ if (false) {
+ implicit_cast<From*, To>(0);
+ }
+
+#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
+ assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
+#endif
+ return static_cast<To>(f);
+}
+
+template<typename To, typename From> // use like this: down_cast<T&>(foo);
+inline To down_cast(From& f) {
+ typedef typename remove_reference<To>::type* ToAsPointer;
+ // Ensures that To is a sub-type of From *. This test is here only
+ // for compile-time type checking, and has no overhead in an
+ // optimized build at run-time, as it will be optimized away
+ // completely.
+ if (false) {
+ implicit_cast<From*, ToAsPointer>(0);
+ }
+
+#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
+ // RTTI: debug mode only!
+ assert(dynamic_cast<ToAsPointer>(&f) != NULL);
+#endif
+ return *static_cast<ToAsPointer>(&f);
+}
+
+} // namespace internal
+
+// We made these internal so that they would show up as such in the docs,
+// but we don't want to stick "internal::" in front of them everywhere.
+using internal::implicit_cast;
+using internal::down_cast;
+
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_CASTS_H__
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
index 1e02b228..54e00ccb 100644
--- a/src/google/protobuf/stubs/common.cc
+++ b/src/google/protobuf/stubs/common.cc
@@ -171,6 +171,7 @@ DECLARE_STREAM_OPERATOR(uint , "%u" )
DECLARE_STREAM_OPERATOR(long , "%ld")
DECLARE_STREAM_OPERATOR(unsigned long, "%lu")
DECLARE_STREAM_OPERATOR(double , "%g" )
+DECLARE_STREAM_OPERATOR(void* , "%p" )
#undef DECLARE_STREAM_OPERATOR
LogMessage::LogMessage(LogLevel level, const char* filename, int line)
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index dde48f47..ca7be71f 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -218,6 +218,17 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
#endif
#endif
+#ifndef GOOGLE_ATTRIBUTE_NOINLINE
+#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+// For functions we want to force not inline.
+// Introduced in gcc 3.1.
+#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline))
+#else
+// Other compilers will have to figure it out for themselves.
+#define GOOGLE_ATTRIBUTE_NOINLINE
+#endif
+#endif
+
#ifndef GOOGLE_ATTRIBUTE_DEPRECATED
#ifdef __GNUC__
// If the method/variable/type is used anywhere, produce a warning.
@@ -236,6 +247,15 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
#endif
#endif
+#ifndef GOOGLE_PREDICT_FALSE
+#ifdef __GNUC__
+// Provided at least since GCC 3.0.
+#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(!!(x), 1))
+#else
+#define GOOGLE_PREDICT_FALSE
+#endif
+#endif
+
// Delimits a block of code which may write to memory which is simultaneously
// written by other threads, but which has been determined to be thread-safe
// (e.g. because it is an idempotent write).
@@ -246,6 +266,52 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
#define GOOGLE_SAFE_CONCURRENT_WRITES_END()
#endif
+#define GOOGLE_GUARDED_BY(x)
+
+// x86 and x86-64 can perform unaligned loads/stores directly.
+#if defined(_M_X64) || defined(__x86_64__) || \
+ defined(_M_IX86) || defined(__i386__)
+
+#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
+#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
+
+#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
+
+#else
+inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) {
+ uint16 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) {
+ uint32 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) {
+ uint64 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
+ memcpy(p, &v, sizeof v);
+}
+#endif
+
// ===================================================================
// from google3/base/basictypes.h
@@ -288,71 +354,6 @@ static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF);
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-namespace internal {
-
-// Use implicit_cast as a safe version of static_cast or const_cast
-// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
-// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
-// a const pointer to Foo).
-// When you use implicit_cast, the compiler checks that the cast is safe.
-// Such explicit implicit_casts are necessary in surprisingly many
-// situations where C++ demands an exact type match instead of an
-// argument type convertable to a target type.
-//
-// The From type can be inferred, so the preferred syntax for using
-// implicit_cast is the same as for static_cast etc.:
-//
-// implicit_cast<ToType>(expr)
-//
-// implicit_cast would have been part of the C++ standard library,
-// but the proposal was submitted too late. It will probably make
-// its way into the language in the future.
-template<typename To, typename From>
-inline To implicit_cast(From const &f) {
- return f;
-}
-
-// When you upcast (that is, cast a pointer from type Foo to type
-// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
-// always succeed. When you downcast (that is, cast a pointer from
-// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
-// how do you know the pointer is really of type SubclassOfFoo? It
-// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
-// when you downcast, you should use this macro. In debug mode, we
-// use dynamic_cast<> to double-check the downcast is legal (we die
-// if it's not). In normal mode, we do the efficient static_cast<>
-// instead. Thus, it's important to test in debug mode to make sure
-// the cast is legal!
-// This is the only place in the code we should use dynamic_cast<>.
-// In particular, you SHOULDN'T be using dynamic_cast<> in order to
-// do RTTI (eg code like this:
-// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
-// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
-// You should design the code some other way not to need this.
-
-template<typename To, typename From> // use like this: down_cast<T*>(foo);
-inline To down_cast(From* f) { // so we only accept pointers
- // Ensures that To is a sub-type of From *. This test is here only
- // for compile-time type checking, and has no overhead in an
- // optimized build at run-time, as it will be optimized away
- // completely.
- if (false) {
- implicit_cast<From*, To>(0);
- }
-
-#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI)
- assert(f == NULL || dynamic_cast<To>(f) != NULL); // RTTI: debug mode only!
-#endif
- return static_cast<To>(f);
-}
-
-} // namespace internal
-
-// We made these internal so that they would show up as such in the docs,
-// but we don't want to stick "internal::" in front of them everywhere.
-using internal::implicit_cast;
-using internal::down_cast;
-
// The COMPILE_ASSERT macro can be used to verify that a compile time
// expression is true. For example, you could use it to verify the
// size of a static array:
@@ -657,6 +658,7 @@ class LIBPROTOBUF_EXPORT LogMessage {
LogMessage& operator<<(long value);
LogMessage& operator<<(unsigned long value);
LogMessage& operator<<(double value);
+ LogMessage& operator<<(void* value);
private:
friend class LogFinisher;
@@ -731,7 +733,8 @@ T* CheckNotNull(const char* /* file */, int /* line */,
}
} // namespace internal
#define GOOGLE_CHECK_NOTNULL(A) \
- internal::CheckNotNull(__FILE__, __LINE__, "'" #A "' must not be NULL", (A))
+ ::google::protobuf::internal::CheckNotNull(\
+ __FILE__, __LINE__, "'" #A "' must not be NULL", (A))
#ifdef NDEBUG
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
index cb892072..7eb4e317 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -31,6 +31,7 @@
// Author: kenton@google.com (Kenton Varda)
#include <vector>
+#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
diff --git a/src/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h
new file mode 100644
index 00000000..e553f142
--- /dev/null
+++ b/src/google/protobuf/stubs/fastmem.h
@@ -0,0 +1,153 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Fast memory copying and comparison routines.
+// strings::fastmemcmp_inlined() replaces memcmp()
+// strings::memcpy_inlined() replaces memcpy()
+// strings::memeq(a, b, n) replaces memcmp(a, b, n) == 0
+//
+// strings::*_inlined() routines are inline versions of the
+// routines exported by this module. Sometimes using the inlined
+// versions is faster. Measure before using the inlined versions.
+//
+// Performance measurement:
+// strings::fastmemcmp_inlined
+// Analysis: memcmp, fastmemcmp_inlined, fastmemcmp
+// 2012-01-30
+
+#ifndef GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
+#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Return true if the n bytes at a equal the n bytes at b.
+// The regions are allowed to overlap.
+//
+// The performance is similar to the performance memcmp(), but faster for
+// moderately-sized inputs, or inputs that share a common prefix and differ
+// somewhere in their last 8 bytes. Further optimizations can be added later
+// if it makes sense to do so.:w
+inline bool memeq(const char* a, const char* b, size_t n) {
+ size_t n_rounded_down = n & ~static_cast<size_t>(7);
+ if (GOOGLE_PREDICT_FALSE(n_rounded_down == 0)) { // n <= 7
+ return memcmp(a, b, n) == 0;
+ }
+ // n >= 8
+ uint64 u = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
+ uint64 v = GOOGLE_UNALIGNED_LOAD64(a + n - 8) ^ GOOGLE_UNALIGNED_LOAD64(b + n - 8);
+ if ((u | v) != 0) { // The first or last 8 bytes differ.
+ return false;
+ }
+ a += 8;
+ b += 8;
+ n = n_rounded_down - 8;
+ if (n > 128) {
+ // As of 2012, memcmp on x86-64 uses a big unrolled loop with SSE2
+ // instructions, and while we could try to do something faster, it
+ // doesn't seem worth pursuing.
+ return memcmp(a, b, n) == 0;
+ }
+ for (; n >= 16; n -= 16) {
+ uint64 x = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b);
+ uint64 y = GOOGLE_UNALIGNED_LOAD64(a + 8) ^ GOOGLE_UNALIGNED_LOAD64(b + 8);
+ if ((x | y) != 0) {
+ return false;
+ }
+ a += 16;
+ b += 16;
+ }
+ // n must be 0 or 8 now because it was a multiple of 8 at the top of the loop.
+ return n == 0 || GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b);
+}
+
+inline int fastmemcmp_inlined(const char *a, const char *b, size_t n) {
+ if (n >= 64) {
+ return memcmp(a, b, n);
+ }
+ const char* a_limit = a + n;
+ while (a + sizeof(uint64) <= a_limit &&
+ GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b)) {
+ a += sizeof(uint64);
+ b += sizeof(uint64);
+ }
+ if (a + sizeof(uint32) <= a_limit &&
+ GOOGLE_UNALIGNED_LOAD32(a) == GOOGLE_UNALIGNED_LOAD32(b)) {
+ a += sizeof(uint32);
+ b += sizeof(uint32);
+ }
+ while (a < a_limit) {
+ int d = static_cast<uint32>(*a++) - static_cast<uint32>(*b++);
+ if (d) return d;
+ }
+ return 0;
+}
+
+// The standard memcpy operation is slow for variable small sizes.
+// This implementation inlines the optimal realization for sizes 1 to 16.
+// To avoid code bloat don't use it in case of not performance-critical spots,
+// nor when you don't expect very frequent values of size <= 16.
+inline void memcpy_inlined(char *dst, const char *src, size_t size) {
+ // Compiler inlines code with minimal amount of data movement when third
+ // parameter of memcpy is a constant.
+ switch (size) {
+ case 1: memcpy(dst, src, 1); break;
+ case 2: memcpy(dst, src, 2); break;
+ case 3: memcpy(dst, src, 3); break;
+ case 4: memcpy(dst, src, 4); break;
+ case 5: memcpy(dst, src, 5); break;
+ case 6: memcpy(dst, src, 6); break;
+ case 7: memcpy(dst, src, 7); break;
+ case 8: memcpy(dst, src, 8); break;
+ case 9: memcpy(dst, src, 9); break;
+ case 10: memcpy(dst, src, 10); break;
+ case 11: memcpy(dst, src, 11); break;
+ case 12: memcpy(dst, src, 12); break;
+ case 13: memcpy(dst, src, 13); break;
+ case 14: memcpy(dst, src, 14); break;
+ case 15: memcpy(dst, src, 15); break;
+ case 16: memcpy(dst, src, 16); break;
+ default: memcpy(dst, src, size); break;
+ }
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
diff --git a/src/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h
new file mode 100644
index 00000000..e123e4fe
--- /dev/null
+++ b/src/google/protobuf/stubs/singleton.h
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifndef GOOGLE_PROTOBUF_STUBS_SINGLETON_H__
+#define GOOGLE_PROTOBUF_STUBS_SINGLETON_H__
+
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/once.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+template<typename T>
+class Singleton {
+ public:
+ static T* get() {
+ GoogleOnceInit(&once_, &Singleton<T>::Init);
+ return instance_;
+ }
+ private:
+ static void Init() {
+ instance_ = new T();
+ }
+ static ProtobufOnceType once_;
+ static T* instance_;
+};
+
+template<typename T>
+ProtobufOnceType Singleton<T>::once_;
+
+template<typename T>
+T* Singleton<T>::instance_;
+} // namespace internal
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_STUBS_SINGLETON_H__
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index a8982593..86d45685 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -94,6 +94,34 @@ void StripString(string* s, const char* remove, char replacewith) {
}
}
+void StripWhitespace(string* str) {
+ int str_length = str->length();
+
+ // Strip off leading whitespace.
+ int first = 0;
+ while (first < str_length && ascii_isspace(str->at(first))) {
+ ++first;
+ }
+ // If entire string is white space.
+ if (first == str_length) {
+ str->clear();
+ return;
+ }
+ if (first > 0) {
+ str->erase(0, first);
+ str_length -= first;
+ }
+
+ // Strip off trailing whitespace.
+ int last = str_length - 1;
+ while (last >= 0 && ascii_isspace(str->at(last))) {
+ --last;
+ }
+ if (last != (str_length - 1) && last >= 0) {
+ str->erase(last + 1, string::npos);
+ }
+}
+
// ----------------------------------------------------------------------
// StringReplace()
// Replace the "old" pattern with the "new" pattern in a string,
@@ -1275,5 +1303,33 @@ string ToHex(uint64 num) {
return string(bufptr, buf + 16 - bufptr);
}
+int GlobalReplaceSubstring(const string& substring,
+ const string& replacement,
+ string* s) {
+ GOOGLE_CHECK(s != NULL);
+ if (s->empty() || substring.empty())
+ return 0;
+ string tmp;
+ int num_replacements = 0;
+ int pos = 0;
+ for (int match_pos = s->find(substring.data(), pos, substring.length());
+ match_pos != string::npos;
+ pos = match_pos + substring.length(),
+ match_pos = s->find(substring.data(), pos, substring.length())) {
+ ++num_replacements;
+ // Append the original content before the match.
+ tmp.append(*s, pos, match_pos - pos);
+ // Append the replacement for the match.
+ tmp.append(replacement.begin(), replacement.end());
+ }
+ // Append the content after the last match. If no replacements were made, the
+ // original string is left untouched.
+ if (num_replacements > 0) {
+ tmp.append(*s, pos, s->length() - pos);
+ s->swap(tmp);
+ }
+ return num_replacements;
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 4178ac9f..f2e1a944 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -57,6 +57,8 @@ namespace protobuf {
// strings, so locale should not be taken into account.
// ascii_isdigit()
// Like above, but only accepts digits.
+// ascii_isspace()
+// Check if the character is a space character.
// ----------------------------------------------------------------------
inline bool ascii_isalnum(char c) {
@@ -69,6 +71,10 @@ inline bool ascii_isdigit(char c) {
return ('0' <= c && c <= '9');
}
+inline bool ascii_isspace(char c) {
+ return c == ' ';
+}
+
// ----------------------------------------------------------------------
// HasPrefixString()
// Check if a string begins with a given prefix.
@@ -119,10 +125,15 @@ inline string StripSuffixString(const string& str, const string& suffix) {
// in 'remove') with the character 'replacewith'.
// Good for keeping html characters or protocol characters (\t) out
// of places where they might cause a problem.
+// StripWhitespace
+// Removes whitespaces from both ends of the given string.
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove,
char replacewith);
+LIBPROTOBUF_EXPORT void StripWhitespace(string* s);
+
+
// ----------------------------------------------------------------------
// LowerString()
// UpperString()
@@ -501,6 +512,16 @@ inline string ToString(string a) {
// StrCat()
// These methods join some strings together.
// ----------------------------------------------------------------------
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+string StrCat(
+ const T1& a, const T2& b, const T3& c, const T4& d, const T5& e,
+ const T6& f, const T7& g) {
+ return internal::ToString(a) + internal::ToString(b) +
+ internal::ToString(c) + internal::ToString(d) + internal::ToString(e) +
+ internal::ToString(f) + internal::ToString(g);
+}
+
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) {
@@ -556,6 +577,17 @@ string Join(const Range& components,
// ----------------------------------------------------------------------
LIBPROTOBUF_EXPORT string ToHex(uint64 num);
+// ----------------------------------------------------------------------
+// GlobalReplaceSubstring()
+// Replaces all instances of a substring in a string. Does nothing
+// if 'substring' is empty. Returns the number of replacements.
+//
+// NOTE: The string pieces must not overlap s.
+// ----------------------------------------------------------------------
+LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring,
+ const string& replacement,
+ string* s);
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h
index e41f5e6f..f5365c38 100644
--- a/src/google/protobuf/stubs/type_traits.h
+++ b/src/google/protobuf/stubs/type_traits.h
@@ -35,6 +35,7 @@
// any changes here, make sure that you're not breaking any platforms.
//
// Define a small subset of tr1 type traits. The traits we define are:
+// enable_if
// is_integral
// is_floating_point
// is_pointer
@@ -60,12 +61,27 @@
#include <utility> // For pair
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/template_util.h> // For true_type and false_type
namespace google {
namespace protobuf {
namespace internal {
+template<typename B, typename D>
+struct is_base_of {
+ typedef char (&yes)[1];
+ typedef char (&no)[2];
+
+ static yes check(const B*);
+ static no check(const void*);
+
+ enum {
+ value = sizeof(check(static_cast<const D*>(NULL))) == sizeof(yes),
+ };
+};
+
+template <bool cond, class T = void> struct enable_if;
template <class T> struct is_integral;
template <class T> struct is_floating_point;
template <class T> struct is_pointer;
@@ -91,6 +107,13 @@ template <class T, class U> struct is_same;
template <class From, class To> struct is_convertible;
#endif
+// enable_if, equivalent semantics to c++11 std::enable_if, specifically:
+// "If B is true, the member typedef type shall equal T; otherwise, there
+// shall be no member typedef type."
+// Specified by 20.9.7.6 [Other transformations]
+
+template<bool cond, class T> struct enable_if { typedef T type; };
+template<class T> struct enable_if<false, T> {};
// is_integral is false except for the built-in integer types. A
// cv-qualified type is integral if and only if the underlying type is.
template <class T> struct is_integral : false_type { };
@@ -144,7 +167,7 @@ template <class T> struct is_pointer<const volatile T> : is_pointer<T> { };
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
-namespace internal {
+namespace type_traits_internal {
template <class T> struct is_class_or_union {
template <class U> static small_ tester(void (U::*)());
@@ -159,7 +182,7 @@ template <bool NotUnum, class T> struct is_enum_impl
template <class T> struct is_enum_impl<true, T> : false_type { };
-} // namespace internal
+} // namespace type_traits_internal
// Specified by TR1 [4.5.1] primary type categories.
@@ -177,12 +200,12 @@ template <class T> struct is_enum_impl<true, T> : false_type { };
// because it can't be used with some types (e.g. void or classes with
// inaccessible conversion operators).
template <class T> struct is_enum
- : internal::is_enum_impl<
+ : type_traits_internal::is_enum_impl<
is_same<T, void>::value ||
is_integral<T>::value ||
is_floating_point<T>::value ||
is_reference<T>::value ||
- internal::is_class_or_union<T>::value,
+ type_traits_internal::is_class_or_union<T>::value,
T> { };
template <class T> struct is_enum<const T> : is_enum<T> { };
@@ -300,7 +323,7 @@ template<typename T> struct is_same<T, T> : public true_type { };
// Specified by TR1 [4.6] Relationships between types
#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
-namespace internal {
+namespace type_traits_internal {
// This class is an implementation detail for is_convertible, and you
// don't need to know how it works to use is_convertible. For those
@@ -317,14 +340,14 @@ struct ConvertHelper {
static big_ Test(...);
static From Create();
};
-} // namespace internal
+} // namespace type_traits_internal
// Inherits from true_type if From is convertible to To, false_type otherwise.
template <typename From, typename To>
struct is_convertible
: integral_constant<bool,
- sizeof(internal::ConvertHelper<From, To>::Test(
- internal::ConvertHelper<From, To>::Create()))
+ sizeof(type_traits_internal::ConvertHelper<From, To>::Test(
+ type_traits_internal::ConvertHelper<From, To>::Create()))
== sizeof(small_)> {
};
#endif
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 84cdbb57..fd04bef1 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -50,6 +50,7 @@
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -1583,10 +1584,23 @@ void TextFormat::Printer::PrintFieldValue(
}
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()));
+ int enum_value = field->is_repeated()
+ ? reflection->GetRepeatedEnumValue(message, field, index)
+ : reflection->GetEnumValue(message, field);
+ const EnumValueDescriptor* enum_desc =
+ field->enum_type()->FindValueByNumber(enum_value);
+ if (enum_desc != NULL) {
+ generator.Print(printer->PrintEnum(enum_value, enum_desc->name()));
+ } else {
+ // Ordinarily, enum_desc should not be null, because proto2 has the
+ // invariant that set enum field values must be in-range, but with the
+ // new integer-based API for enums (or the RepeatedField<int> loophole),
+ // it is possible for the user to force an unknown integer value. So we
+ // simply use the integer value itself as the enum value name in this
+ // case.
+ generator.Print(printer->PrintEnum(enum_value,
+ StringPrintf("%d", enum_value)));
+ }
break;
}
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 29549410..548962cb 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -40,6 +40,9 @@
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index c48cc923..7450fe53 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -34,6 +34,7 @@
//
// A proto file we will use for unit testing.
+syntax = "proto2";
// Some generic_services option(s) added automatically.
// See: http://go/proto2-generic-services-default
@@ -429,7 +430,7 @@ message TestMutualRecursionB {
}
// Test that groups have disjoint field numbers from their siblings and
-// parents. This is NOT possible in proto1; only proto2. When attempting
+// parents. This is NOT possible in proto1; only google.protobuf. When attempting
// to compile with proto1, this will emit an error; so we only include it
// in protobuf_unittest_proto.
message TestDupFieldNumber { // NO_PROTO1
@@ -505,6 +506,15 @@ message TestFieldOrderings {
optional int64 my_int = 1;
extensions 12 to 100;
optional float my_float = 101;
+ message NestedMessage {
+ optional int64 oo = 2;
+ // The field name "b" fails to compile in proto1 because it conflicts with
+ // a local variable named "b" in one of the generated methods. Doh.
+ // This file needs to compile in proto1 to test backwards-compatibility.
+ optional int32 bb = 1;
+ }
+
+ optional NestedMessage optional_nested_message = 200;
}
diff --git a/src/google/protobuf/unittest_arena.proto b/src/google/protobuf/unittest_arena.proto
new file mode 100644
index 00000000..6fdbbe02
--- /dev/null
+++ b/src/google/protobuf/unittest_arena.proto
@@ -0,0 +1,45 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+import "google/protobuf/unittest_no_arena_import.proto";
+
+package proto2_arena_unittest;
+
+
+message NestedMessage {
+ optional int32 d = 1;
+}
+
+message ArenaMessage {
+ repeated NestedMessage repeated_nested_message = 1;
+ repeated ImportNoArenaNestedMessage repeated_import_no_arena_message = 2;
+};
diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto
index 0bb12e17..d4d6e869 100644
--- a/src/google/protobuf/unittest_custom_options.proto
+++ b/src/google/protobuf/unittest_custom_options.proto
@@ -32,8 +32,9 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
-// A proto file used to test the "custom options" feature of proto2.
+// A proto file used to test the "custom options" feature of google.protobuf.
+syntax = "proto2";
// Some generic_services option(s) added automatically.
// See: http://go/proto2-generic-services-default
diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto
new file mode 100644
index 00000000..66b31acf
--- /dev/null
+++ b/src/google/protobuf/unittest_drop_unknown_fields.proto
@@ -0,0 +1,55 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package unittest_drop_unknown_fields;
+
+message Foo {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+ optional int32 int32_value = 1;
+ optional NestedEnum enum_value = 2;
+}
+
+message FooWithExtraFields {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+ optional int32 int32_value = 1;
+ optional NestedEnum enum_value = 2;
+ optional int32 extra_int32_value = 3;
+}
diff --git a/src/google/protobuf/unittest_embed_optimize_for.proto b/src/google/protobuf/unittest_embed_optimize_for.proto
index ad515131..d8b0f9b9 100644
--- a/src/google/protobuf/unittest_embed_optimize_for.proto
+++ b/src/google/protobuf/unittest_embed_optimize_for.proto
@@ -34,6 +34,7 @@
//
// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
+syntax = "proto2";
import "google/protobuf/unittest_optimize_for.proto";
package protobuf_unittest;
diff --git a/src/google/protobuf/unittest_empty.proto b/src/google/protobuf/unittest_empty.proto
index b7337ef3..36443e7e 100644
--- a/src/google/protobuf/unittest_empty.proto
+++ b/src/google/protobuf/unittest_empty.proto
@@ -35,3 +35,4 @@
// This file intentionally left blank. (At one point this wouldn't compile
// correctly.)
+syntax = "proto2";
diff --git a/src/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto
index 3ba8b419..2250261d 100644
--- a/src/google/protobuf/unittest_enormous_descriptor.proto
+++ b/src/google/protobuf/unittest_enormous_descriptor.proto
@@ -35,6 +35,7 @@
// A proto file that has an extremely large descriptor. Used to test that
// descriptors over 64k don't break the string literal length limit in Java.
+syntax = "proto2";
package google.protobuf;
option java_package = "com.google.protobuf";
diff --git a/src/google/protobuf/unittest_import.proto b/src/google/protobuf/unittest_import.proto
index 38275dc9..c1289e38 100644
--- a/src/google/protobuf/unittest_import.proto
+++ b/src/google/protobuf/unittest_import.proto
@@ -34,6 +34,7 @@
//
// A proto file which is imported by unittest.proto to test importing.
+syntax = "proto2";
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto
index 7cee113a..a7afa452 100644
--- a/src/google/protobuf/unittest_import_lite.proto
+++ b/src/google/protobuf/unittest_import_lite.proto
@@ -32,6 +32,7 @@
//
// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
+syntax = "proto2";
package protobuf_unittest_import;
option optimize_for = LITE_RUNTIME;
diff --git a/src/google/protobuf/unittest_import_public.proto b/src/google/protobuf/unittest_import_public.proto
index e5929cb5..ffaf7736 100644
--- a/src/google/protobuf/unittest_import_public.proto
+++ b/src/google/protobuf/unittest_import_public.proto
@@ -30,6 +30,7 @@
// Author: liujisi@google.com (Pherl Liu)
+syntax = "proto2";
package protobuf_unittest_import;
diff --git a/src/google/protobuf/unittest_import_public_lite.proto b/src/google/protobuf/unittest_import_public_lite.proto
index e39bdb49..33549c22 100644
--- a/src/google/protobuf/unittest_import_public_lite.proto
+++ b/src/google/protobuf/unittest_import_public_lite.proto
@@ -30,6 +30,7 @@
// Author: liujisi@google.com (Pherl Liu)
+syntax = "proto2";
package protobuf_unittest_import;
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index 30dd67fb..662c0e46 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -32,6 +32,7 @@
//
// This is like unittest.proto but with optimize_for = LITE_RUNTIME.
+syntax = "proto2";
package protobuf_unittest;
import "google/protobuf/unittest_import_lite.proto";
diff --git a/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/google/protobuf/unittest_lite_imports_nonlite.proto
index 5ef8a06d..132d6a82 100644
--- a/src/google/protobuf/unittest_lite_imports_nonlite.proto
+++ b/src/google/protobuf/unittest_lite_imports_nonlite.proto
@@ -32,6 +32,7 @@
//
// Tests that a "lite" message can import a regular message.
+syntax = "proto2";
package protobuf_unittest;
import "google/protobuf/unittest.proto";
diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto
index 8fbe7abb..5a07ed12 100644
--- a/src/google/protobuf/unittest_mset.proto
+++ b/src/google/protobuf/unittest_mset.proto
@@ -34,6 +34,7 @@
//
// This file contains messages for testing message_set_wire_format.
+syntax = "proto2";
package protobuf_unittest;
option optimize_for = SPEED;
diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto
new file mode 100644
index 00000000..cd7cbbae
--- /dev/null
+++ b/src/google/protobuf/unittest_no_arena.proto
@@ -0,0 +1,199 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This proto file contains copies of TestAllTypes and friends, but with arena
+// support disabled in code generation. It allows us to test the performance
+// impact against baseline (non-arena) google.protobuf.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option cc_generic_services = true; // auto-added
+option java_generic_services = true; // auto-added
+option py_generic_services = true; // auto-added
+
+import "google/protobuf/unittest_import.proto";
+import "google/protobuf/unittest_arena.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest_no_arena;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+option java_outer_classname = "UnittestProto";
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+ message NestedMessage {
+ // The field name "b" fails to compile in proto1 because it conflicts with
+ // a local variable named "b" in one of the generated methods. Doh.
+ // This file needs to compile in proto1 to test backwards-compatibility.
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ NEG = -1; // Intentionally negative.
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessage optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessage optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnum optional_foreign_enum = 22;
+ optional protobuf_unittest_import.ImportEnum optional_import_enum = 23;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+ repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32 = 61 [default = 41 ];
+ optional int64 default_int64 = 62 [default = 42 ];
+ optional uint32 default_uint32 = 63 [default = 43 ];
+ optional uint64 default_uint64 = 64 [default = 44 ];
+ optional sint32 default_sint32 = 65 [default = -45 ];
+ optional sint64 default_sint64 = 66 [default = 46 ];
+ optional fixed32 default_fixed32 = 67 [default = 47 ];
+ optional fixed64 default_fixed64 = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32 = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64 = 70 [default = -50 ];
+ optional float default_float = 71 [default = 51.5 ];
+ optional double default_double = 72 [default = 52e3 ];
+ optional bool default_bool = 73 [default = true ];
+ optional string default_string = 74 [default = "hello"];
+ optional bytes default_bytes = 75 [default = "world"];
+
+ optional NestedEnum default_nested_enum = 81 [default = BAR ];
+ optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
+ optional protobuf_unittest_import.ImportEnum
+ default_import_enum = 83 [default = IMPORT_BAR];
+
+ 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;
+ }
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ optional int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+message TestNoArenaMessage {
+ optional proto2_arena_unittest.ArenaMessage arena_message = 1;
+};
diff --git a/src/google/protobuf/unittest_no_arena_import.proto b/src/google/protobuf/unittest_no_arena_import.proto
new file mode 100644
index 00000000..072af49e
--- /dev/null
+++ b/src/google/protobuf/unittest_no_arena_import.proto
@@ -0,0 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package proto2_arena_unittest;
+
+message ImportNoArenaNestedMessage {
+ optional int32 d = 1;
+};
diff --git a/src/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto
new file mode 100644
index 00000000..e04da0ac
--- /dev/null
+++ b/src/google/protobuf/unittest_no_field_presence.proto
@@ -0,0 +1,138 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// A proto file used to test a message type with no explicit field presence.
+
+syntax = "proto3";
+
+// We want to test embedded proto2 messages, so include some proto2 types.
+import "google/protobuf/unittest.proto";
+
+package proto2_nofieldpresence_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+ message NestedMessage {
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+
+ // Singular
+ // TODO: remove 'optional' labels as soon as CL 69188077 is LGTM'd to make
+ // 'optional' optional.
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessage optional_foreign_message = 19;
+ optional protobuf_unittest.TestAllTypes optional_proto2_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnum optional_foreign_enum = 22;
+ // N.B.: proto2-enum-type fields not allowed, because their default values
+ // might not be zero.
+ //optional protobuf_unittest.ForeignEnum optional_proto2_enum = 23;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ optional NestedMessage optional_lazy_message = 30 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated protobuf_unittest.TestAllTypes repeated_proto2_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ NestedMessage oneof_nested_message = 112;
+ string oneof_string = 113;
+ NestedEnum oneof_enum = 114;
+ }
+}
+
+message TestProto2Required {
+ optional protobuf_unittest.TestRequired proto2 = 1;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ optional int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_FOO = 0;
+ FOREIGN_BAR = 1;
+ FOREIGN_BAZ = 2;
+}
diff --git a/src/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto
index cf6d16c2..8fc7713c 100644
--- a/src/google/protobuf/unittest_no_generic_services.proto
+++ b/src/google/protobuf/unittest_no_generic_services.proto
@@ -30,6 +30,7 @@
// Author: kenton@google.com (Kenton Varda)
+syntax = "proto2";
package google.protobuf.no_generic_services_test;
diff --git a/src/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto
index 9f7b4eea..ee9cc7bd 100644
--- a/src/google/protobuf/unittest_optimize_for.proto
+++ b/src/google/protobuf/unittest_optimize_for.proto
@@ -34,6 +34,7 @@
//
// A proto file which uses optimize_for = CODE_SIZE.
+syntax = "proto2";
import "google/protobuf/unittest.proto";
package protobuf_unittest;
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
new file mode 100644
index 00000000..ba050d70
--- /dev/null
+++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -0,0 +1,66 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package proto2_preserve_unknown_enum_unittest;
+
+enum MyEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+}
+
+enum MyEnumPlusExtra {
+ E_FOO = 0;
+ E_BAR = 1;
+ E_BAZ = 2;
+ E_EXTRA = 3;
+}
+
+message MyMessage {
+ optional MyEnum e = 1;
+ repeated MyEnum repeated_e = 2;
+ repeated MyEnum repeated_packed_e = 3 [packed=true];
+ oneof o {
+ MyEnum oneof_e_1 = 4;
+ MyEnum oneof_e_2 = 5;
+ }
+}
+
+message MyMessagePlusExtra {
+ optional MyEnumPlusExtra e = 1;
+ repeated MyEnumPlusExtra repeated_e = 2;
+ repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true];
+ oneof o {
+ MyEnumPlusExtra oneof_e_1 = 4;
+ MyEnumPlusExtra oneof_e_2 = 5;
+ }
+}
diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
new file mode 100644
index 00000000..84ec7960
--- /dev/null
+++ b/src/google/protobuf/unittest_proto3_arena.proto
@@ -0,0 +1,143 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+
+import "google/protobuf/unittest_import.proto";
+
+package proto3_arena_unittest;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+ message NestedMessage {
+ // The field name "b" fails to compile in proto1 because it conflicts with
+ // a local variable named "b" in one of the generated methods. Doh.
+ // This file needs to compile in proto1 to test backwards-compatibility.
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ NEG = -1; // Intentionally negative.
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessage optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessage optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnum optional_foreign_enum = 22;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ NestedMessage oneof_nested_message = 112;
+ string oneof_string = 113;
+ bytes oneof_bytes = 114;
+ }
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ optional int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_FOO = 0;
+ FOREIGN_BAR = 1;
+ FOREIGN_BAZ = 2;
+}
diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h
new file mode 100644
index 00000000..fb5380aa
--- /dev/null
+++ b/src/google/protobuf/unknown_enum_impl.h
@@ -0,0 +1,132 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_UTIL_UNKNOWN_ENUM_IMPL_H__
+#define GOOGLE_PROTOBUF_UTIL_UNKNOWN_ENUM_IMPL_H__
+
+#include <stdlib.h>
+
+#include <google/protobuf/stubs/common.h>
+#include "net/proto/tagmapper.h"
+#include <google/protobuf/bridge/compatibility_mode_support.h>
+
+namespace google {
+namespace protobuf {
+
+// google/protobuf/message.h
+class Message;
+
+namespace util {
+
+// NOTE: You should not call these functions directly. Instead use either
+// HAS_UNKNOWN_ENUM() or GET_UNKNOWN_ENUM(), defined in the public header.
+// The macro-versions operate in a type-safe manner and behave appropriately
+// for the proto version of the message, whereas these versions assume a
+// specific proto version and allow the caller to pass in any arbitrary integer
+// value as a field number.
+//
+// Returns whether the message has unrecognized the enum value for a given
+// field. It also stores the value into the unknown_value parameter if the
+// function returns true and the pointer is not NULL.
+//
+// In proto2, invalid enum values will be treated as unknown fields. This
+// function checks that case.
+bool HasUnknownEnum(const Message& message, int32 field_number,
+ int32* unknown_value = nullptr);
+// Same as above, but returns all unknown enums.
+bool GetRepeatedEnumUnknowns(const Message& message, int32 field_number,
+ vector<int32>* unknown_values = nullptr);
+// In proto1, invalue enum values are stored in the same way as valid enum
+// values.
+// TODO(karner): Delete this once the migration to proto2 is complete.
+bool HasUnknownEnumProto1(const Message& message, int32 field_number,
+ int32* unknown_value);
+// Same as above, but returns all unknown enums.
+bool GetRepeatedEnumUnknownsProto1(const Message& message, int32 field_number,
+ vector<int32>* unknown_values);
+// Invokes the appropriate version based on whether the message is proto1
+// or proto2.
+template <typename T>
+bool HasUnknownEnum_Template(const T& message, int32 field_number,
+ int32* unknown_value = nullptr) {
+ if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
+ !internal::is_base_of<ProtocolMessage, T>::value) {
+ return HasUnknownEnum(message, field_number, unknown_value);
+ } else {
+ return HasUnknownEnumProto1(message, field_number, unknown_value);
+ }
+}
+// Invokes the appropriate version based on whether the message is proto1
+// or proto2.
+template <typename T>
+bool GetRepeatedEnumUnknowns_Template(
+ const T& message, int32 field_number,
+ vector<int32>* unknown_values = nullptr) {
+ if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
+ !internal::is_base_of<ProtocolMessage, T>::value) {
+ return GetRepeatedEnumUnknowns(message, field_number, unknown_values);
+ } else {
+ return GetRepeatedEnumUnknownsProto1(message, field_number,
+ unknown_values);
+ }
+}
+
+// NOTE: You should not call these functions directly. Instead use
+// SET_UNKNOWN_ENUM(), defined in the public header. The macro-versions
+// operate in a type-safe manner and behave appropriately for the proto
+// version of the message, whereas these versions assume a specific proto
+// version and allow the caller to pass in any arbitrary integer value as a
+// field number.
+//
+// Sets the given value in the unknown fields of the message.
+void SetUnknownEnum(Message* message, int32 field_number, int32 unknown_value);
+// In proto1, invalue enum values are stored in the same way as valid enum
+// values.
+// TODO(karner): Delete this once the migration to proto2 is complete.
+void SetUnknownEnumProto1(Message* message, int32 field_number,
+ int32 unknown_value);
+// Invokes the appropriate version based on whether the message is proto1
+// or proto2.
+template <typename T>
+void SetUnknownEnum_Template(T* message, int32 field_number,
+ int32 unknown_value) {
+ if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
+ !internal::is_base_of<ProtocolMessage, T>::value) {
+ SetUnknownEnum(message, field_number, unknown_value);
+ } else {
+ SetUnknownEnumProto1(message, field_number, unknown_value);
+ }
+}
+
+} // namespace util
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_UTIL_UNKNOWN_ENUM_IMPL_H__
diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto
new file mode 100644
index 00000000..caafadcd
--- /dev/null
+++ b/src/google/protobuf/unknown_enum_test.proto
@@ -0,0 +1,61 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Definitions of protos for testing cross-version compatibility. The
+// UpRevision message acts as if it were a newer version of the DownRevision
+// message. That is, UpRevision shares all the same fields as DownRevision,
+// but UpRevision can add fields and add enum values.
+syntax = "proto2";
+
+package google.protobuf.util;
+
+
+message DownRevision {
+ enum Enum {
+ DEFAULT_VALUE = 2;
+ NONDEFAULT_VALUE = 3;
+ }
+
+ optional Enum value = 1 [default = DEFAULT_VALUE];
+ repeated Enum values = 2;
+}
+
+message UpRevision {
+ enum Enum {
+ DEFAULT_VALUE = 2;
+ NONDEFAULT_VALUE = 3;
+ NEW_VALUE = 4;
+ NEW_VALUE_2 = 5;
+ NEW_VALUE_3 = 6;
+ }
+
+ optional Enum value = 1 [default = DEFAULT_VALUE];
+ repeated Enum values = 2;
+}
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 020a323b..e15280c8 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -44,6 +44,25 @@
namespace google {
namespace protobuf {
+namespace {
+// This global instance is returned by unknown_fields() on any message class
+// when the object has no unknown fields. This is necessary because we now
+// instantiate the UnknownFieldSet dynamically only when required.
+UnknownFieldSet* default_unknown_field_set_instance_ = NULL;
+
+void InitDefaultUnknownFieldSet() {
+ default_unknown_field_set_instance_ = new UnknownFieldSet();
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(default_unknown_field_set_once_init_);
+}
+
+const UnknownFieldSet* UnknownFieldSet::default_instance() {
+ ::google::protobuf::GoogleOnceInit(&default_unknown_field_set_once_init_,
+ &InitDefaultUnknownFieldSet);
+ return default_unknown_field_set_instance_;
+}
+
UnknownFieldSet::UnknownFieldSet()
: fields_(NULL) {}
@@ -53,31 +72,63 @@ UnknownFieldSet::~UnknownFieldSet() {
}
void UnknownFieldSet::ClearFallback() {
- GOOGLE_DCHECK(fields_ != NULL);
- for (int i = 0; i < fields_->size(); i++) {
- (*fields_)[i].Delete();
+ if (fields_ != NULL) {
+ for (int i = 0; i < fields_->size(); i++) {
+ (*fields_)[i].Delete();
+ }
+ delete fields_;
+ fields_ = NULL;
}
- fields_->clear();
}
void UnknownFieldSet::ClearAndFreeMemory() {
if (fields_ != NULL) {
Clear();
- delete fields_;
- fields_ = NULL;
+ }
+}
+
+void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
+ int other_field_count = other.field_count();
+ if (other_field_count > 0) {
+ fields_ = new vector<UnknownField>();
+ for (int i = 0; i < other_field_count; i++) {
+ fields_->push_back((*other.fields_)[i]);
+ fields_->back().DeepCopy();
+ }
}
}
void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
- for (int i = 0; i < other.field_count(); i++) {
- AddField(other.field(i));
+ int other_field_count = other.field_count();
+ if (other_field_count > 0) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
+ for (int i = 0; i < other_field_count; i++) {
+ fields_->push_back((*other.fields_)[i]);
+ fields_->back().DeepCopy();
+ }
}
}
+// A specialized MergeFrom for performance when we are merging from an UFS that
+// is temporary and can be destroyed in the process.
+void UnknownFieldSet::MergeFromAndDestroy(UnknownFieldSet* other) {
+ int other_field_count = other->field_count();
+ if (other_field_count > 0) {
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
+ for (int i = 0; i < other_field_count; i++) {
+ fields_->push_back((*other->fields_)[i]);
+ (*other->fields_)[i].Reset();
+ }
+ }
+ delete other->fields_;
+ other->fields_ = NULL;
+}
+
int UnknownFieldSet::SpaceUsedExcludingSelf() const {
if (fields_ == NULL) return 0;
int total_size = sizeof(*fields_) + sizeof(UnknownField) * fields_->size();
+
for (int i = 0; i < fields_->size(); i++) {
const UnknownField& field = (*fields_)[i];
switch (field.type()) {
@@ -101,61 +152,60 @@ int UnknownFieldSet::SpaceUsed() const {
}
void UnknownFieldSet::AddVarint(int number, uint64 value) {
- if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
field.SetType(UnknownField::TYPE_VARINT);
field.varint_ = value;
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
}
void UnknownFieldSet::AddFixed32(int number, uint32 value) {
- if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
field.SetType(UnknownField::TYPE_FIXED32);
field.fixed32_ = value;
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
}
void UnknownFieldSet::AddFixed64(int number, uint64 value) {
- if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
field.SetType(UnknownField::TYPE_FIXED64);
field.fixed64_ = value;
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
}
string* UnknownFieldSet::AddLengthDelimited(int number) {
- if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
field.SetType(UnknownField::TYPE_LENGTH_DELIMITED);
field.length_delimited_.string_value_ = new string;
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
return field.length_delimited_.string_value_;
}
UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
- if (fields_ == NULL) fields_ = new vector<UnknownField>;
UnknownField field;
field.number_ = number;
field.SetType(UnknownField::TYPE_GROUP);
field.group_ = new UnknownFieldSet;
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
return field.group_;
}
void UnknownFieldSet::AddField(const UnknownField& field) {
- if (fields_ == NULL) fields_ = new vector<UnknownField>;
+ if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
fields_->back().DeepCopy();
}
void UnknownFieldSet::DeleteSubrange(int start, int num) {
- GOOGLE_DCHECK(fields_ != NULL);
// Delete the specified fields.
for (int i = 0; i < num; ++i) {
(*fields_)[i + start].Delete();
@@ -168,6 +218,11 @@ void UnknownFieldSet::DeleteSubrange(int start, int num) {
for (int i = 0; i < num; ++i) {
fields_->pop_back();
}
+ if (fields_ && fields_->size() == 0) {
+ // maintain invariant: never hold fields_ if empty.
+ delete fields_;
+ fields_ = NULL;
+ }
}
void UnknownFieldSet::DeleteByNumber(int number) {
@@ -185,13 +240,18 @@ void UnknownFieldSet::DeleteByNumber(int number) {
}
}
fields_->resize(left);
+ if (left == 0) {
+ // maintain invariant: never hold fields_ if empty.
+ delete fields_;
+ fields_ = NULL;
+ }
}
bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) {
UnknownFieldSet other;
if (internal::WireFormat::SkipMessage(input, &other) &&
input->ConsumedEntireMessage()) {
- MergeFrom(other);
+ MergeFromAndDestroy(&other);
return true;
} else {
return false;
@@ -227,6 +287,22 @@ void UnknownField::Delete() {
}
}
+// Reset all owned ptrs, a special function for performance, to avoid double
+// owning the ptrs, when we merge from a temporary UnknownFieldSet objects.
+void UnknownField::Reset() {
+ switch (type()) {
+ case UnknownField::TYPE_LENGTH_DELIMITED:
+ length_delimited_.string_value_ = NULL;
+ break;
+ case UnknownField::TYPE_GROUP: {
+ group_ = NULL;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
void UnknownField::DeepCopy() {
switch (type()) {
case UnknownField::TYPE_LENGTH_DELIMITED:
@@ -234,8 +310,8 @@ void UnknownField::DeepCopy() {
*length_delimited_.string_value_);
break;
case UnknownField::TYPE_GROUP: {
- UnknownFieldSet* group = new UnknownFieldSet;
- group->MergeFrom(*group_);
+ UnknownFieldSet* group = new UnknownFieldSet();
+ group->InternalMergeFrom(*group_);
group_ = group;
break;
}
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 31f17e2a..6f7a9fdb 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -88,6 +88,9 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
// Merge the contents of some other UnknownFieldSet with this one.
void MergeFrom(const UnknownFieldSet& other);
+ // Similar to above, but this function will destroy the contents of other.
+ void MergeFromAndDestroy(UnknownFieldSet* other);
+
// Swaps the contents of some other UnknownFieldSet with this one.
inline void Swap(UnknownFieldSet* x);
@@ -141,12 +144,22 @@ class LIBPROTOBUF_EXPORT UnknownFieldSet {
return ParseFromArray(data.data(), static_cast<int>(data.size()));
}
+ static const UnknownFieldSet* default_instance();
private:
-
+ // For InternalMergeFrom
+ friend class UnknownField;
+ // Merges from other UnknownFieldSet. This method assumes, that this object
+ // is newly created and has fields_ == NULL;
+ void InternalMergeFrom(const UnknownFieldSet& other);
void ClearFallback();
+ // fields_ is either NULL, or a pointer to a vector that is *non-empty*. We
+ // never hold the empty vector because we want the 'do we have any unknown
+ // fields' check to be fast, and avoid a cache miss: the UFS instance gets
+ // embedded in the message object, so 'fields_ != NULL' tests a member
+ // variable hot in the cache, without the need to go touch a vector somewhere
+ // else in memory.
std::vector<UnknownField>* fields_;
-
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
};
@@ -198,6 +211,10 @@ class LIBPROTOBUF_EXPORT UnknownField {
// If this UnknownField contains a pointer, delete it.
void Delete();
+ // Reset all the underlying pointers to NULL. A special function to be only
+ // used while merging from a temporary UFS.
+ void Reset();
+
// Make a deep copy of any pointers in this UnknownField.
void DeepCopy();
@@ -222,13 +239,14 @@ class LIBPROTOBUF_EXPORT UnknownField {
// inline implementations
inline void UnknownFieldSet::Clear() {
- if (fields_ != NULL) {
+ if (fields_) {
ClearFallback();
}
}
inline bool UnknownFieldSet::empty() const {
- return fields_ == NULL || fields_->empty();
+ // Invariant: fields_ is never empty if present.
+ return !fields_;
}
inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
@@ -236,9 +254,10 @@ inline void UnknownFieldSet::Swap(UnknownFieldSet* x) {
}
inline int UnknownFieldSet::field_count() const {
- return (fields_ == NULL) ? 0 : static_cast<int>(fields_->size());
+ return fields_ ? static_cast<int>(fields_->size()) : 0;
}
inline const UnknownField& UnknownFieldSet::field(int index) const {
+ GOOGLE_DCHECK(fields_ != NULL);
return (*fields_)[index];
}
inline UnknownField* UnknownFieldSet::mutable_field(int index) {
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index aaaa2e89..6bba8fc7 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -482,6 +482,13 @@ TEST_F(UnknownFieldSetTest, UnknownEnumValue) {
}
}
+TEST_F(UnknownFieldSetTest, SpaceUsedExcludingSelf) {
+ UnknownFieldSet empty;
+ empty.AddVarint(1, 0);
+ EXPECT_EQ(/* vector<UnknownField> */ 24 + /* sizeof(UnknownField) */ 16,
+ empty.SpaceUsedExcludingSelf());
+}
+
TEST_F(UnknownFieldSetTest, SpaceUsed) {
unittest::TestEmptyMessage empty_message;
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index 6bdfcd62..f4f02157 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -512,10 +512,15 @@ bool WireFormat::ParseAndMergeField(
int value;
if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
input, &value)) return false;
- const EnumValueDescriptor* enum_value =
- field->enum_type()->FindValueByNumber(value);
- if (enum_value != NULL) {
- message_reflection->AddEnum(message, field, enum_value);
+ if (message->GetDescriptor()->file()->syntax() ==
+ FileDescriptor::SYNTAX_PROTO3) {
+ message_reflection->AddEnumValue(message, field, value);
+ } else {
+ const EnumValueDescriptor* enum_value =
+ field->enum_type()->FindValueByNumber(value);
+ if (enum_value != NULL) {
+ message_reflection->AddEnum(message, field, enum_value);
+ }
}
}
@@ -572,21 +577,31 @@ bool WireFormat::ParseAndMergeField(
int value;
if (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
input, &value)) return false;
- const EnumValueDescriptor* enum_value =
- field->enum_type()->FindValueByNumber(value);
- if (enum_value != NULL) {
+ if (message->GetDescriptor()->file()->syntax() ==
+ FileDescriptor::SYNTAX_PROTO3) {
if (field->is_repeated()) {
- message_reflection->AddEnum(message, field, enum_value);
+ message_reflection->AddEnumValue(message, field, value);
} else {
- message_reflection->SetEnum(message, field, enum_value);
+ message_reflection->SetEnumValue(message, field, value);
}
} else {
- // The enum value is not one of the known values. Add it to the
- // UnknownFieldSet.
- int64 sign_extended_value = static_cast<int64>(value);
- message_reflection->MutableUnknownFields(message)
- ->AddVarint(WireFormatLite::GetTagFieldNumber(tag),
- sign_extended_value);
+ const EnumValueDescriptor* enum_value =
+ field->enum_type()->FindValueByNumber(value);
+ if (enum_value != NULL) {
+ if (field->is_repeated()) {
+ message_reflection->AddEnum(message, field, enum_value);
+ } else {
+ message_reflection->SetEnum(message, field, enum_value);
+ }
+ } else {
+ // The enum value is not one of the known values. Add it to the
+ // UnknownFieldSet.
+ int64 sign_extended_value = static_cast<int64>(value);
+ message_reflection->MutableUnknownFields(message)
+ ->AddVarint(
+ WireFormatLite::GetTagFieldNumber(tag),
+ sign_extended_value);
+ }
}
break;
}
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 8de82784..c80a7050 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -291,7 +291,7 @@ bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
int, WireFormatLite::TYPE_ENUM>(input, &value)) {
return false;
}
- if (is_valid(value)) {
+ if (is_valid == NULL || is_valid(value)) {
values->Add(value);
}
}
@@ -451,19 +451,24 @@ void WireFormatLite::WriteMessageMaybeToArray(int field_number,
}
}
-bool WireFormatLite::ReadString(io::CodedInputStream* input,
- string* value) {
- // String is for UTF-8 text only
+static inline bool ReadBytesToString(io::CodedInputStream* input,
+ string* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+static inline bool ReadBytesToString(io::CodedInputStream* input,
+ string* value) {
uint32 length;
- if (!input->ReadVarint32(&length)) return false;
- if (!input->InternalReadStringInline(value, length)) return false;
- return true;
+ return input->ReadVarint32(&length) &&
+ input->InternalReadStringInline(value, length);
}
-bool WireFormatLite::ReadBytes(io::CodedInputStream* input,
- string* value) {
- uint32 length;
- if (!input->ReadVarint32(&length)) return false;
- return input->InternalReadStringInline(value, length);
+
+bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string* value) {
+ return ReadBytesToString(input, value);
+}
+
+bool WireFormatLite::ReadBytes(io::CodedInputStream* input, string** p) {
+ if (*p == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
+ *p = new ::std::string();
+ }
+ return ReadBytesToString(input, *p);
}
} // namespace internal
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index 21aa4889..acf88ead 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -292,13 +292,22 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
// Read a packed enum field. Values for which is_valid() returns false are
- // dropped.
+ // dropped. If is_valid == NULL, no values are dropped.
static bool ReadPackedEnumNoInline(input,
bool (*is_valid)(int),
RepeatedField<int>* value);
- static bool ReadString(input, string* value);
- static bool ReadBytes (input, string* value);
+ // Read a string. ReadString(..., string* value) requires an existing string.
+ static inline bool ReadString(input, string* value);
+ // ReadString(..., string** p) is internal-only, and should only be called
+ // from generated code. It starts by setting *p to "new string"
+ // if *p == &GetEmptyStringAlreadyInited(). It then invokes
+ // ReadString(input, *p). This is useful for reducing code size.
+ static inline bool ReadString(input, string** p);
+ // Analogous to ReadString().
+ static bool ReadBytes(input, string* value);
+ static bool ReadBytes(input, string** p);
+
static inline bool ReadGroup (field_number, input, MessageLite* value);
static inline bool ReadMessage(input, MessageLite* value);
@@ -654,6 +663,19 @@ inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
return (n >> 1) ^ -static_cast<int64>(n & 1);
}
+// String is for UTF-8 text only, but, even so, ReadString() can simply
+// call ReadBytes().
+
+inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
+ string* value) {
+ return ReadBytes(input, value);
+}
+
+inline bool WireFormatLite::ReadString(io::CodedInputStream* input,
+ string** p) {
+ return ReadBytes(input, p);
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index feb22540..129fc63f 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -47,6 +47,7 @@
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arenastring.h>
namespace google {
@@ -426,6 +427,7 @@ bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input,
}
+
inline bool WireFormatLite::ReadGroup(int field_number,
io::CodedInputStream* input,
MessageLite* value) {
@@ -442,15 +444,12 @@ inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input,
MessageLite* value) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
- if (!input->IncrementRecursionDepth()) return false;
- io::CodedInputStream::Limit limit = input->PushLimit(length);
- if (!value->MergePartialFromCodedStream(input)) return false;
+ std::pair<io::CodedInputStream::Limit, int> p =
+ input->IncrementRecursionDepthAndPushLimit(length);
+ if (p.second < 0 || !value->MergePartialFromCodedStream(input)) return false;
// Make sure that parsing stopped when the limit was hit, not at an endgroup
// tag.
- if (!input->ConsumedEntireMessage()) return false;
- input->PopLimit(limit);
- input->DecrementRecursionDepth();
- return true;
+ return input->DecrementRecursionDepthAndPopLimit(p.first);
}
// We name the template parameter something long and extremely unlikely to occur
@@ -483,17 +482,14 @@ inline bool WireFormatLite::ReadMessageNoVirtual(
io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
uint32 length;
if (!input->ReadVarint32(&length)) return false;
- if (!input->IncrementRecursionDepth()) return false;
- io::CodedInputStream::Limit limit = input->PushLimit(length);
- if (!value->
+ std::pair<io::CodedInputStream::Limit, int> p =
+ input->IncrementRecursionDepthAndPushLimit(length);
+ if (p.second < 0 || !value->
MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
return false;
// Make sure that parsing stopped when the limit was hit, not at an endgroup
// tag.
- if (!input->ConsumedEntireMessage()) return false;
- input->PopLimit(limit);
- input->DecrementRecursionDepth();
- return true;
+ return input->DecrementRecursionDepthAndPopLimit(p.first);
}
// ===================================================================
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index 81a024b3..a3062a6a 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -980,7 +980,8 @@ TEST_F(Utf8ValidationTest, WriteInvalidUTF8String) {
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
ASSERT_EQ(1, errors.size());
EXPECT_TRUE(StartsWith(errors[0],
- "String field 'data' contains invalid UTF-8 data when "
+ "String field 'protobuf_unittest.OneString.data' "
+ "contains invalid UTF-8 data when "
"serializing a protocol buffer. Use the "
"'bytes' type if you intend to send raw bytes."));
#else
@@ -1003,7 +1004,8 @@ TEST_F(Utf8ValidationTest, ReadInvalidUTF8String) {
#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
ASSERT_EQ(1, errors.size());
EXPECT_TRUE(StartsWith(errors[0],
- "String field 'data' contains invalid UTF-8 data when "
+ "String field 'protobuf_unittest.OneString.data' "
+ "contains invalid UTF-8 data when "
"parsing a protocol buffer. Use the "
"'bytes' type if you intend to send raw bytes."));