aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Bo Yang <teboring@google.com>2015-05-21 14:28:59 -0700
committerGravatar Bo Yang <teboring@google.com>2015-05-21 19:32:02 -0700
commit5db217305f37a79eeccd70f000088a06ec82fcec (patch)
treebe53dcf0c0b47ef9178ab8a6fa5c1946ee84a28f
parent56095026ccc2f755a6fdb296e30c3ddec8f556a2 (diff)
down-integrate internal changes
-rw-r--r--.gitignore1
-rw-r--r--Android.mk6
-rw-r--r--Makefile.am14
-rw-r--r--conformance/conformance.proto68
-rw-r--r--conformance/conformance_test.cc1
-rw-r--r--editors/proto.vim2
-rw-r--r--editors/protobuf-mode.el2
-rwxr-xr-xgenerate_descriptor_proto.sh5
-rw-r--r--java/pom.xml15
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessageLite.java16
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractProtobufList.java136
-rw-r--r--java/src/main/java/com/google/protobuf/BooleanArrayList.java244
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java42
-rw-r--r--java/src/main/java/com/google/protobuf/DoubleArrayList.java243
-rw-r--r--java/src/main/java/com/google/protobuf/FloatArrayList.java242
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java396
-rw-r--r--java/src/main/java/com/google/protobuf/IntArrayList.java242
-rw-r--r--java/src/main/java/com/google/protobuf/Internal.java129
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringArrayList.java87
-rw-r--r--java/src/main/java/com/google/protobuf/LongArrayList.java242
-rw-r--r--java/src/main/java/com/google/protobuf/MapField.java63
-rw-r--r--java/src/main/java/com/google/protobuf/MapFieldLite.java376
-rw-r--r--java/src/main/java/com/google/protobuf/MutabilityOracle.java48
-rw-r--r--java/src/main/java/com/google/protobuf/ProtobufArrayList.java95
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java4
-rw-r--r--java/src/test/java/com/google/protobuf/BooleanArrayListTest.java473
-rw-r--r--java/src/test/java/com/google/protobuf/DescriptorsTest.java17
-rw-r--r--java/src/test/java/com/google/protobuf/DoubleArrayListTest.java473
-rw-r--r--java/src/test/java/com/google/protobuf/FloatArrayListTest.java473
-rw-r--r--java/src/test/java/com/google/protobuf/IntArrayListTest.java473
-rw-r--r--java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java188
-rw-r--r--java/src/test/java/com/google/protobuf/LiteTest.java1314
-rw-r--r--java/src/test/java/com/google/protobuf/LiteralByteStringTest.java3
-rw-r--r--java/src/test/java/com/google/protobuf/LongArrayListTest.java473
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java161
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2Test.java148
-rw-r--r--java/src/test/java/com/google/protobuf/MapTest.java133
-rw-r--r--java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java303
-rw-r--r--java/src/test/java/com/google/protobuf/field_presence_test.proto26
-rw-r--r--java/src/test/java/com/google/protobuf/map_initialization_order_test.proto61
-rw-r--r--java/src/test/java/com/google/protobuf/map_test.proto4
-rwxr-xr-xpython/google/protobuf/descriptor.py46
-rw-r--r--python/google/protobuf/descriptor_pool.py39
-rwxr-xr-xpython/google/protobuf/internal/containers.py297
-rwxr-xr-xpython/google/protobuf/internal/decoder.py44
-rw-r--r--python/google/protobuf/internal/descriptor_database_test.py1
-rw-r--r--python/google/protobuf/internal/descriptor_pool_test.py45
-rwxr-xr-xpython/google/protobuf/internal/descriptor_test.py2
-rwxr-xr-xpython/google/protobuf/internal/encoder.py55
-rwxr-xr-xpython/google/protobuf/internal/generator_test.py1
-rw-r--r--python/google/protobuf/internal/message_factory_test.py1
-rwxr-xr-xpython/google/protobuf/internal/message_test.py521
-rw-r--r--python/google/protobuf/internal/proto_builder_test.py21
-rwxr-xr-xpython/google/protobuf/internal/python_message.py159
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py6
-rwxr-xr-xpython/google/protobuf/internal/service_reflection_test.py3
-rw-r--r--python/google/protobuf/internal/symbol_database_test.py1
-rwxr-xr-xpython/google/protobuf/internal/test_util.py24
-rwxr-xr-xpython/google/protobuf/internal/text_encoding_test.py1
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py141
-rwxr-xr-xpython/google/protobuf/internal/type_checkers.py9
-rwxr-xr-xpython/google/protobuf/internal/unknown_fields_test.py1
-rwxr-xr-xpython/google/protobuf/internal/wire_format_test.py1
-rw-r--r--python/google/protobuf/proto_builder.py20
-rw-r--r--python/google/protobuf/pyext/descriptor.cc287
-rw-r--r--python/google/protobuf/pyext/descriptor.h21
-rw-r--r--python/google/protobuf/pyext/descriptor_containers.cc26
-rw-r--r--python/google/protobuf/pyext/descriptor_containers.h5
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.cc185
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.h8
-rw-r--r--python/google/protobuf/pyext/extension_dict.cc17
-rw-r--r--python/google/protobuf/pyext/message.cc432
-rw-r--r--python/google/protobuf/pyext/message.h13
-rw-r--r--python/google/protobuf/pyext/message_map_container.cc540
-rw-r--r--python/google/protobuf/pyext/message_map_container.h117
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc56
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.h10
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.cc8
-rw-r--r--python/google/protobuf/pyext/scalar_map_container.cc514
-rw-r--r--python/google/protobuf/pyext/scalar_map_container.h110
-rwxr-xr-xpython/google/protobuf/reflection.py1
-rwxr-xr-xpython/google/protobuf/text_format.py36
-rwxr-xr-xpython/setup.py1
-rw-r--r--ruby/tests/generated_code.proto26
-rw-r--r--src/Makefile.am27
-rw-r--r--src/google/protobuf/any.cc100
-rw-r--r--src/google/protobuf/any.h90
-rw-r--r--src/google/protobuf/any.pb.cc23
-rw-r--r--src/google/protobuf/any.pb.h10
-rw-r--r--src/google/protobuf/any_test.cc89
-rw-r--r--src/google/protobuf/any_test.proto41
-rw-r--r--src/google/protobuf/api.pb.cc74
-rw-r--r--src/google/protobuf/api.pb.h4
-rwxr-xr-xsrc/google/protobuf/arena.cc9
-rw-r--r--src/google/protobuf/arena.h346
-rw-r--r--src/google/protobuf/arena_nc_test.py1
-rw-r--r--src/google/protobuf/arena_test_util.h1
-rw-r--r--src/google/protobuf/arena_unittest.cc75
-rw-r--r--src/google/protobuf/compiler/code_generator.h31
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc46
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc14
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc14
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h26
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc505
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h29
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc59
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc688
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h25
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc33
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_options.h5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc14
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto34
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc16
-rw-r--r--src/google/protobuf/compiler/cpp/test_large_enum_value.proto43
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc16
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.cc967
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.h159
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc108
-rw-r--r--src/google/protobuf/compiler/java/java_field.h32
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc10
-rw-r--r--src/google/protobuf/compiler/java/java_generator_factory.cc8
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h10
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field.cc226
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc708
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field_lite.h118
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc51
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.h1
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.cc461
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.h81
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc1184
-rw-r--r--src/google/protobuf/compiler/java/java_message.h11
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.cc661
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.h86
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder_lite.cc192
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder_lite.h83
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc411
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.cc944
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.h157
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc1174
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.h91
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc15
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.cc892
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.h163
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.cc1013
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.h158
-rw-r--r--src/google/protobuf/compiler/parser.cc80
-rw-r--r--src/google/protobuf/compiler/parser.h8
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc75
-rw-r--r--src/google/protobuf/compiler/plugin.cc28
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc90
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h4
-rw-r--r--src/google/protobuf/descriptor.cc183
-rw-r--r--src/google/protobuf/descriptor.h67
-rw-r--r--src/google/protobuf/descriptor.pb.cc1863
-rw-r--r--src/google/protobuf/descriptor.pb.h414
-rw-r--r--src/google/protobuf/descriptor.proto45
-rw-r--r--src/google/protobuf/descriptor_database.h4
-rw-r--r--src/google/protobuf/descriptor_unittest.cc246
-rw-r--r--src/google/protobuf/duration.pb.cc12
-rw-r--r--src/google/protobuf/empty.pb.cc8
-rw-r--r--src/google/protobuf/extension_set.cc61
-rw-r--r--src/google/protobuf/extension_set.h6
-rw-r--r--src/google/protobuf/extension_set_heavy.cc2
-rw-r--r--src/google/protobuf/field_mask.pb.cc12
-rw-r--r--src/google/protobuf/generated_message_reflection.h37
-rw-r--r--src/google/protobuf/generated_message_util.h13
-rw-r--r--src/google/protobuf/io/coded_stream.cc104
-rw-r--r--src/google/protobuf/io/coded_stream.h84
-rw-r--r--src/google/protobuf/io/coded_stream_inl.h17
-rw-r--r--src/google/protobuf/io/printer.cc72
-rw-r--r--src/google/protobuf/io/printer.h32
-rw-r--r--src/google/protobuf/lite_unittest.cc378
-rw-r--r--src/google/protobuf/map.h1
-rw-r--r--src/google/protobuf/map_entry_lite.h18
-rw-r--r--src/google/protobuf/map_field.cc18
-rw-r--r--src/google/protobuf/map_field.h1
-rw-r--r--src/google/protobuf/map_field_inl.h2
-rw-r--r--src/google/protobuf/map_field_lite.h2
-rw-r--r--src/google/protobuf/map_field_test.cc13
-rw-r--r--src/google/protobuf/map_test.cc21
-rw-r--r--src/google/protobuf/map_type_handler.h4
-rw-r--r--src/google/protobuf/map_unittest.proto16
-rw-r--r--src/google/protobuf/message.cc19
-rw-r--r--src/google/protobuf/message.h15
-rw-r--r--src/google/protobuf/message_lite.cc2
-rw-r--r--src/google/protobuf/message_lite.h3
-rw-r--r--src/google/protobuf/message_unittest.cc31
-rw-r--r--src/google/protobuf/proto3_arena_unittest.cc10
-rwxr-xr-xsrc/google/protobuf/reflection.h1
-rw-r--r--src/google/protobuf/repeated_field.h60
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc22
-rw-r--r--src/google/protobuf/source_context.pb.cc10
-rw-r--r--src/google/protobuf/struct.pb.cc95
-rw-r--r--src/google/protobuf/struct.pb.h4
-rw-r--r--src/google/protobuf/stubs/common.h8
-rw-r--r--src/google/protobuf/stubs/strutil.cc18
-rw-r--r--src/google/protobuf/stubs/strutil.h6
-rw-r--r--src/google/protobuf/testdata/golden_message_proto3bin398 -> 248 bytes
-rw-r--r--src/google/protobuf/testdata/map_test_data.txt140
-rw-r--r--src/google/protobuf/text_format.cc267
-rw-r--r--src/google/protobuf/text_format.h15
-rw-r--r--src/google/protobuf/text_format_unittest.cc21
-rw-r--r--src/google/protobuf/timestamp.pb.cc12
-rw-r--r--src/google/protobuf/type.pb.cc161
-rw-r--r--src/google/protobuf/type.pb.h14
-rw-r--r--src/google/protobuf/unittest.proto6
-rw-r--r--src/google/protobuf/unittest_drop_unknown_fields.proto10
-rw-r--r--src/google/protobuf/unittest_no_field_presence.proto56
-rw-r--r--src/google/protobuf/unittest_preserve_unknown_enum.proto4
-rw-r--r--src/google/protobuf/unittest_proto3_arena.proto90
-rw-r--r--src/google/protobuf/unknown_field_set.cc8
-rw-r--r--src/google/protobuf/unknown_field_set.h2
-rw-r--r--src/google/protobuf/wire_format.cc4
-rw-r--r--src/google/protobuf/wire_format_lite.h11
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h21
-rw-r--r--src/google/protobuf/wire_format_unittest.cc132
-rw-r--r--src/google/protobuf/wrappers.pb.cc90
-rw-r--r--src/google/protobuf/wrappers.pb.h16
-rw-r--r--vsprojects/libprotoc.vcproj64
227 files changed, 25713 insertions, 3789 deletions
diff --git a/.gitignore b/.gitignore
index 6508eccb..38755c96 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,7 @@ src/.libs
.dirstamp
+any_test.pb.*
map*unittest.pb.*
unittest*.pb.*
cpp_test*.pb.*
diff --git a/Android.mk b/Android.mk
index 18bdd091..bbd15740 100644
--- a/Android.mk
+++ b/Android.mk
@@ -90,14 +90,20 @@ COMPILER_SRC_FILES := \
src/google/protobuf/compiler/cpp/cpp_string_field.cc \
src/google/protobuf/compiler/java/java_enum.cc \
src/google/protobuf/compiler/java/java_enum_field.cc \
+ src/google/protobuf/compiler/java/java_enum_field_lite.cc \
src/google/protobuf/compiler/java/java_extension.cc \
src/google/protobuf/compiler/java/java_field.cc \
src/google/protobuf/compiler/java/java_file.cc \
src/google/protobuf/compiler/java/java_generator.cc \
src/google/protobuf/compiler/java/java_helpers.cc \
src/google/protobuf/compiler/java/java_message.cc \
+ src/google/protobuf/compiler/java/java_message_lite.cc \
+ src/google/protobuf/compiler/java/java_message_builder.cc \
+ src/google/protobuf/compiler/java/java_message_builder_lite.cc \
src/google/protobuf/compiler/java/java_message_field.cc \
+ src/google/protobuf/compiler/java/java_message_field_lite.cc \
src/google/protobuf/compiler/java/java_primitive_field.cc \
+ src/google/protobuf/compiler/java/java_primitive_field_lite.cc \
src/google/protobuf/compiler/java/java_service.cc \
src/google/protobuf/compiler/javamicro/javamicro_enum.cc \
src/google/protobuf/compiler/javamicro/javamicro_enum_field.cc \
diff --git a/Makefile.am b/Makefile.am
index 45d44f5c..645c924b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,28 +43,34 @@ java_EXTRA_DIST= \
java/src/main/java/com/google/protobuf/AbstractMessage.java \
java/src/main/java/com/google/protobuf/AbstractMessageLite.java \
java/src/main/java/com/google/protobuf/AbstractParser.java \
+ java/src/main/java/com/google/protobuf/AbstractProtobufList.java \
java/src/main/java/com/google/protobuf/BlockingRpcChannel.java \
java/src/main/java/com/google/protobuf/BlockingService.java \
java/src/main/java/com/google/protobuf/BoundedByteString.java \
+ java/src/main/java/com/google/protobuf/BooleanArrayList.java \
java/src/main/java/com/google/protobuf/ByteString.java \
java/src/main/java/com/google/protobuf/CodedInputStream.java \
java/src/main/java/com/google/protobuf/CodedOutputStream.java \
java/src/main/java/com/google/protobuf/Descriptors.java \
+ java/src/main/java/com/google/protobuf/DoubleArrayList.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 \
+ java/src/main/java/com/google/protobuf/FloatArrayList.java \
java/src/main/java/com/google/protobuf/GeneratedMessage.java \
java/src/main/java/com/google/protobuf/GeneratedMessageLite.java \
java/src/main/java/com/google/protobuf/Internal.java \
+ java/src/main/java/com/google/protobuf/IntArrayList.java \
java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
java/src/main/java/com/google/protobuf/LazyField.java \
java/src/main/java/com/google/protobuf/LazyFieldLite.java \
java/src/main/java/com/google/protobuf/LazyStringArrayList.java \
java/src/main/java/com/google/protobuf/LazyStringList.java \
java/src/main/java/com/google/protobuf/LiteralByteString.java \
+ java/src/main/java/com/google/protobuf/LongArrayList.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 \
@@ -74,7 +80,9 @@ java_EXTRA_DIST= \
java/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java \
java/src/main/java/com/google/protobuf/MessageOrBuilder.java \
java/src/main/java/com/google/protobuf/MessageReflection.java \
+ java/src/main/java/com/google/protobuf/MutabilityOracle.java \
java/src/main/java/com/google/protobuf/Parser.java \
+ java/src/main/java/com/google/protobuf/ProtobufArrayList.java \
java/src/main/java/com/google/protobuf/ProtocolMessageEnum.java \
java/src/main/java/com/google/protobuf/ProtocolStringList.java \
java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java \
@@ -96,16 +104,20 @@ java_EXTRA_DIST= \
java/src/main/java/com/google/protobuf/WireFormat.java \
java/src/test/java/com/google/protobuf/AbstractMessageTest.java \
java/src/test/java/com/google/protobuf/BoundedByteStringTest.java \
+ java/src/test/java/com/google/protobuf/BooleanArrayListTest.java \
java/src/test/java/com/google/protobuf/ByteStringTest.java \
java/src/test/java/com/google/protobuf/CheckUtf8Test.java \
java/src/test/java/com/google/protobuf/CodedInputStreamTest.java \
java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java \
java/src/test/java/com/google/protobuf/DeprecatedFieldTest.java \
java/src/test/java/com/google/protobuf/DescriptorsTest.java \
+ java/src/test/java/com/google/protobuf/DoubleArrayListTest.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/FloatArrayListTest.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/IntArrayListTest.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/LazyFieldLiteTest.java \
@@ -116,12 +128,14 @@ java_EXTRA_DIST= \
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/LongArrayListTest.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 \
+ java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java \
java/src/test/java/com/google/protobuf/RepeatedFieldBuilderTest.java \
java/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java \
java/src/test/java/com/google/protobuf/RopeByteStringTest.java \
diff --git a/conformance/conformance.proto b/conformance/conformance.proto
index 7b676898..39eafdbb 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -71,7 +71,7 @@ message ConformanceRequest {
}
// Which format should the testee serialize its message to?
- optional RequestedOutput requested_output = 3;
+ RequestedOutput requested_output = 3;
}
// Represents a single test case's output.
@@ -103,8 +103,8 @@ message ConformanceResponse {
// forms.
message TestAllTypes {
message NestedMessage {
- optional int32 a = 1;
- optional TestAllTypes corecursive = 2;
+ int32 a = 1;
+ TestAllTypes corecursive = 2;
}
enum NestedEnum {
@@ -115,36 +115,32 @@ message TestAllTypes {
}
// 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 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];
-
- optional TestAllTypes recursive_message = 27;
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+
+ NestedMessage optional_nested_message = 18;
+ ForeignMessage optional_foreign_message = 19;
+
+ NestedEnum optional_nested_enum = 21;
+ ForeignEnum optional_foreign_enum = 22;
+
+ string optional_string_piece = 24 [ctype=STRING_PIECE];
+ string optional_cord = 25 [ctype=CORD];
+
+ TestAllTypes recursive_message = 27;
// Repeated
repeated int32 repeated_int32 = 31;
@@ -163,10 +159,6 @@ message TestAllTypes {
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;
@@ -206,7 +198,7 @@ message TestAllTypes {
}
message ForeignMessage {
- optional int32 c = 1;
+ int32 c = 1;
}
enum ForeignEnum {
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index 61029e44..857f2152 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -295,6 +295,7 @@ void ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
failures_ = 0;
for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) {
+ if (i == FieldDescriptor::TYPE_GROUP) continue;
TestPrematureEOFForType(static_cast<WireFormatLite::FieldType>(i));
}
diff --git a/editors/proto.vim b/editors/proto.vim
index 23085a28..7f1aeb73 100644
--- a/editors/proto.vim
+++ b/editors/proto.vim
@@ -57,7 +57,7 @@ syn keyword pbSyntax syntax import option
syn keyword pbStructure package message group oneof
syn keyword pbRepeat optional required repeated
syn keyword pbDefault default
-syn keyword pbExtend extend extensions to max
+syn keyword pbExtend extend extensions to max reserved
syn keyword pbRPC service rpc returns
syn keyword pbType int32 int64 uint32 uint64 sint32 sint64
diff --git a/editors/protobuf-mode.el b/editors/protobuf-mode.el
index 09aecc93..f615a0af 100644
--- a/editors/protobuf-mode.el
+++ b/editors/protobuf-mode.el
@@ -106,7 +106,7 @@
;; cc-mode. So, we approximate as best we can.
(c-lang-defconst c-type-list-kwds
- protobuf '("extensions" "to"))
+ protobuf '("extensions" "to" "reserved"))
(c-lang-defconst c-typeless-decl-kwds
protobuf '("extend" "rpc" "option" "returns"))
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index 27d293a2..89449e10 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -43,8 +43,11 @@ declare -a RUNTIME_PROTO_FILES=(\
google/protobuf/wrappers.proto)
CORE_PROTO_IS_CORRECT=0
+PROCESS_ROUND=1
+echo "Updating descriptor protos..."
while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
do
+ echo "Round $PROCESS_ROUND"
CORE_PROTO_IS_CORRECT=1
for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]}; do
BASE_NAME=${PROTO_FILE%.*}
@@ -86,5 +89,7 @@ do
done
rm google/protobuf/compiler/plugin.pb.h.tmp
rm google/protobuf/compiler/plugin.pb.cc.tmp
+
+ PROCESS_ROUND=$((PROCESS_ROUND + 1))
done
cd ..
diff --git a/java/pom.xml b/java/pom.xml
index 3eb7a703..9f270113 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -134,6 +134,7 @@
<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" />
+ <arg value="src/test/java/com/google/protobuf/map_initialization_order_test.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
@@ -227,25 +228,33 @@
<includes>
<include>**/AbstractMessageLite.java</include>
<include>**/AbstractParser.java</include>
+ <include>**/AbstractProtobufList.java</include>
<include>**/BoundedByteString.java</include>
+ <include>**/BooleanArrayList.java</include>
<include>**/ByteString.java</include>
<include>**/CodedInputStream.java</include>
<include>**/CodedOutputStream.java</include>
+ <include>**/DoublerrayList.java</include>
<include>**/ExtensionLite.java</include>
<include>**/ExtensionRegistryLite.java</include>
<include>**/FieldSet.java</include>
+ <include>**/FloatArrayList.java</include>
<include>**/GeneratedMessageLite.java</include>
+ <include>**/IntArrayList.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>**/LongArrayList.java</include>
<include>**/MapEntryLite.java</include>
<include>**/MapFieldLite.java</include>
<include>**/MessageLite.java</include>
<include>**/MessageLiteOrBuilder.java</include>
+ <include>**/MutabilityOracle.java</include>
<include>**/Parser.java</include>
+ <include>**/ProtobufArrayList.java</include>
<include>**/ProtocolStringList.java</include>
<include>**/RopeByteString.java</include>
<include>**/SmallSortedMap.java</include>
@@ -257,8 +266,14 @@
</includes>
<testIncludes>
<testInclude>**/*Lite.java</testInclude>
+ <testInclude>**/BooleanArrayListTest.java</testInclude>
+ <testInclude>**/DoubleArrayListTest.java</testInclude>
+ <testInclude>**/FloatArrayListTest.java</testInclude>
+ <testInclude>**/IntArrayListTest.java</testInclude>
<testInclude>**/LazyMessageLiteTest.java</testInclude>
<testInclude>**/LiteTest.java</testInclude>
+ <testInclude>**/LongArrayListTest.java</testInclude>
+ <testInclude>**/ProtobufArrayListTest.java</testInclude>
<testInclude>**/UnknownFieldSetLiteTest.java</testInclude>
</testIncludes>
</configuration>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
index aac4fa77..12384983 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -31,8 +31,8 @@
package com.google.protobuf;
import java.io.FilterInputStream;
-import java.io.InputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
@@ -109,6 +109,11 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
+ protected static <T> void addAll(final Iterable<T> values,
+ final Collection<? super T> list) {
+ Builder.addAll(values, list);
+ }
+
/**
* A partial implementation of the {@link Message.Builder} interface which
* implements as many methods of that interface as possible in terms of
@@ -320,12 +325,15 @@ public abstract class AbstractMessageLite implements MessageLite {
* Adds the {@code values} to the {@code list}. This is a helper method
* used by generated code. Users should ignore it.
*
- * @throws NullPointerException if any of the elements of {@code values} is
- * null. When that happens, some elements of {@code values} may have already
- * been added to the result {@code list}.
+ * @throws NullPointerException if {@code values} or any of the elements of
+ * {@code values} is null. When that happens, some elements of
+ * {@code values} may have already been added to the result {@code list}.
*/
protected static <T> void addAll(final Iterable<T> values,
final Collection<? super T> list) {
+ if (values == null) {
+ throw new NullPointerException();
+ }
if (values instanceof LazyStringList) {
// For StringOrByteStringLists, check the underlying elements to avoid
// forcing conversions of ByteStrings to Strings.
diff --git a/java/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/src/main/java/com/google/protobuf/AbstractProtobufList.java
new file mode 100644
index 00000000..bb6446b2
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/AbstractProtobufList.java
@@ -0,0 +1,136 @@
+// 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.Internal.ProtobufList;
+
+import java.util.AbstractList;
+import java.util.Collection;
+
+/**
+ * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate
+ * methods are check if the list is mutable before proceeding. Subclasses must invoke
+ * {@link #ensureIsMutable()} manually when overriding those methods.
+ */
+abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> {
+
+ /**
+ * Whether or not this list is modifiable.
+ */
+ private boolean isMutable;
+
+ /**
+ * Constructs a mutable list by default.
+ */
+ AbstractProtobufList() {
+ isMutable = true;
+ }
+
+ @Override
+ public boolean add(E e) {
+ ensureIsMutable();
+ return super.add(e);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ ensureIsMutable();
+ super.add(index, element);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ ensureIsMutable();
+ return super.addAll(c);
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
+ ensureIsMutable();
+ return super.addAll(index, c);
+ }
+
+ @Override
+ public void clear() {
+ ensureIsMutable();
+ super.clear();
+ }
+
+ @Override
+ public boolean isModifiable() {
+ return isMutable;
+ }
+
+ @Override
+ public final void makeImmutable() {
+ isMutable = false;
+ }
+
+ @Override
+ public E remove(int index) {
+ ensureIsMutable();
+ return super.remove(index);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ return super.remove(o);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ ensureIsMutable();
+ return super.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ ensureIsMutable();
+ return super.retainAll(c);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ ensureIsMutable();
+ return super.set(index, element);
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException} if the list is immutable. Subclasses are
+ * responsible for invoking this method on mutate operations.
+ */
+ protected void ensureIsMutable() {
+ if (!isMutable) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/src/main/java/com/google/protobuf/BooleanArrayList.java
new file mode 100644
index 00000000..45492d2f
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -0,0 +1,244 @@
+// 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.Internal.BooleanList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link BooleanList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class BooleanArrayList
+ extends AbstractProtobufList<Boolean> implements BooleanList, RandomAccess {
+
+ private static final int DEFAULT_CAPACITY = 10;
+
+ private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static BooleanArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private boolean[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code BooleanArrayList}.
+ */
+ BooleanArrayList() {
+ array = new boolean[DEFAULT_CAPACITY];
+ size = 0;
+ }
+
+ /**
+ * Constructs a new mutable {@code BooleanArrayList} containing the same elements as
+ * {@code other}.
+ */
+ BooleanArrayList(List<Boolean> other) {
+ if (other instanceof BooleanArrayList) {
+ BooleanArrayList list = (BooleanArrayList) other;
+ array = list.array.clone();
+ size = list.size;
+ } else {
+ size = other.size();
+ array = new boolean[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = other.get(i);
+ }
+ }
+ }
+
+ @Override
+ public Boolean get(int index) {
+ return getBoolean(index);
+ }
+
+ @Override
+ public boolean getBoolean(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Boolean set(int index, Boolean element) {
+ return setBoolean(index, element);
+ }
+
+ @Override
+ public boolean setBoolean(int index, boolean element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ boolean previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Boolean element) {
+ addBoolean(index, element);
+ }
+
+ /**
+ * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addBoolean(boolean element) {
+ addBoolean(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element.
+ */
+ private void addBoolean(int index, boolean element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ boolean[] newArray = new boolean[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Boolean> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another BooleanArrayList to avoid boxing elements.
+ if (!(collection instanceof BooleanArrayList)) {
+ return super.addAll(collection);
+ }
+
+ BooleanArrayList list = (BooleanArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Boolean remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ boolean value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index b60bd36b..3658410c 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -644,6 +644,30 @@ public final class Descriptors {
return false;
}
+ /** Determines if the given field number is reserved. */
+ public boolean isReservedNumber(final int number) {
+ for (final DescriptorProto.ReservedRange range :
+ proto.getReservedRangeList()) {
+ if (range.getStart() <= number && number < range.getEnd()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Determines if the given field name is reserved. */
+ public boolean isReservedName(final String name) {
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ for (final String reservedName : proto.getReservedNameList()) {
+ if (reservedName.equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Indicates whether the message can be extended. That is, whether it has
* any "extensions x to y" ranges declared on it.
@@ -917,9 +941,18 @@ public final class Descriptors {
return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
}
- /** Does this field have the {@code [packed = true]} option? */
+ /** Does this field have the {@code [packed = true]} option or is this field
+ * packable in proto3 and not explicitly setted to unpacked?
+ */
public boolean isPacked() {
- return getOptions().getPacked();
+ if (!isPackable()) {
+ return false;
+ }
+ if (getFile().getSyntax() == FileDescriptor.Syntax.PROTO2) {
+ return getOptions().getPacked();
+ } else {
+ return !getOptions().hasPacked() || getOptions().getPacked();
+ }
}
/** Can this field be packed? i.e. is it a repeated primitive field? */
@@ -2317,6 +2350,11 @@ public final class Descriptors {
public int getFieldCount() { return fieldCount; }
+ /** Get a list of this message type's fields. */
+ public List<FieldDescriptor> getFields() {
+ return Collections.unmodifiableList(Arrays.asList(fields));
+ }
+
public FieldDescriptor getField(int index) {
return fields[index];
}
diff --git a/java/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/src/main/java/com/google/protobuf/DoubleArrayList.java
new file mode 100644
index 00000000..90ebe109
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -0,0 +1,243 @@
+// 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.Internal.DoubleList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link DoubleList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class DoubleArrayList
+ extends AbstractProtobufList<Double> implements DoubleList, RandomAccess {
+
+ private static final int DEFAULT_CAPACITY = 10;
+
+ private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static DoubleArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private double[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code DoubleArrayList}.
+ */
+ DoubleArrayList() {
+ array = new double[DEFAULT_CAPACITY];
+ size = 0;
+ }
+
+ /**
+ * Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}.
+ */
+ DoubleArrayList(List<Double> other) {
+ if (other instanceof DoubleArrayList) {
+ DoubleArrayList list = (DoubleArrayList) other;
+ array = list.array.clone();
+ size = list.size;
+ } else {
+ size = other.size();
+ array = new double[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = other.get(i);
+ }
+ }
+ }
+
+ @Override
+ public Double get(int index) {
+ return getDouble(index);
+ }
+
+ @Override
+ public double getDouble(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Double set(int index, Double element) {
+ return setDouble(index, element);
+ }
+
+ @Override
+ public double setDouble(int index, double element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ double previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Double element) {
+ addDouble(index, element);
+ }
+
+ /**
+ * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addDouble(double element) {
+ addDouble(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Double)} but more efficient in that it doesn't box the element.
+ */
+ private void addDouble(int index, double element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ double[] newArray = new double[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Double> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another DoubleArrayList to avoid boxing elements.
+ if (!(collection instanceof DoubleArrayList)) {
+ return super.addAll(collection);
+ }
+
+ DoubleArrayList list = (DoubleArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Double remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ double value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/FloatArrayList.java b/java/src/main/java/com/google/protobuf/FloatArrayList.java
new file mode 100644
index 00000000..293eaff6
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -0,0 +1,242 @@
+// 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.Internal.FloatList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link FloatList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class FloatArrayList extends AbstractProtobufList<Float> implements FloatList, RandomAccess {
+
+ private static final int DEFAULT_CAPACITY = 10;
+
+ private static final FloatArrayList EMPTY_LIST = new FloatArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static FloatArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private float[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code FloatArrayList}.
+ */
+ FloatArrayList() {
+ array = new float[DEFAULT_CAPACITY];
+ size = 0;
+ }
+
+ /**
+ * Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}.
+ */
+ FloatArrayList(List<Float> other) {
+ if (other instanceof FloatArrayList) {
+ FloatArrayList list = (FloatArrayList) other;
+ array = list.array.clone();
+ size = list.size;
+ } else {
+ size = other.size();
+ array = new float[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = other.get(i);
+ }
+ }
+ }
+
+ @Override
+ public Float get(int index) {
+ return getFloat(index);
+ }
+
+ @Override
+ public float getFloat(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Float set(int index, Float element) {
+ return setFloat(index, element);
+ }
+
+ @Override
+ public float setFloat(int index, float element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ float previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Float element) {
+ addFloat(index, element);
+ }
+
+ /**
+ * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addFloat(float element) {
+ addFloat(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Float)} but more efficient in that it doesn't box the element.
+ */
+ private void addFloat(int index, float element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ float[] newArray = new float[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Float> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another FloatArrayList to avoid boxing elements.
+ if (!(collection instanceof FloatArrayList)) {
+ return super.addAll(collection);
+ }
+
+ FloatArrayList list = (FloatArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Float remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ float value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 6839c9dd..bd6bc463 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -30,6 +30,12 @@
package com.google.protobuf;
+import com.google.protobuf.Internal.BooleanList;
+import com.google.protobuf.Internal.DoubleList;
+import com.google.protobuf.Internal.FloatList;
+import com.google.protobuf.Internal.IntList;
+import com.google.protobuf.Internal.LongList;
+import com.google.protobuf.Internal.ProtobufList;
import com.google.protobuf.WireFormat.FieldType;
import java.io.IOException;
@@ -76,7 +82,11 @@ public abstract class GeneratedMessageLite<
private static final long serialVersionUID = 1L;
/** For use by generated code only. */
- protected UnknownFieldSetLite unknownFields;
+ protected UnknownFieldSetLite unknownFields =
+ UnknownFieldSetLite.getDefaultInstance();
+
+ /** For use by generated code only. */
+ protected int memoizedSerializedSize = -1;
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final Parser<MessageType> getParserForType() {
@@ -109,10 +119,67 @@ public abstract class GeneratedMessageLite<
return unknownFields.mergeFieldFrom(tag, input);
}
- // The default behavior. If a message has required fields in its subtree, the
- // generated code will override.
- public boolean isInitialized() {
- return true;
+ public final boolean isInitialized() {
+ return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null;
+ }
+
+ public final BuilderType toBuilder() {
+ BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
+ builder.mergeFrom((MessageType) this);
+ return builder;
+ }
+
+ /**
+ * Defines which method path to invoke in {@link GeneratedMessageLite
+ * #dynamicMethod(MethodToInvoke, Object...)}.
+ * <p>
+ * For use by generated code only.
+ */
+ public static enum MethodToInvoke {
+ IS_INITIALIZED,
+ PARSE_PARTIAL_FROM,
+ MERGE_FROM,
+ MAKE_IMMUTABLE,
+ NEW_INSTANCE,
+ NEW_BUILDER;
+ }
+
+ /**
+ * A method that implements different types of operations described in {@link MethodToInvoke}.
+ * Theses different kinds of operations are required to implement message-level operations for
+ * builders in the runtime. This method bundles those operations to reduce the generated methods
+ * count.
+ * <ul>
+ * <li>{@code PARSE_PARTIAL_FROM} is parameterized with an {@link CodedInputStream} and
+ * {@link ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the
+ * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, the
+ * implementation wraps it in a RuntimeException
+ * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer
+ * <li>{@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to
+ * memoize. It returns {@code null} for false and the default instance for true. We optionally
+ * memoize to support the Builder case, where memoization is not desired.
+ * <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance.
+ * <li>{@code MERGE_FROM} is parameterized with a {@code MessageType} and merges the fields from
+ * that instance into this instance.
+ * <li>{@code MAKE_IMMUTABLE} sets all internal fields to an immutable state.
+ * </ul>
+ * This method, plus the implementation of the Builder, enables the Builder class to be proguarded
+ * away entirely on Android.
+ * <p>
+ * For use by generated code only.
+ */
+ protected abstract Object dynamicMethod(
+ MethodToInvoke method,
+ Object... args);
+
+ /**
+ * Merge some unknown fields into the {@link UnknownFieldSetLite} for this
+ * message.
+ *
+ * <p>For use by generated code only.
+ */
+ protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) {
+ this.unknownFields = UnknownFieldSetLite.concat(this.unknownFields, unknownFields);
}
@SuppressWarnings("unchecked")
@@ -122,24 +189,37 @@ public abstract class GeneratedMessageLite<
extends AbstractMessageLite.Builder<BuilderType> {
private final MessageType defaultInstance;
-
- /** For use by generated code only. */
- protected UnknownFieldSetLite unknownFields =
- UnknownFieldSetLite.getDefaultInstance();
+ protected MessageType instance;
+ protected boolean isBuilt;
protected Builder(MessageType defaultInstance) {
this.defaultInstance = defaultInstance;
+ this.instance = (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
+ isBuilt = false;
}
- // The default behavior. If a message has required fields in its subtree,
- // the generated code will override.
- public boolean isInitialized() {
- return true;
+ /**
+ * Called before any method that would mutate the builder to ensure that it correctly copies
+ * any state before the write happens to preserve immutability guarantees.
+ */
+ protected void copyOnWrite() {
+ if (isBuilt) {
+ MessageType newInstance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
+ newInstance.dynamicMethod(MethodToInvoke.MERGE_FROM, instance);
+ instance = newInstance;
+ isBuilt = false;
+ }
+ }
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
+ public final boolean isInitialized() {
+ return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */);
}
//@Override (Java 1.6 override semantics, but we must support 1.5)
- public BuilderType clear() {
- unknownFields = UnknownFieldSetLite.getDefaultInstance();
+ public final BuilderType clear() {
+ // No need to copy on write since we're dropping the instance anyways.
+ instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
return (BuilderType) this;
}
@@ -151,8 +231,12 @@ public abstract class GeneratedMessageLite<
return builder;
}
- /** All subclasses implement this. */
- public abstract MessageType buildPartial();
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
+ public MessageType buildPartial() {
+ instance.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+ isBuilt = true;
+ return instance;
+ }
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final MessageType build() {
@@ -162,9 +246,13 @@ public abstract class GeneratedMessageLite<
}
return result;
}
-
+
/** All subclasses implement this. */
- public abstract BuilderType mergeFrom(MessageType message);
+ public BuilderType mergeFrom(MessageType message) {
+ copyOnWrite();
+ instance.dynamicMethod(MethodToInvoke.MERGE_FROM, message);
+ return (BuilderType) this;
+ }
public MessageType getDefaultInstanceForType() {
return defaultInstance;
@@ -181,18 +269,6 @@ public abstract class GeneratedMessageLite<
int tag) throws IOException {
return unknownFields.mergeFieldFrom(tag, input);
}
-
- /**
- * 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 BuilderType mergeFrom(
com.google.protobuf.CodedInputStream input,
@@ -259,19 +335,13 @@ public abstract class GeneratedMessageLite<
*/
protected FieldSet<ExtensionDescriptor> extensions = FieldSet.newFieldSet();
- // -1 => not memoized, 0 => false, 1 => true.
- private byte memoizedIsInitialized = -1;
-
- // The default behavior. If a message has required fields in its subtree,
- // the generated code will override.
- public boolean isInitialized() {
- if (memoizedIsInitialized == -1) {
- memoizedIsInitialized = (byte) (extensions.isInitialized() ? 1 : 0);
+ protected final void mergeExtensionFields(final MessageType other) {
+ if (extensions.isImmutable()) {
+ extensions = extensions.clone();
}
-
- return memoizedIsInitialized == 1;
+ extensions.mergeFrom(((ExtendableMessage) other).extensions);
}
-
+
private void verifyExtensionContainingType(
final GeneratedExtension<MessageType, ?> extension) {
if (extension.getContainingTypeDefaultInstance() !=
@@ -420,46 +490,38 @@ public abstract class GeneratedMessageLite<
implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
protected ExtendableBuilder(MessageType defaultInstance) {
super(defaultInstance);
- }
-
- private FieldSet<ExtensionDescriptor> extensions = FieldSet.emptySet();
- private boolean extensionsIsMutable;
-
- // The default behavior. If a message has required fields in its subtree,
- // the generated code will override.
- public boolean isInitialized() {
- return extensions.isInitialized();
+
+ // TODO(dweis): This is kind of an unnecessary clone since we construct a
+ // new instance in the parent constructor which makes the extensions
+ // immutable. This extra allocation shouldn't matter in practice
+ // though.
+ instance.extensions = instance.extensions.clone();
}
// For immutable message conversion.
void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) {
- this.extensions = extensions;
+ copyOnWrite();
+ instance.extensions = extensions;
}
- @Override
- public BuilderType clear() {
- extensions.clear();
- extensionsIsMutable = false;
- return super.clear();
+ // @Override (Java 1.6 override semantics, but we must support 1.5)
+ protected void copyOnWrite() {
+ if (!isBuilt) {
+ return;
+ }
+
+ super.copyOnWrite();
+ instance.extensions = instance.extensions.clone();
}
- private void ensureExtensionsIsMutable() {
- if (!extensionsIsMutable) {
- extensions = extensions.clone();
- extensionsIsMutable = true;
+ // @Override (Java 1.6 override semantics, but we must support 1.5)
+ public final MessageType buildPartial() {
+ if (isBuilt) {
+ return instance;
}
- }
- /**
- * Called by the build code path to create a copy of the extensions for
- * building the message.
- * <p>
- * For use by generated code only.
- */
- protected final FieldSet<ExtensionDescriptor> buildExtensions() {
- extensions.makeImmutable();
- extensionsIsMutable = false;
- return extensions;
+ instance.extensions.makeImmutable();
+ return super.buildPartial();
}
private void verifyExtensionContainingType(
@@ -477,22 +539,14 @@ public abstract class GeneratedMessageLite<
//@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> boolean hasExtension(
final ExtensionLite<MessageType, Type> extension) {
- GeneratedExtension<MessageType, Type> extensionLite =
- checkIsLite(extension);
-
- verifyExtensionContainingType(extensionLite);
- return extensions.hasField(extensionLite.descriptor);
+ return instance.hasExtension(extension);
}
/** 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 ExtensionLite<MessageType, List<Type>> extension) {
- GeneratedExtension<MessageType, List<Type>> extensionLite =
- checkIsLite(extension);
-
- verifyExtensionContainingType(extensionLite);
- return extensions.getRepeatedFieldCount(extensionLite.descriptor);
+ return instance.getExtensionCount(extension);
}
/** Get the value of an extension. */
@@ -500,16 +554,7 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
final ExtensionLite<MessageType, Type> extension) {
- GeneratedExtension<MessageType, Type> extensionLite =
- checkIsLite(extension);
-
- verifyExtensionContainingType(extensionLite);
- final Object value = extensions.getField(extensionLite.descriptor);
- if (value == null) {
- return extensionLite.defaultValue;
- } else {
- return (Type) extensionLite.fromFieldSetType(value);
- }
+ return instance.getExtension(extension);
}
/** Get one element of a repeated extension. */
@@ -518,12 +563,7 @@ public abstract class GeneratedMessageLite<
public final <Type> Type getExtension(
final ExtensionLite<MessageType, List<Type>> extension,
final int index) {
- GeneratedExtension<MessageType, List<Type>> extensionLite =
- checkIsLite(extension);
-
- verifyExtensionContainingType(extensionLite);
- return (Type) extensionLite.singularFromFieldSetType(
- extensions.getRepeatedField(extensionLite.descriptor, index));
+ return instance.getExtension(extension, index);
}
// This is implemented here only to work around an apparent bug in the
@@ -542,9 +582,8 @@ public abstract class GeneratedMessageLite<
checkIsLite(extension);
verifyExtensionContainingType(extensionLite);
- ensureExtensionsIsMutable();
- extensions.setField(extensionLite.descriptor,
- extensionLite.toFieldSetType(value));
+ copyOnWrite();
+ instance.extensions.setField(extensionLite.descriptor, extensionLite.toFieldSetType(value));
return (BuilderType) this;
}
@@ -556,9 +595,9 @@ public abstract class GeneratedMessageLite<
checkIsLite(extension);
verifyExtensionContainingType(extensionLite);
- ensureExtensionsIsMutable();
- extensions.setRepeatedField(extensionLite.descriptor, index,
- extensionLite.singularToFieldSetType(value));
+ copyOnWrite();
+ instance.extensions.setRepeatedField(
+ extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value));
return (BuilderType) this;
}
@@ -570,9 +609,9 @@ public abstract class GeneratedMessageLite<
checkIsLite(extension);
verifyExtensionContainingType(extensionLite);
- ensureExtensionsIsMutable();
- extensions.addRepeatedField(extensionLite.descriptor,
- extensionLite.singularToFieldSetType(value));
+ copyOnWrite();
+ instance.extensions.addRepeatedField(
+ extensionLite.descriptor, extensionLite.singularToFieldSetType(value));
return (BuilderType) this;
}
@@ -582,20 +621,10 @@ public abstract class GeneratedMessageLite<
GeneratedExtension<MessageType, ?> extensionLite = checkIsLite(extension);
verifyExtensionContainingType(extensionLite);
- ensureExtensionsIsMutable();
- extensions.clearField(extensionLite.descriptor);
+ copyOnWrite();
+ instance.extensions.clearField(extensionLite.descriptor);
return (BuilderType) this;
}
-
- /** Called by subclasses to check if all extensions are initialized. */
- protected boolean extensionsAreInitialized() {
- return extensions.isInitialized();
- }
-
- protected final void mergeExtensionFields(final MessageType other) {
- ensureExtensionsIsMutable();
- extensions.mergeFrom(((ExtendableMessage) other).extensions);
- }
}
//-----------------------------------------------------------------
@@ -1113,4 +1142,133 @@ public abstract class GeneratedMessageLite<
return (BuilderType) defaultInstance.toBuilder();
}
}
+
+ /**
+ * A static helper method for checking if a message is initialized, optionally memoizing.
+ * <p>
+ * For use by generated code only.
+ */
+ protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized(
+ T message, boolean shouldMemoize) {
+ return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null;
+ }
+
+ protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) {
+ message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+ }
+
+ /**
+ * A static helper method for parsing a partial from input using the extension registry and the
+ * instance.
+ */
+ static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+ T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ return (T) instance.dynamicMethod(
+ MethodToInvoke.PARSE_PARTIAL_FROM, input, extensionRegistry);
+ } catch (RuntimeException e) {
+ if (e.getCause() instanceof InvalidProtocolBufferException) {
+ throw (InvalidProtocolBufferException) e.getCause();
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * A {@link Parser} implementation that delegates to the default instance.
+ * <p>
+ * For use by generated code only.
+ */
+ protected static class DefaultInstanceBasedParser<T extends GeneratedMessageLite<T, ?>>
+ extends AbstractParser<T> {
+
+ private T defaultInstance;
+
+ public DefaultInstanceBasedParser(T defaultInstance) {
+ this.defaultInstance = defaultInstance;
+ }
+
+ @Override
+ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return GeneratedMessageLite.parsePartialFrom(defaultInstance, input, extensionRegistry);
+ }
+ }
+
+ protected static IntList newIntList() {
+ return new IntArrayList();
+ }
+
+ protected static IntList newIntList(List<Integer> toCopy) {
+ return new IntArrayList(toCopy);
+ }
+
+ protected static IntList emptyIntList() {
+ return IntArrayList.emptyList();
+ }
+
+ protected static LongList newLongList() {
+ return new LongArrayList();
+ }
+
+ protected static LongList newLongList(List<Long> toCopy) {
+ return new LongArrayList(toCopy);
+ }
+
+ protected static LongList emptyLongList() {
+ return LongArrayList.emptyList();
+ }
+
+ protected static FloatList newFloatList() {
+ return new FloatArrayList();
+ }
+
+ protected static FloatList newFloatList(List<Float> toCopy) {
+ return new FloatArrayList(toCopy);
+ }
+
+ protected static FloatList emptyFloatList() {
+ return FloatArrayList.emptyList();
+ }
+
+ protected static DoubleList newDoubleList() {
+ return new DoubleArrayList();
+ }
+
+ protected static DoubleList newDoubleList(List<Double> toCopy) {
+ return new DoubleArrayList(toCopy);
+ }
+
+ protected static DoubleList emptyDoubleList() {
+ return DoubleArrayList.emptyList();
+ }
+
+ protected static BooleanList newBooleanList() {
+ return new BooleanArrayList();
+ }
+
+ protected static BooleanList newBooleanList(List<Boolean> toCopy) {
+ return new BooleanArrayList(toCopy);
+ }
+
+ protected static BooleanList emptyBooleanList() {
+ return BooleanArrayList.emptyList();
+ }
+
+ protected static <E> ProtobufList<E> newProtobufList() {
+ return new ProtobufArrayList<E>();
+ }
+
+ protected static <E> ProtobufList<E> newProtobufList(List<E> toCopy) {
+ return new ProtobufArrayList<E>(toCopy);
+ }
+
+ protected static <E> ProtobufList<E> emptyProtobufList() {
+ return ProtobufArrayList.emptyList();
+ }
+
+ protected static LazyStringArrayList emptyLazyStringArrayList() {
+ return LazyStringArrayList.emptyList();
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/IntArrayList.java b/java/src/main/java/com/google/protobuf/IntArrayList.java
new file mode 100644
index 00000000..f7609cc9
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/IntArrayList.java
@@ -0,0 +1,242 @@
+// 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.Internal.IntList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link IntList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class IntArrayList extends AbstractProtobufList<Integer> implements IntList, RandomAccess {
+
+ private static final int DEFAULT_CAPACITY = 10;
+
+ private static final IntArrayList EMPTY_LIST = new IntArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static IntArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private int[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code IntArrayList}.
+ */
+ IntArrayList() {
+ array = new int[DEFAULT_CAPACITY];
+ size = 0;
+ }
+
+ /**
+ * Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}.
+ */
+ IntArrayList(List<Integer> other) {
+ if (other instanceof IntArrayList) {
+ IntArrayList list = (IntArrayList) other;
+ array = list.array.clone();
+ size = list.size;
+ } else {
+ size = other.size();
+ array = new int[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = other.get(i);
+ }
+ }
+ }
+
+ @Override
+ public Integer get(int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public int getInt(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Integer set(int index, Integer element) {
+ return setInt(index, element);
+ }
+
+ @Override
+ public int setInt(int index, int element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ int previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Integer element) {
+ addInt(index, element);
+ }
+
+ /**
+ * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addInt(int element) {
+ addInt(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element.
+ */
+ private void addInt(int index, int element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ int[] newArray = new int[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Integer> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another IntArrayList to avoid boxing elements.
+ if (!(collection instanceof IntArrayList)) {
+ return super.addAll(collection);
+ }
+
+ IntArrayList list = (IntArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Integer remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ int value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
index 74bf44c0..20054b79 100644
--- a/java/src/main/java/com/google/protobuf/Internal.java
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -30,6 +30,7 @@
package com.google.protobuf;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.AbstractList;
@@ -532,4 +533,132 @@ public class Internal {
}
}
}
+
+ /**
+ * Extends {@link List} to add the capability to make the list immutable and inspect if it is
+ * modifiable.
+ */
+ public static interface ProtobufList<E> extends List<E> {
+
+ /**
+ * Makes this list immutable. All subsequent modifications will throw an
+ * {@link UnsupportedOperationException}.
+ */
+ void makeImmutable();
+
+ /**
+ * Returns whether this list can be modified via the publicly accessible {@link List} methods.
+ */
+ boolean isModifiable();
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Integers if
+ * possible. Does not support null elements.
+ */
+ public static interface IntList extends ProtobufList<Integer> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ int getInt(int index);
+
+ /**
+ * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
+ */
+ void addInt(int element);
+
+ /**
+ * Like {@link #set(int, Integer)} but more efficient in that it doesn't box the element.
+ */
+ int setInt(int index, int element);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Booleans if
+ * possible. Does not support null elements.
+ */
+ public static interface BooleanList extends ProtobufList<Boolean> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ boolean getBoolean(int index);
+
+ /**
+ * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
+ */
+ void addBoolean(boolean element);
+
+ /**
+ * Like {@link #set(int, Boolean)} but more efficient in that it doesn't box the element.
+ */
+ boolean setBoolean(int index, boolean element);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Longs if
+ * possible. Does not support null elements.
+ */
+ public static interface LongList extends ProtobufList<Long> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ long getLong(int index);
+
+ /**
+ * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
+ */
+ void addLong(long element);
+
+ /**
+ * Like {@link #set(int, Long)} but more efficient in that it doesn't box the element.
+ */
+ long setLong(int index, long element);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Doubles if
+ * possible. Does not support null elements.
+ */
+ public static interface DoubleList extends ProtobufList<Double> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ double getDouble(int index);
+
+ /**
+ * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
+ */
+ void addDouble(double element);
+
+ /**
+ * Like {@link #set(int, Double)} but more efficient in that it doesn't box the element.
+ */
+ double setDouble(int index, double element);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Floats if
+ * possible. Does not support null elements.
+ */
+ public static interface FloatList extends ProtobufList<Float> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ float getFloat(int index);
+
+ /**
+ * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
+ */
+ void addFloat(float element);
+
+ /**
+ * Like {@link #set(int, Float)} but more efficient in that it doesn't box the element.
+ */
+ float setFloat(int index, float element);
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
index 2d40a51f..a2997e1c 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -62,11 +62,20 @@ import java.util.RandomAccess;
*
* @author jonp@google.com (Jon Perlow)
*/
-public class LazyStringArrayList extends AbstractList<String>
+public class LazyStringArrayList extends AbstractProtobufList<String>
implements LazyStringList, RandomAccess {
+
+ private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ static LazyStringArrayList emptyList() {
+ return EMPTY_LIST;
+ }
- public static final LazyStringList EMPTY =
- new LazyStringArrayList().getUnmodifiableView();
+ // For compatibility with older runtimes.
+ public static final LazyStringList EMPTY = EMPTY_LIST;
private final List<Object> list;
@@ -116,12 +125,26 @@ public class LazyStringArrayList extends AbstractList<String>
@Override
public String set(int index, String s) {
+ ensureIsMutable();
Object o = list.set(index, s);
return asString(o);
}
@Override
public void add(int index, String element) {
+ ensureIsMutable();
+ list.add(index, element);
+ modCount++;
+ }
+
+ private void add(int index, ByteString element) {
+ ensureIsMutable();
+ list.add(index, element);
+ modCount++;
+ }
+
+ private void add(int index, byte[] element) {
+ ensureIsMutable();
list.add(index, element);
modCount++;
}
@@ -137,6 +160,7 @@ public class LazyStringArrayList extends AbstractList<String>
@Override
public boolean addAll(int index, Collection<? extends String> c) {
+ ensureIsMutable();
// When copying from another LazyStringList, directly copy the underlying
// elements rather than forcing each element to be decoded to a String.
Collection<?> collection = c instanceof LazyStringList
@@ -148,6 +172,7 @@ public class LazyStringArrayList extends AbstractList<String>
// @Override
public boolean addAllByteString(Collection<? extends ByteString> values) {
+ ensureIsMutable();
boolean ret = list.addAll(values);
modCount++;
return ret;
@@ -155,6 +180,7 @@ public class LazyStringArrayList extends AbstractList<String>
// @Override
public boolean addAllByteArray(Collection<byte[]> c) {
+ ensureIsMutable();
boolean ret = list.addAll(c);
modCount++;
return ret;
@@ -162,6 +188,7 @@ public class LazyStringArrayList extends AbstractList<String>
@Override
public String remove(int index) {
+ ensureIsMutable();
Object o = list.remove(index);
modCount++;
return asString(o);
@@ -169,18 +196,21 @@ public class LazyStringArrayList extends AbstractList<String>
@Override
public void clear() {
+ ensureIsMutable();
list.clear();
modCount++;
}
// @Override
public void add(ByteString element) {
+ ensureIsMutable();
list.add(element);
modCount++;
}
// @Override
public void add(byte[] element) {
+ ensureIsMutable();
list.add(element);
modCount++;
}
@@ -207,14 +237,23 @@ public class LazyStringArrayList extends AbstractList<String>
// @Override
public void set(int index, ByteString s) {
- list.set(index, s);
+ setAndReturn(index, s);
+ }
+
+ private Object setAndReturn(int index, ByteString s) {
+ ensureIsMutable();
+ return list.set(index, s);
}
// @Override
public void set(int index, byte[] s) {
- list.set(index, s);
+ setAndReturn(index, s);
+ }
+
+ private Object setAndReturn(int index, byte[] s) {
+ ensureIsMutable();
+ return list.set(index, s);
}
-
private static String asString(Object o) {
if (o instanceof String) {
@@ -253,6 +292,7 @@ public class LazyStringArrayList extends AbstractList<String>
// @Override
public void mergeFrom(LazyStringList other) {
+ ensureIsMutable();
for (Object o : other.getUnderlyingElements()) {
if (o instanceof byte[]) {
byte[] b = (byte[]) o;
@@ -267,20 +307,15 @@ public class LazyStringArrayList extends AbstractList<String>
private static class ByteArrayListView extends AbstractList<byte[]>
implements RandomAccess {
- private final List<Object> list;
+ private final LazyStringArrayList list;
- ByteArrayListView(List<Object> list) {
+ ByteArrayListView(LazyStringArrayList list) {
this.list = list;
}
@Override
public byte[] get(int index) {
- Object o = list.get(index);
- byte[] b = asByteArray(o);
- if (b != o) {
- list.set(index, b);
- }
- return b;
+ return list.getByteArray(index);
}
@Override
@@ -290,7 +325,7 @@ public class LazyStringArrayList extends AbstractList<String>
@Override
public byte[] set(int index, byte[] s) {
- Object o = list.set(index, s);
+ Object o = list.setAndReturn(index, s);
modCount++;
return asByteArray(o);
}
@@ -311,25 +346,20 @@ public class LazyStringArrayList extends AbstractList<String>
// @Override
public List<byte[]> asByteArrayList() {
- return new ByteArrayListView(list);
+ return new ByteArrayListView(this);
}
private static class ByteStringListView extends AbstractList<ByteString>
implements RandomAccess {
- private final List<Object> list;
+ private final LazyStringArrayList list;
- ByteStringListView(List<Object> list) {
+ ByteStringListView(LazyStringArrayList list) {
this.list = list;
}
@Override
public ByteString get(int index) {
- Object o = list.get(index);
- ByteString b = asByteString(o);
- if (b != o) {
- list.set(index, b);
- }
- return b;
+ return list.getByteString(index);
}
@Override
@@ -339,7 +369,7 @@ public class LazyStringArrayList extends AbstractList<String>
@Override
public ByteString set(int index, ByteString s) {
- Object o = list.set(index, s);
+ Object o = list.setAndReturn(index, s);
modCount++;
return asByteString(o);
}
@@ -360,12 +390,15 @@ public class LazyStringArrayList extends AbstractList<String>
// @Override
public List<ByteString> asByteStringList() {
- return new ByteStringListView(list);
+ return new ByteStringListView(this);
}
// @Override
public LazyStringList getUnmodifiableView() {
- return new UnmodifiableLazyStringList(this);
+ if (isModifiable()) {
+ return new UnmodifiableLazyStringList(this);
+ }
+ return this;
}
}
diff --git a/java/src/main/java/com/google/protobuf/LongArrayList.java b/java/src/main/java/com/google/protobuf/LongArrayList.java
new file mode 100644
index 00000000..298617ff
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/LongArrayList.java
@@ -0,0 +1,242 @@
+// 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.Internal.LongList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link LongList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class LongArrayList extends AbstractProtobufList<Long> implements LongList, RandomAccess {
+
+ private static final int DEFAULT_CAPACITY = 10;
+
+ private static final LongArrayList EMPTY_LIST = new LongArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static LongArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private long[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code LongArrayList}.
+ */
+ LongArrayList() {
+ array = new long[DEFAULT_CAPACITY];
+ size = 0;
+ }
+
+ /**
+ * Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}.
+ */
+ LongArrayList(List<Long> other) {
+ if (other instanceof LongArrayList) {
+ LongArrayList list = (LongArrayList) other;
+ array = list.array.clone();
+ size = list.size;
+ } else {
+ size = other.size();
+ array = new long[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = other.get(i);
+ }
+ }
+ }
+
+ @Override
+ public Long get(int index) {
+ return getLong(index);
+ }
+
+ @Override
+ public long getLong(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Long set(int index, Long element) {
+ return setLong(index, element);
+ }
+
+ @Override
+ public long setLong(int index, long element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ long previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Long element) {
+ addLong(index, element);
+ }
+
+ /**
+ * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addLong(long element) {
+ addLong(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Long)} but more efficient in that it doesn't box the element.
+ */
+ private void addLong(int index, long element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ long[] newArray = new long[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Long> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another LongArrayList to avoid boxing elements.
+ if (!(collection instanceof LongArrayList)) {
+ return super.addAll(collection);
+ }
+
+ LongArrayList list = (LongArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Long remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ long value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/MapField.java b/java/src/main/java/com/google/protobuf/MapField.java
index 82906d37..b290993c 100644
--- a/java/src/main/java/com/google/protobuf/MapField.java
+++ b/java/src/main/java/com/google/protobuf/MapField.java
@@ -30,9 +30,11 @@
package com.google.protobuf;
+import com.google.protobuf.MapFieldLite.MutatabilityAwareMap;
+
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -51,7 +53,7 @@ import java.util.Map;
* and getList() concurrently in multiple threads. If write-access is needed,
* all access must be synchronized.
*/
-public class MapField<K, V> {
+public class MapField<K, V> implements MutabilityOracle {
/**
* Indicates where the data of this map field is currently stored.
*
@@ -72,8 +74,9 @@ public class MapField<K, V> {
*/
private enum StorageMode {MAP, LIST, BOTH}
+ private volatile boolean isMutable;
private volatile StorageMode mode;
- private Map<K, V> mapData;
+ private MutatabilityAwareMap<K, V> mapData;
private List<Message> listData;
// Convert between a map entry Message and a key-value pair.
@@ -110,20 +113,19 @@ public class MapField<K, V> {
private MapField(
Converter<K, V> converter,
StorageMode mode,
- Map<K, V> mapData,
- List<Message> listData) {
+ Map<K, V> mapData) {
this.converter = converter;
+ this.isMutable = true;
this.mode = mode;
- this.mapData = mapData;
- this.listData = listData;
+ this.mapData = new MutatabilityAwareMap<K, V>(this, mapData);
+ this.listData = null;
}
private MapField(
MapEntry<K, V> defaultEntry,
StorageMode mode,
- Map<K, V> mapData,
- List<Message> listData) {
- this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData, listData);
+ Map<K, V> mapData) {
+ this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData);
}
@@ -131,14 +133,14 @@ public class MapField<K, V> {
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);
+ defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap());
}
/** 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);
+ defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>());
}
@@ -151,7 +153,7 @@ public class MapField<K, V> {
converter.convertMessageToKeyAndValue(message, map);
}
- private List<Message> convertMapToList(Map<K, V> mapData) {
+ private List<Message> convertMapToList(MutatabilityAwareMap<K, V> mapData) {
List<Message> listData = new ArrayList<Message>();
for (Map.Entry<K, V> entry : mapData.entrySet()) {
listData.add(
@@ -161,12 +163,12 @@ public class MapField<K, V> {
return listData;
}
- private Map<K, V> convertListToMap(List<Message> listData) {
- Map<K, V> mapData = new HashMap<K, V>();
+ private MutatabilityAwareMap<K, V> convertListToMap(List<Message> listData) {
+ Map<K, V> mapData = new LinkedHashMap<K, V>();
for (Message item : listData) {
convertMessageToKeyAndValue(item, mapData);
}
- return mapData;
+ return new MutatabilityAwareMap<K, V>(this, mapData);
}
/** Returns the content of this MapField as a read-only Map. */
@@ -199,7 +201,7 @@ public class MapField<K, V> {
}
public void clear() {
- mapData = new HashMap<K, V>();
+ mapData = new MutatabilityAwareMap<K, V>(this, new LinkedHashMap<K, V>());
mode = StorageMode.MAP;
}
@@ -221,7 +223,7 @@ public class MapField<K, V> {
/** Returns a deep copy of this MapField. */
public MapField<K, V> copy() {
return new MapField<K, V>(
- converter, StorageMode.MAP, MapFieldLite.copy(getMap()), null);
+ converter, StorageMode.MAP, MapFieldLite.copy(getMap()));
}
/** Gets the content of this MapField as a read-only List. */
@@ -256,4 +258,29 @@ public class MapField<K, V> {
Message getMapEntryMessageDefaultInstance() {
return converter.getMessageDefaultInstance();
}
+
+ /**
+ * Makes this list immutable. All subsequent modifications will throw an
+ * {@link UnsupportedOperationException}.
+ */
+ public void makeImmutable() {
+ isMutable = false;
+ }
+
+ /**
+ * Returns whether this field can be modified.
+ */
+ public boolean isMutable() {
+ return isMutable;
+ }
+
+ /* (non-Javadoc)
+ * @see com.google.protobuf.MutabilityOracle#ensureMutable()
+ */
+ @Override
+ public void ensureMutable() {
+ if (!isMutable()) {
+ throw new UnsupportedOperationException();
+ }
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/MapFieldLite.java b/java/src/main/java/com/google/protobuf/MapFieldLite.java
index 7f94c690..c17fa7b1 100644
--- a/java/src/main/java/com/google/protobuf/MapFieldLite.java
+++ b/java/src/main/java/com/google/protobuf/MapFieldLite.java
@@ -31,9 +31,12 @@
package com.google.protobuf;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Set;
/**
* Internal representation of map fields in generated lite-runtime messages.
@@ -41,16 +44,21 @@ import java.util.Map;
* This class is a protobuf implementation detail. Users shouldn't use this
* class directly.
*/
-public class MapFieldLite<K, V> {
- private Map<K, V> mapData;
+public class MapFieldLite<K, V> implements MutabilityOracle {
+ private MutatabilityAwareMap<K, V> mapData;
+ private boolean isMutable;
private MapFieldLite(Map<K, V> mapData) {
- this.mapData = mapData;
+ this.mapData = new MutatabilityAwareMap<K, V>(this, mapData);
+ this.isMutable = true;
}
@SuppressWarnings({"rawtypes", "unchecked"})
private static final MapFieldLite EMPTY_MAP_FIELD =
new MapFieldLite(Collections.emptyMap());
+ static {
+ EMPTY_MAP_FIELD.makeImmutable();
+ }
/** Returns an singleton immutable empty MapFieldLite instance. */
@SuppressWarnings({"unchecked", "cast"})
@@ -60,7 +68,7 @@ public class MapFieldLite<K, V> {
/** Creates a new MapFieldLite instance. */
public static <K, V> MapFieldLite<K, V> newMapField() {
- return new MapFieldLite<K, V>(new HashMap<K, V>());
+ return new MapFieldLite<K, V>(new LinkedHashMap<K, V>());
}
/** Gets the content of this MapField as a read-only Map. */
@@ -168,7 +176,7 @@ public class MapFieldLite<K, V> {
*/
@SuppressWarnings("unchecked")
static <K, V> Map<K, V> copy(Map<K, V> map) {
- Map<K, V> result = new HashMap<K, V>();
+ Map<K, V> result = new LinkedHashMap<K, V>();
for (Map.Entry<K, V> entry : map.entrySet()) {
result.put(entry.getKey(), (V) copy(entry.getValue()));
}
@@ -179,4 +187,360 @@ public class MapFieldLite<K, V> {
public MapFieldLite<K, V> copy() {
return new MapFieldLite<K, V>(copy(mapData));
}
+
+ /**
+ * Makes this field immutable. All subsequent modifications will throw an
+ * {@link UnsupportedOperationException}.
+ */
+ public void makeImmutable() {
+ isMutable = false;
+ }
+
+ /**
+ * Returns whether this field can be modified.
+ */
+ public boolean isMutable() {
+ return isMutable;
+ }
+
+ @Override
+ public void ensureMutable() {
+ if (!isMutable()) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * An internal map that checks for mutability before delegating.
+ */
+ static class MutatabilityAwareMap<K, V> implements Map<K, V> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Map<K, V> delegate;
+
+ MutatabilityAwareMap(MutabilityOracle mutabilityOracle, Map<K, V> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return delegate.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return delegate.containsValue(value);
+ }
+
+ @Override
+ public V get(Object key) {
+ return delegate.get(key);
+ }
+
+ @Override
+ public V put(K key, V value) {
+ mutabilityOracle.ensureMutable();
+ return delegate.put(key, value);
+ }
+
+ @Override
+ public V remove(Object key) {
+ mutabilityOracle.ensureMutable();
+ return delegate.remove(key);
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ mutabilityOracle.ensureMutable();
+ delegate.putAll(m);
+ }
+
+ @Override
+ public void clear() {
+ mutabilityOracle.ensureMutable();
+ delegate.clear();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ return new MutatabilityAwareSet<K>(mutabilityOracle, delegate.keySet());
+ }
+
+ @Override
+ public Collection<V> values() {
+ return new MutatabilityAwareCollection<V>(mutabilityOracle, delegate.values());
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<K, V>> entrySet() {
+ return new MutatabilityAwareSet<Entry<K, V>>(mutabilityOracle, delegate.entrySet());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+ }
+
+ /**
+ * An internal collection that checks for mutability before delegating.
+ */
+ private static class MutatabilityAwareCollection<E> implements Collection<E> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Collection<E> delegate;
+
+ MutatabilityAwareCollection(MutabilityOracle mutabilityOracle, Collection<E> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return delegate.contains(o);
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator());
+ }
+
+ @Override
+ public Object[] toArray() {
+ return delegate.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return delegate.toArray(a);
+ }
+
+ @Override
+ public boolean add(E e) {
+ // Unsupported operation in the delegate.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ mutabilityOracle.ensureMutable();
+ return delegate.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return delegate.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ // Unsupported operation in the delegate.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ mutabilityOracle.ensureMutable();
+ delegate.clear();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+ }
+
+ /**
+ * An internal set that checks for mutability before delegating.
+ */
+ private static class MutatabilityAwareSet<E> implements Set<E> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Set<E> delegate;
+
+ MutatabilityAwareSet(MutabilityOracle mutabilityOracle, Set<E> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return delegate.contains(o);
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator());
+ }
+
+ @Override
+ public Object[] toArray() {
+ return delegate.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return delegate.toArray(a);
+ }
+
+ @Override
+ public boolean add(E e) {
+ mutabilityOracle.ensureMutable();
+ return delegate.add(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ mutabilityOracle.ensureMutable();
+ return delegate.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return delegate.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.addAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.retainAll(c);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.removeAll(c);
+ }
+
+ @Override
+ public void clear() {
+ mutabilityOracle.ensureMutable();
+ delegate.clear();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+ }
+
+ /**
+ * An internal iterator that checks for mutability before delegating.
+ */
+ private static class MutatabilityAwareIterator<E> implements Iterator<E> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Iterator<E> delegate;
+
+ MutatabilityAwareIterator(MutabilityOracle mutabilityOracle, Iterator<E> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return delegate.hasNext();
+ }
+
+ @Override
+ public E next() {
+ return delegate.next();
+ }
+
+ @Override
+ public void remove() {
+ mutabilityOracle.ensureMutable();
+ delegate.remove();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return delegate.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/MutabilityOracle.java b/java/src/main/java/com/google/protobuf/MutabilityOracle.java
new file mode 100644
index 00000000..82b723c9
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/MutabilityOracle.java
@@ -0,0 +1,48 @@
+// 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;
+
+/**
+ * Verifies that an object is mutable, throwing if not.
+ */
+interface MutabilityOracle {
+ static final MutabilityOracle IMMUTABLE = new MutabilityOracle() {
+ @Override
+ public void ensureMutable() {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ /**
+ * Throws an {@link UnsupportedOperationException} if not mutable.
+ */
+ void ensureMutable();
+}
diff --git a/java/src/main/java/com/google/protobuf/ProtobufArrayList.java b/java/src/main/java/com/google/protobuf/ProtobufArrayList.java
new file mode 100644
index 00000000..759368c9
--- /dev/null
+++ b/java/src/main/java/com/google/protobuf/ProtobufArrayList.java
@@ -0,0 +1,95 @@
+// 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.Internal.ProtobufList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implements {@link ProtobufList} for non-primitive and {@link String} types.
+ */
+class ProtobufArrayList<E> extends AbstractProtobufList<E> {
+
+ private static final ProtobufArrayList<Object> EMPTY_LIST = new ProtobufArrayList<Object>();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed safe by runtime.
+ public static <E> ProtobufArrayList<E> emptyList() {
+ return (ProtobufArrayList<E>) EMPTY_LIST;
+ }
+
+ private final List<E> list;
+
+ ProtobufArrayList() {
+ list = new ArrayList<E>();
+ }
+
+ ProtobufArrayList(List<E> toCopy) {
+ list = new ArrayList<E>(toCopy);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ ensureIsMutable();
+ list.add(index, element);
+ modCount++;
+ }
+
+ @Override
+ public E get(int index) {
+ return list.get(index);
+ }
+
+ @Override
+ public E remove(int index) {
+ ensureIsMutable();
+ E toReturn = list.remove(index);
+ modCount++;
+ return toReturn;
+ }
+
+ @Override
+ public E set(int index, E element) {
+ ensureIsMutable();
+ E toReturn = list.set(index, element);
+ modCount++;
+ return toReturn;
+ }
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+}
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index dd2b4600..a79ce559 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -1725,7 +1725,7 @@ public final class TextFormat {
* {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with
* "\x") are also recognized.
*/
- static ByteString unescapeBytes(final CharSequence charString)
+ public static ByteString unescapeBytes(final CharSequence charString)
throws InvalidEscapeSequenceException {
// First convert the Java character sequence to UTF-8 bytes.
ByteString input = ByteString.copyFromUtf8(charString.toString());
@@ -1808,7 +1808,7 @@ public final class TextFormat {
* Thrown by {@link TextFormat#unescapeBytes} and
* {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
*/
- static class InvalidEscapeSequenceException extends IOException {
+ public static class InvalidEscapeSequenceException extends IOException {
private static final long serialVersionUID = -8164033650142593304L;
InvalidEscapeSequenceException(final String description) {
diff --git a/java/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/java/src/test/java/com/google/protobuf/BooleanArrayListTest.java
new file mode 100644
index 00000000..df89c263
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/BooleanArrayListTest.java
@@ -0,0 +1,473 @@
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link BooleanArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class BooleanArrayListTest extends TestCase {
+
+ private static final BooleanArrayList UNARY_LIST = newImmutableBooleanArrayList(true);
+ private static final BooleanArrayList TERTIARY_LIST =
+ newImmutableBooleanArrayList(true, true, false);
+
+ private BooleanArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new BooleanArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(BooleanArrayList.emptyList(), BooleanArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(BooleanArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addBoolean(true);
+ list.addBoolean(false);
+ list.addBoolean(true);
+ list.addBoolean(true);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ BooleanArrayList copy = new BooleanArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new BooleanArrayList(BooleanArrayList.emptyList());
+ assertEquals(BooleanArrayList.emptyList(), copy);
+
+ copy = new BooleanArrayList(asList(false, false, true));
+ assertEquals(asList(false, false, true), copy);
+
+ copy = new BooleanArrayList(Collections.<Boolean>emptyList());
+ assertEquals(BooleanArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(true, false, false, true));
+ Iterator<Boolean> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(true, (boolean) list.get(0));
+ assertEquals(true, (boolean) iterator.next());
+ list.set(0, true);
+ assertEquals(false, (boolean) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, false);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(true, (boolean) TERTIARY_LIST.get(0));
+ assertEquals(true, (boolean) TERTIARY_LIST.get(1));
+ assertEquals(false, (boolean) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetInt() {
+ assertEquals(true, TERTIARY_LIST.getBoolean(0));
+ assertEquals(true, TERTIARY_LIST.getBoolean(1));
+ assertEquals(false, TERTIARY_LIST.getBoolean(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, BooleanArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addBoolean(true);
+ list.addBoolean(false);
+ list.addBoolean(false);
+ list.addBoolean(false);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(true);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addBoolean(false);
+ list.addBoolean(false);
+
+ assertEquals(false, (boolean) list.set(0, true));
+ assertEquals(true, list.getBoolean(0));
+
+ assertEquals(false, (boolean) list.set(1, false));
+ assertEquals(false, list.getBoolean(1));
+
+ try {
+ list.set(-1, true);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetInt() {
+ list.addBoolean(true);
+ list.addBoolean(true);
+
+ assertEquals(true, list.setBoolean(0, false));
+ assertEquals(false, list.getBoolean(0));
+
+ assertEquals(true, list.setBoolean(1, false));
+ assertEquals(false, list.getBoolean(1));
+
+ try {
+ list.setBoolean(-1, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setBoolean(2, true);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(true));
+ assertEquals(asList(true), list);
+
+ assertTrue(list.add(false));
+ list.add(0, false);
+ assertEquals(asList(false, true, false), list);
+
+ list.add(0, false);
+ list.add(0, true);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(true);
+ }
+ assertEquals(asList(true, false, false, true, false, true, true, true, true, true, true), list);
+
+ try {
+ list.add(-1, false);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, true);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddInt() {
+ assertEquals(0, list.size());
+
+ list.addBoolean(true);
+ assertEquals(asList(true), list);
+
+ list.addBoolean(false);
+ assertEquals(asList(true, false), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(false)));
+ assertEquals(1, list.size());
+ assertEquals(false, (boolean) list.get(0));
+ assertEquals(false, list.getBoolean(0));
+
+ assertTrue(list.addAll(asList(true, false, false, false, true)));
+ assertEquals(asList(false, true, false, false, false, true), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(false, true, false, false, false, true, true, true, false), list);
+
+ assertFalse(list.addAll(Collections.<Boolean>emptyList()));
+ assertFalse(list.addAll(BooleanArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(true, (boolean) list.remove(0));
+ assertEquals(asList(true, false), list);
+
+ assertTrue(list.remove(Boolean.TRUE));
+ assertEquals(asList(false), list);
+
+ assertFalse(list.remove(Boolean.TRUE));
+ assertEquals(asList(false), list);
+
+ assertEquals(false, (boolean) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(BooleanArrayList list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(false);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(false));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new BooleanArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(true));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addBoolean(true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setBoolean(0, false);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static BooleanArrayList newImmutableBooleanArrayList(boolean... elements) {
+ BooleanArrayList list = new BooleanArrayList();
+ for (boolean element : elements) {
+ list.addBoolean(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
index 6cfa18d5..edd7fc46 100644
--- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -56,6 +56,7 @@ import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestReservedFields;
import protobuf_unittest.UnittestProto.TestService;
import junit.framework.TestCase;
@@ -687,6 +688,9 @@ public class DescriptorsTest extends TestCase {
assertEquals(4, oneofDescriptor.getFieldCount());
assertSame(oneofDescriptor.getField(1), field);
+
+ assertEquals(4, oneofDescriptor.getFields().size());
+ assertEquals(oneofDescriptor.getFields().get(1), field);
}
public void testMessageDescriptorExtensions() throws Exception {
@@ -702,6 +706,19 @@ public class DescriptorsTest extends TestCase {
assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143));
}
+ public void testReservedFields() {
+ Descriptor d = TestReservedFields.getDescriptor();
+ assertTrue(d.isReservedNumber(2));
+ assertFalse(d.isReservedNumber(8));
+ assertTrue(d.isReservedNumber(9));
+ assertTrue(d.isReservedNumber(10));
+ assertTrue(d.isReservedNumber(11));
+ assertFalse(d.isReservedNumber(12));
+ assertFalse(d.isReservedName("foo"));
+ assertTrue(d.isReservedName("bar"));
+ assertTrue(d.isReservedName("baz"));
+ }
+
public void testToString() {
assertEquals("protobuf_unittest.TestAllTypes.optional_uint64",
UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber(
diff --git a/java/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/java/src/test/java/com/google/protobuf/DoubleArrayListTest.java
new file mode 100644
index 00000000..e7a73d70
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/DoubleArrayListTest.java
@@ -0,0 +1,473 @@
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link DoubleArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class DoubleArrayListTest extends TestCase {
+
+ private static final DoubleArrayList UNARY_LIST = newImmutableDoubleArrayList(1);
+ private static final DoubleArrayList TERTIARY_LIST =
+ newImmutableDoubleArrayList(1, 2, 3);
+
+ private DoubleArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new DoubleArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(DoubleArrayList.emptyList(), DoubleArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(DoubleArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addDouble(2);
+ list.addDouble(4);
+ list.addDouble(6);
+ list.addDouble(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ DoubleArrayList copy = new DoubleArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new DoubleArrayList(DoubleArrayList.emptyList());
+ assertEquals(DoubleArrayList.emptyList(), copy);
+
+ copy = new DoubleArrayList(asList(1D, 2D, 3D));
+ assertEquals(asList(1D, 2D, 3D), copy);
+
+ copy = new DoubleArrayList(Collections.<Double>emptyList());
+ assertEquals(DoubleArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1D, 2D, 3D, 4D));
+ Iterator<Double> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1D, (double) list.get(0));
+ assertEquals(1D, (double) iterator.next());
+ list.set(0, 1D);
+ assertEquals(2D, (double) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0D);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1D, (double) TERTIARY_LIST.get(0));
+ assertEquals(2D, (double) TERTIARY_LIST.get(1));
+ assertEquals(3D, (double) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetInt() {
+ assertEquals(1D, TERTIARY_LIST.getDouble(0));
+ assertEquals(2D, TERTIARY_LIST.getDouble(1));
+ assertEquals(3D, TERTIARY_LIST.getDouble(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, DoubleArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addDouble(2);
+ list.addDouble(4);
+ list.addDouble(6);
+ list.addDouble(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16D);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addDouble(2);
+ list.addDouble(4);
+
+ assertEquals(2D, (double) list.set(0, 0D));
+ assertEquals(0D, list.getDouble(0));
+
+ assertEquals(4D, (double) list.set(1, 0D));
+ assertEquals(0D, list.getDouble(1));
+
+ try {
+ list.set(-1, 0D);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0D);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetInt() {
+ list.addDouble(2);
+ list.addDouble(4);
+
+ assertEquals(2D, list.setDouble(0, 0));
+ assertEquals(0D, list.getDouble(0));
+
+ assertEquals(4D, list.setDouble(1, 0));
+ assertEquals(0D, list.getDouble(1));
+
+ try {
+ list.setDouble(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setDouble(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2D));
+ assertEquals(asList(2D), list);
+
+ assertTrue(list.add(3D));
+ list.add(0, 4D);
+ assertEquals(asList(4D, 2D, 3D), list);
+
+ list.add(0, 1D);
+ list.add(0, 0D);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Double.valueOf(5 + i));
+ }
+ assertEquals(asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), list);
+
+ try {
+ list.add(-1, 5D);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5D);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddInt() {
+ assertEquals(0, list.size());
+
+ list.addDouble(2);
+ assertEquals(asList(2D), list);
+
+ list.addDouble(3);
+ assertEquals(asList(2D, 3D), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1D)));
+ assertEquals(1, list.size());
+ assertEquals(1D, (double) list.get(0));
+ assertEquals(1D, list.getDouble(0));
+
+ assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D)));
+ assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D, 1D, 2D, 3D), list);
+
+ assertFalse(list.addAll(Collections.<Double>emptyList()));
+ assertFalse(list.addAll(DoubleArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1D, (double) list.remove(0));
+ assertEquals(asList(2D, 3D), list);
+
+ assertTrue(list.remove(Double.valueOf(3)));
+ assertEquals(asList(2D), list);
+
+ assertFalse(list.remove(Double.valueOf(3)));
+ assertEquals(asList(2D), list);
+
+ assertEquals(2D, (double) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(DoubleArrayList list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new DoubleArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addDouble(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setDouble(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static DoubleArrayList newImmutableDoubleArrayList(double... elements) {
+ DoubleArrayList list = new DoubleArrayList();
+ for (double element : elements) {
+ list.addDouble(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/FloatArrayListTest.java b/java/src/test/java/com/google/protobuf/FloatArrayListTest.java
new file mode 100644
index 00000000..8f3e93dc
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/FloatArrayListTest.java
@@ -0,0 +1,473 @@
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link FloatArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class FloatArrayListTest extends TestCase {
+
+ private static final FloatArrayList UNARY_LIST = newImmutableFloatArrayList(1);
+ private static final FloatArrayList TERTIARY_LIST =
+ newImmutableFloatArrayList(1, 2, 3);
+
+ private FloatArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new FloatArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(FloatArrayList.emptyList(), FloatArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(FloatArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addFloat(2);
+ list.addFloat(4);
+ list.addFloat(6);
+ list.addFloat(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ FloatArrayList copy = new FloatArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new FloatArrayList(FloatArrayList.emptyList());
+ assertEquals(FloatArrayList.emptyList(), copy);
+
+ copy = new FloatArrayList(asList(1F, 2F, 3F));
+ assertEquals(asList(1F, 2F, 3F), copy);
+
+ copy = new FloatArrayList(Collections.<Float>emptyList());
+ assertEquals(FloatArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1F, 2F, 3F, 4F));
+ Iterator<Float> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1F, (float) list.get(0));
+ assertEquals(1F, (float) iterator.next());
+ list.set(0, 1F);
+ assertEquals(2F, (float) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0F);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1F, (float) TERTIARY_LIST.get(0));
+ assertEquals(2F, (float) TERTIARY_LIST.get(1));
+ assertEquals(3F, (float) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetFloat() {
+ assertEquals(1F, TERTIARY_LIST.getFloat(0));
+ assertEquals(2F, TERTIARY_LIST.getFloat(1));
+ assertEquals(3F, TERTIARY_LIST.getFloat(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, FloatArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addFloat(2);
+ list.addFloat(4);
+ list.addFloat(6);
+ list.addFloat(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16F);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addFloat(2);
+ list.addFloat(4);
+
+ assertEquals(2F, (float) list.set(0, 0F));
+ assertEquals(0F, list.getFloat(0));
+
+ assertEquals(4F, (float) list.set(1, 0F));
+ assertEquals(0F, list.getFloat(1));
+
+ try {
+ list.set(-1, 0F);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0F);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetFloat() {
+ list.addFloat(2);
+ list.addFloat(4);
+
+ assertEquals(2F, list.setFloat(0, 0));
+ assertEquals(0F, list.getFloat(0));
+
+ assertEquals(4F, list.setFloat(1, 0));
+ assertEquals(0F, list.getFloat(1));
+
+ try {
+ list.setFloat(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setFloat(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2F));
+ assertEquals(asList(2F), list);
+
+ assertTrue(list.add(3F));
+ list.add(0, 4F);
+ assertEquals(asList(4F, 2F, 3F), list);
+
+ list.add(0, 1F);
+ list.add(0, 0F);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Float.valueOf(5 + i));
+ }
+ assertEquals(asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), list);
+
+ try {
+ list.add(-1, 5F);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5F);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddFloat() {
+ assertEquals(0, list.size());
+
+ list.addFloat(2);
+ assertEquals(asList(2F), list);
+
+ list.addFloat(3);
+ assertEquals(asList(2F, 3F), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1F)));
+ assertEquals(1, list.size());
+ assertEquals(1F, (float) list.get(0));
+ assertEquals(1F, list.getFloat(0));
+
+ assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F)));
+ assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F, 1F, 2F, 3F), list);
+
+ assertFalse(list.addAll(Collections.<Float>emptyList()));
+ assertFalse(list.addAll(FloatArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1F, (float) list.remove(0));
+ assertEquals(asList(2F, 3F), list);
+
+ assertTrue(list.remove(Float.valueOf(3)));
+ assertEquals(asList(2F), list);
+
+ assertFalse(list.remove(Float.valueOf(3)));
+ assertEquals(asList(2F), list);
+
+ assertEquals(2F, (float) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(FloatArrayList list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new FloatArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addFloat(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setFloat(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static FloatArrayList newImmutableFloatArrayList(int... elements) {
+ FloatArrayList list = new FloatArrayList();
+ for (int element : elements) {
+ list.addFloat(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/IntArrayListTest.java b/java/src/test/java/com/google/protobuf/IntArrayListTest.java
new file mode 100644
index 00000000..3733eb30
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/IntArrayListTest.java
@@ -0,0 +1,473 @@
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link IntArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class IntArrayListTest extends TestCase {
+
+ private static final IntArrayList UNARY_LIST = newImmutableIntArrayList(1);
+ private static final IntArrayList TERTIARY_LIST =
+ newImmutableIntArrayList(1, 2, 3);
+
+ private IntArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new IntArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(IntArrayList.emptyList(), IntArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(IntArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addInt(2);
+ list.addInt(4);
+ list.addInt(6);
+ list.addInt(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ IntArrayList copy = new IntArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new IntArrayList(IntArrayList.emptyList());
+ assertEquals(IntArrayList.emptyList(), copy);
+
+ copy = new IntArrayList(asList(1, 2, 3));
+ assertEquals(asList(1, 2, 3), copy);
+
+ copy = new IntArrayList(Collections.<Integer>emptyList());
+ assertEquals(IntArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1, 2, 3, 4));
+ Iterator<Integer> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, (int) iterator.next());
+ list.set(0, 1);
+ assertEquals(2, (int) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1, (int) TERTIARY_LIST.get(0));
+ assertEquals(2, (int) TERTIARY_LIST.get(1));
+ assertEquals(3, (int) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetInt() {
+ assertEquals(1, TERTIARY_LIST.getInt(0));
+ assertEquals(2, TERTIARY_LIST.getInt(1));
+ assertEquals(3, TERTIARY_LIST.getInt(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, IntArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addInt(2);
+ list.addInt(4);
+ list.addInt(6);
+ list.addInt(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addInt(2);
+ list.addInt(4);
+
+ assertEquals(2, (int) list.set(0, 0));
+ assertEquals(0, list.getInt(0));
+
+ assertEquals(4, (int) list.set(1, 0));
+ assertEquals(0, list.getInt(1));
+
+ try {
+ list.set(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetInt() {
+ list.addInt(2);
+ list.addInt(4);
+
+ assertEquals(2, list.setInt(0, 0));
+ assertEquals(0, list.getInt(0));
+
+ assertEquals(4, list.setInt(1, 0));
+ assertEquals(0, list.getInt(1));
+
+ try {
+ list.setInt(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setInt(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2));
+ assertEquals(asList(2), list);
+
+ assertTrue(list.add(3));
+ list.add(0, 4);
+ assertEquals(asList(4, 2, 3), list);
+
+ list.add(0, 1);
+ list.add(0, 0);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(5 + i);
+ }
+ assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list);
+
+ try {
+ list.add(-1, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddInt() {
+ assertEquals(0, list.size());
+
+ list.addInt(2);
+ assertEquals(asList(2), list);
+
+ list.addInt(3);
+ assertEquals(asList(2, 3), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1)));
+ assertEquals(1, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, list.getInt(0));
+
+ assertTrue(list.addAll(asList(2, 3, 4, 5, 6)));
+ assertEquals(asList(1, 2, 3, 4, 5, 6), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list);
+
+ assertFalse(list.addAll(Collections.<Integer>emptyList()));
+ assertFalse(list.addAll(IntArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1, (int) list.remove(0));
+ assertEquals(asList(2, 3), list);
+
+ assertTrue(list.remove(Integer.valueOf(3)));
+ assertEquals(asList(2), list);
+
+ assertFalse(list.remove(Integer.valueOf(3)));
+ assertEquals(asList(2), list);
+
+ assertEquals(2, (int) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(IntArrayList list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new IntArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addInt(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setInt(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static IntArrayList newImmutableIntArrayList(int... elements) {
+ IntArrayList list = new IntArrayList();
+ for (int element : elements) {
+ list.addInt(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
index f3012b96..0f42ac50 100644
--- a/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -30,9 +30,13 @@
package com.google.protobuf;
+import static java.util.Arrays.asList;
+
import junit.framework.TestCase;
import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
import java.util.List;
/**
@@ -171,4 +175,188 @@ public class LazyStringArrayListTest extends TestCase {
assertSame(BYTE_STRING_B, list2.getByteString(1));
assertSame(BYTE_STRING_C, list2.getByteString(2));
}
+
+ public void testModificationWithIteration() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.addAll(asList(STRING_A, STRING_B, STRING_C));
+ Iterator<String> iterator = list.iterator();
+ assertEquals(3, list.size());
+ assertEquals(STRING_A, list.get(0));
+ assertEquals(STRING_A, iterator.next());
+
+ // Does not structurally modify.
+ iterator = list.iterator();
+ list.set(0, STRING_B);
+ iterator.next();
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, STRING_C);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testMakeImmutable() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(STRING_B);
+ list.add(STRING_C);
+ list.makeImmutable();
+ assertGenericListImmutable(list, STRING_A);
+
+ // LazyStringArrayList has extra methods not covered in the generic
+ // assertion.
+
+ try {
+ list.add(BYTE_STRING_A.toByteArray());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAllByteArray(asList(BYTE_STRING_A.toByteArray()));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAllByteString(asList(BYTE_STRING_A));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.mergeFrom(new LazyStringArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, BYTE_STRING_A.toByteArray());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ public void testImmutabilityPropagation() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.makeImmutable();
+
+ assertGenericListImmutable(list.asByteStringList(), BYTE_STRING_A);
+
+ // Arrays use reference equality so need to retrieve the underlying value
+ // to properly test deep immutability.
+ List<byte[]> byteArrayList = list.asByteArrayList();
+ assertGenericListImmutable(byteArrayList, byteArrayList.get(0));
+ }
+
+ private static <T> void assertGenericListImmutable(List<T> list, T value) {
+ try {
+ list.add(value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(asList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(asList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java
index 4d8037fc..8c3b5e5c 100644
--- a/java/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteTest.java
@@ -30,9 +30,18 @@
package com.google.protobuf;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
import com.google.protobuf.UnittestLite;
-import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
import junit.framework.TestCase;
@@ -149,13 +158,1302 @@ public class LiteTest extends TestCase {
public void testClone() {
TestAllTypesLite.Builder expected = TestAllTypesLite.newBuilder()
.setOptionalInt32(123);
- assertEquals(
- expected.getOptionalInt32(), expected.clone().getOptionalInt32());
+ assertEquals(
+ expected.getOptionalInt32(), expected.clone().getOptionalInt32());
- TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder()
- .setExtension(UnittestLite.optionalInt32ExtensionLite, 123);
- assertEquals(
- expected2.getExtension(UnittestLite.optionalInt32ExtensionLite),
- expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite));
+ TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123);
+ assertEquals(
+ expected2.getExtension(UnittestLite.optionalInt32ExtensionLite),
+ expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite));
+ }
+
+ public void testAddAll() {
+ try {
+ TestAllTypesLite.newBuilder()
+ .addAllRepeatedBytes(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+ }
+
+ public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+ // Since builders are implemented as a thin wrapper around a message
+ // instance, we attempt to verify that we can't cause the builder to modify
+ // a produced message.
+
+ TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+ TestAllTypesLite message = builder.build();
+ TestAllTypesLite messageAfterBuild;
+ builder.setOptionalBool(true);
+ assertEquals(false, message.getOptionalBool());
+ assertEquals(true, builder.getOptionalBool());
+ messageAfterBuild = builder.build();
+ assertEquals(true, messageAfterBuild.getOptionalBool());
+ assertEquals(false, message.getOptionalBool());
+ builder.clearOptionalBool();
+ assertEquals(false, builder.getOptionalBool());
+ assertEquals(true, messageAfterBuild.getOptionalBool());
+
+ message = builder.build();
+ builder.setOptionalBytes(ByteString.copyFromUtf8("hi"));
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ assertEquals(ByteString.copyFromUtf8("hi"), builder.getOptionalBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ builder.clearOptionalBytes();
+ assertEquals(ByteString.EMPTY, builder.getOptionalBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+
+ message = builder.build();
+ builder.setOptionalCord("hi");
+ assertEquals("", message.getOptionalCord());
+ assertEquals("hi", builder.getOptionalCord());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalCord());
+ assertEquals("", message.getOptionalCord());
+ builder.clearOptionalCord();
+ assertEquals("", builder.getOptionalCord());
+ assertEquals("hi", messageAfterBuild.getOptionalCord());
+
+ message = builder.build();
+ builder.setOptionalCordBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+ assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalCordBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalCordBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+ builder.clearOptionalCord();
+ assertEquals(ByteString.EMPTY, builder.getOptionalCordBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalCordBytes());
+
+ message = builder.build();
+ builder.setOptionalDouble(1);
+ assertEquals(0D, message.getOptionalDouble());
+ assertEquals(1D, builder.getOptionalDouble());
+ messageAfterBuild = builder.build();
+ assertEquals(1D, messageAfterBuild.getOptionalDouble());
+ assertEquals(0D, message.getOptionalDouble());
+ builder.clearOptionalDouble();
+ assertEquals(0D, builder.getOptionalDouble());
+ assertEquals(1D, messageAfterBuild.getOptionalDouble());
+
+ message = builder.build();
+ builder.setOptionalFixed32(1);
+ assertEquals(0, message.getOptionalFixed32());
+ assertEquals(1, builder.getOptionalFixed32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalFixed32());
+ assertEquals(0, message.getOptionalFixed32());
+ builder.clearOptionalFixed32();
+ assertEquals(0, builder.getOptionalFixed32());
+ assertEquals(1, messageAfterBuild.getOptionalFixed32());
+
+ message = builder.build();
+ builder.setOptionalFixed64(1);
+ assertEquals(0L, message.getOptionalFixed64());
+ assertEquals(1L, builder.getOptionalFixed64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+ assertEquals(0L, message.getOptionalFixed64());
+ builder.clearOptionalFixed64();
+ assertEquals(0L, builder.getOptionalFixed64());
+ assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+
+ message = builder.build();
+ builder.setOptionalFloat(1);
+ assertEquals(0F, message.getOptionalFloat());
+ assertEquals(1F, builder.getOptionalFloat());
+ messageAfterBuild = builder.build();
+ assertEquals(1F, messageAfterBuild.getOptionalFloat());
+ assertEquals(0F, message.getOptionalFloat());
+ builder.clearOptionalFloat();
+ assertEquals(0F, builder.getOptionalFloat());
+ assertEquals(1F, messageAfterBuild.getOptionalFloat());
+
+ message = builder.build();
+ builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR, builder.getOptionalForeignEnum());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+ builder.clearOptionalForeignEnum();
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, builder.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getOptionalForeignEnum());
+
+ message = builder.build();
+ ForeignMessageLite foreignMessage = ForeignMessageLite.newBuilder()
+ .setC(1)
+ .build();
+ builder.setOptionalForeignMessage(foreignMessage);
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ assertEquals(foreignMessage, builder.getOptionalForeignMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ builder.clearOptionalForeignMessage();
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getOptionalForeignMessage());
+ assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+
+ message = builder.build();
+ ForeignMessageLite.Builder foreignMessageBuilder =
+ ForeignMessageLite.newBuilder()
+ .setC(3);
+ builder.setOptionalForeignMessage(foreignMessageBuilder);
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on foreignMessage.
+ assertEquals(3, builder.getOptionalForeignMessage().getC());
+ messageAfterBuild = builder.build();
+ assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ builder.clearOptionalForeignMessage();
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getOptionalForeignMessage());
+ assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC());
+
+ message = builder.build();
+ OptionalGroup optionalGroup = OptionalGroup.newBuilder()
+ .setA(1)
+ .build();
+ builder.setOptionalGroup(optionalGroup);
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ assertEquals(optionalGroup, builder.getOptionalGroup());
+ messageAfterBuild = builder.build();
+ assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ builder.clearOptionalGroup();
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+ assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+
+ message = builder.build();
+ OptionalGroup.Builder optionalGroupBuilder = OptionalGroup.newBuilder()
+ .setA(3);
+ builder.setOptionalGroup(optionalGroupBuilder);
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on optionalGroup.
+ assertEquals(3, builder.getOptionalGroup().getA());
+ messageAfterBuild = builder.build();
+ assertEquals(3, messageAfterBuild.getOptionalGroup().getA());
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ builder.clearOptionalGroup();
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+ assertEquals(3, messageAfterBuild.getOptionalGroup().getA());
+
+ message = builder.build();
+ builder.setOptionalInt32(1);
+ assertEquals(0, message.getOptionalInt32());
+ assertEquals(1, builder.getOptionalInt32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalInt32());
+ assertEquals(0, message.getOptionalInt32());
+ builder.clearOptionalInt32();
+ assertEquals(0, builder.getOptionalInt32());
+ assertEquals(1, messageAfterBuild.getOptionalInt32());
+
+ message = builder.build();
+ builder.setOptionalInt64(1);
+ assertEquals(0L, message.getOptionalInt64());
+ assertEquals(1L, builder.getOptionalInt64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalInt64());
+ assertEquals(0L, message.getOptionalInt64());
+ builder.clearOptionalInt64();
+ assertEquals(0L, builder.getOptionalInt64());
+ assertEquals(1L, messageAfterBuild.getOptionalInt64());
+
+ message = builder.build();
+ NestedMessage nestedMessage = NestedMessage.newBuilder()
+ .setBb(1)
+ .build();
+ builder.setOptionalLazyMessage(nestedMessage);
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ assertEquals(nestedMessage, builder.getOptionalLazyMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ builder.clearOptionalLazyMessage();
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+ assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+
+ message = builder.build();
+ NestedMessage.Builder nestedMessageBuilder =
+ NestedMessage.newBuilder()
+ .setBb(3);
+ builder.setOptionalLazyMessage(nestedMessageBuilder);
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property.
+ assertEquals(3, builder.getOptionalLazyMessage().getBb());
+ messageAfterBuild = builder.build();
+ assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb());
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ builder.clearOptionalLazyMessage();
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+ assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb());
+
+ message = builder.build();
+ builder.setOptionalSfixed32(1);
+ assertEquals(0, message.getOptionalSfixed32());
+ assertEquals(1, builder.getOptionalSfixed32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+ assertEquals(0, message.getOptionalSfixed32());
+ builder.clearOptionalSfixed32();
+ assertEquals(0, builder.getOptionalSfixed32());
+ assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+
+ message = builder.build();
+ builder.setOptionalSfixed64(1);
+ assertEquals(0L, message.getOptionalSfixed64());
+ assertEquals(1L, builder.getOptionalSfixed64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+ assertEquals(0L, message.getOptionalSfixed64());
+ builder.clearOptionalSfixed64();
+ assertEquals(0L, builder.getOptionalSfixed64());
+ assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+
+ message = builder.build();
+ builder.setOptionalSint32(1);
+ assertEquals(0, message.getOptionalSint32());
+ assertEquals(1, builder.getOptionalSint32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalSint32());
+ builder.clearOptionalSint32();
+ assertEquals(0, builder.getOptionalSint32());
+ assertEquals(1, messageAfterBuild.getOptionalSint32());
+
+ message = builder.build();
+ builder.setOptionalSint64(1);
+ assertEquals(0L, message.getOptionalSint64());
+ assertEquals(1L, builder.getOptionalSint64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalSint64());
+ assertEquals(0L, message.getOptionalSint64());
+ builder.clearOptionalSint64();
+ assertEquals(0L, builder.getOptionalSint64());
+ assertEquals(1L, messageAfterBuild.getOptionalSint64());
+
+ message = builder.build();
+ builder.setOptionalString("hi");
+ assertEquals("", message.getOptionalString());
+ assertEquals("hi", builder.getOptionalString());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalString());
+ assertEquals("", message.getOptionalString());
+ builder.clearOptionalString();
+ assertEquals("", builder.getOptionalString());
+ assertEquals("hi", messageAfterBuild.getOptionalString());
+
+ message = builder.build();
+ builder.setOptionalStringBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"), builder.getOptionalStringBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+ builder.clearOptionalString();
+ assertEquals(ByteString.EMPTY, builder.getOptionalStringBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringBytes());
+
+ message = builder.build();
+ builder.setOptionalStringPiece("hi");
+ assertEquals("", message.getOptionalStringPiece());
+ assertEquals("hi", builder.getOptionalStringPiece());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+ assertEquals("", message.getOptionalStringPiece());
+ builder.clearOptionalStringPiece();
+ assertEquals("", builder.getOptionalStringPiece());
+ assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+
+ message = builder.build();
+ builder.setOptionalStringPieceBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"), builder.getOptionalStringPieceBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringPieceBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+ builder.clearOptionalStringPiece();
+ assertEquals(ByteString.EMPTY, builder.getOptionalStringPieceBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringPieceBytes());
+
+ message = builder.build();
+ builder.setOptionalUint32(1);
+ assertEquals(0, message.getOptionalUint32());
+ assertEquals(1, builder.getOptionalUint32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalUint32());
+ assertEquals(0, message.getOptionalUint32());
+ builder.clearOptionalUint32();
+ assertEquals(0, builder.getOptionalUint32());
+ assertEquals(1, messageAfterBuild.getOptionalUint32());
+
+ message = builder.build();
+ builder.setOptionalUint64(1);
+ assertEquals(0L, message.getOptionalUint64());
+ assertEquals(1L, builder.getOptionalUint64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalUint64());
+ assertEquals(0L, message.getOptionalUint64());
+ builder.clearOptionalUint64();
+ assertEquals(0L, builder.getOptionalUint64());
+ assertEquals(1L, messageAfterBuild.getOptionalUint64());
+
+ message = builder.build();
+ builder.addAllRepeatedBool(singletonList(true));
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ assertEquals(singletonList(true), builder.getRepeatedBoolList());
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBool();
+ assertEquals(emptyList(), builder.getRepeatedBoolList());
+ assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+ message = builder.build();
+ builder.addAllRepeatedBytes(singletonList(ByteString.copyFromUtf8("hi")));
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ builder.getRepeatedBytesList());
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBytes();
+ assertEquals(emptyList(), builder.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ messageAfterBuild.getRepeatedBytesList());
+
+ message = builder.build();
+ builder.addAllRepeatedCord(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedCord();
+ assertEquals(emptyList(), builder.getRepeatedCordList());
+ assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+ message = builder.build();
+ builder.addAllRepeatedDouble(singletonList(1D));
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedDouble();
+ assertEquals(emptyList(), builder.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+ message = builder.build();
+ builder.addAllRepeatedFixed32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed32();
+ assertEquals(emptyList(), builder.getRepeatedFixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+ message = builder.build();
+ builder.addAllRepeatedFixed64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed64();
+ assertEquals(emptyList(), builder.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+ message = builder.build();
+ builder.addAllRepeatedFloat(singletonList(1F));
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFloat();
+ assertEquals(emptyList(), builder.getRepeatedFloatList());
+ assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+ message = builder.build();
+ builder.addAllRepeatedForeignEnum(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR));
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ builder.getRepeatedForeignEnumList());
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignEnum();
+ assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ messageAfterBuild.getRepeatedForeignEnumList());
+
+ message = builder.build();
+ builder.addAllRepeatedForeignMessage(singletonList(foreignMessage));
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignMessage();
+ assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage),
+ messageAfterBuild.getRepeatedForeignMessageList());
+
+ message = builder.build();
+ builder.addAllRepeatedGroup(
+ singletonList(RepeatedGroup.getDefaultInstance()));
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ builder.getRepeatedGroupList());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedGroup();
+ assertEquals(emptyList(), builder.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ messageAfterBuild.getRepeatedGroupList());
+
+ message = builder.build();
+ builder.addAllRepeatedInt32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ assertEquals(singletonList(1), builder.getRepeatedInt32List());
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt32();
+ assertEquals(emptyList(), builder.getRepeatedInt32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+ message = builder.build();
+ builder.addAllRepeatedInt64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt64();
+ assertEquals(emptyList(), builder.getRepeatedInt64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+ message = builder.build();
+ builder.addAllRepeatedLazyMessage(singletonList(nestedMessage));
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedLazyMessage();
+ assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage),
+ messageAfterBuild.getRepeatedLazyMessageList());
+
+ message = builder.build();
+ builder.addAllRepeatedSfixed32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed32();
+ assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+ message = builder.build();
+ builder.addAllRepeatedSfixed64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed64();
+ assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+ assertEquals(
+ singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+ message = builder.build();
+ builder.addAllRepeatedSint32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ assertEquals(singletonList(1), builder.getRepeatedSint32List());
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint32();
+ assertEquals(emptyList(), builder.getRepeatedSint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+ message = builder.build();
+ builder.addAllRepeatedSint64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint64();
+ assertEquals(emptyList(), builder.getRepeatedSint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+ message = builder.build();
+ builder.addAllRepeatedString(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedString();
+ assertEquals(emptyList(), builder.getRepeatedStringList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+ message = builder.build();
+ builder.addAllRepeatedStringPiece(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedStringPiece();
+ assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+ message = builder.build();
+ builder.addAllRepeatedUint32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ assertEquals(singletonList(1), builder.getRepeatedUint32List());
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint32();
+ assertEquals(emptyList(), builder.getRepeatedUint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+ message = builder.build();
+ builder.addAllRepeatedUint64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint64();
+ assertEquals(emptyList(), builder.getRepeatedUint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+
+ message = builder.build();
+ builder.addRepeatedBool(true);
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ assertEquals(singletonList(true), builder.getRepeatedBoolList());
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBool();
+ assertEquals(emptyList(), builder.getRepeatedBoolList());
+ assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+ message = builder.build();
+ builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ builder.getRepeatedBytesList());
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBytes();
+ assertEquals(emptyList(), builder.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ messageAfterBuild.getRepeatedBytesList());
+
+ message = builder.build();
+ builder.addRepeatedCord("hi");
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedCord();
+ assertEquals(emptyList(), builder.getRepeatedCordList());
+ assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+ message = builder.build();
+ builder.addRepeatedDouble(1D);
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedDouble();
+ assertEquals(emptyList(), builder.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+ message = builder.build();
+ builder.addRepeatedFixed32(1);
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed32();
+ assertEquals(emptyList(), builder.getRepeatedFixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+ message = builder.build();
+ builder.addRepeatedFixed64(1L);
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed64();
+ assertEquals(emptyList(), builder.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+ message = builder.build();
+ builder.addRepeatedFloat(1F);
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFloat();
+ assertEquals(emptyList(), builder.getRepeatedFloatList());
+ assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+ message = builder.build();
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ builder.getRepeatedForeignEnumList());
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignEnum();
+ assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ messageAfterBuild.getRepeatedForeignEnumList());
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessage);
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedForeignMessage(0);
+ assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage),
+ messageAfterBuild.getRepeatedForeignMessageList());
+
+ message = builder.build();
+ builder.addRepeatedGroup(RepeatedGroup.getDefaultInstance());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ builder.getRepeatedGroupList());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedGroup(0);
+ assertEquals(emptyList(), builder.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ messageAfterBuild.getRepeatedGroupList());
+
+ message = builder.build();
+ builder.addRepeatedInt32(1);
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ assertEquals(singletonList(1), builder.getRepeatedInt32List());
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt32();
+ assertEquals(emptyList(), builder.getRepeatedInt32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+ message = builder.build();
+ builder.addRepeatedInt64(1L);
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt64();
+ assertEquals(emptyList(), builder.getRepeatedInt64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessage);
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedLazyMessage(0);
+ assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage),
+ messageAfterBuild.getRepeatedLazyMessageList());
+
+ message = builder.build();
+ builder.addRepeatedSfixed32(1);
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed32();
+ assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+ message = builder.build();
+ builder.addRepeatedSfixed64(1L);
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed64();
+ assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+ assertEquals(
+ singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+ message = builder.build();
+ builder.addRepeatedSint32(1);
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ assertEquals(singletonList(1), builder.getRepeatedSint32List());
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint32();
+ assertEquals(emptyList(), builder.getRepeatedSint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+ message = builder.build();
+ builder.addRepeatedSint64(1L);
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint64();
+ assertEquals(emptyList(), builder.getRepeatedSint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+ message = builder.build();
+ builder.addRepeatedString("hi");
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedString();
+ assertEquals(emptyList(), builder.getRepeatedStringList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+ message = builder.build();
+ builder.addRepeatedStringPiece("hi");
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedStringPiece();
+ assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+ message = builder.build();
+ builder.addRepeatedUint32(1);
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ assertEquals(singletonList(1), builder.getRepeatedUint32List());
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint32();
+ assertEquals(emptyList(), builder.getRepeatedUint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+ message = builder.build();
+ builder.addRepeatedUint64(1L);
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint64();
+ assertEquals(emptyList(), builder.getRepeatedUint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+
+ message = builder.build();
+ builder.addRepeatedBool(true);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedBoolCount());
+ builder.setRepeatedBool(0, false);
+ assertEquals(true, messageAfterBuild.getRepeatedBool(0));
+ assertEquals(false, builder.getRepeatedBool(0));
+ builder.clearRepeatedBool();
+
+ message = builder.build();
+ builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedBytesCount());
+ builder.setRepeatedBytes(0, ByteString.EMPTY);
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedBytes(0));
+ builder.clearRepeatedBytes();
+
+ message = builder.build();
+ builder.addRepeatedCord("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedCordCount());
+ builder.setRepeatedCord(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedCord(0));
+ assertEquals("", builder.getRepeatedCord(0));
+ builder.clearRepeatedCord();
+ message = builder.build();
+
+ builder.addRepeatedCordBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedCordCount());
+ builder.setRepeatedCord(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedCordBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedCordBytes(0));
+ builder.clearRepeatedCord();
+
+ message = builder.build();
+ builder.addRepeatedDouble(1D);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedDoubleCount());
+ builder.setRepeatedDouble(0, 0D);
+ assertEquals(1D, messageAfterBuild.getRepeatedDouble(0));
+ assertEquals(0D, builder.getRepeatedDouble(0));
+ builder.clearRepeatedDouble();
+
+ message = builder.build();
+ builder.addRepeatedFixed32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFixed32Count());
+ builder.setRepeatedFixed32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedFixed32(0));
+ assertEquals(0, builder.getRepeatedFixed32(0));
+ builder.clearRepeatedFixed32();
+
+ message = builder.build();
+ builder.addRepeatedFixed64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFixed64Count());
+ builder.setRepeatedFixed64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedFixed64(0));
+ assertEquals(0L, builder.getRepeatedFixed64(0));
+ builder.clearRepeatedFixed64();
+
+ message = builder.build();
+ builder.addRepeatedFloat(1F);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFloatCount());
+ builder.setRepeatedFloat(0, 0F);
+ assertEquals(1F, messageAfterBuild.getRepeatedFloat(0));
+ assertEquals(0F, builder.getRepeatedFloat(0));
+ builder.clearRepeatedFloat();
+
+ message = builder.build();
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignEnumCount());
+ builder.setRepeatedForeignEnum(0, ForeignEnumLite.FOREIGN_LITE_FOO);
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getRepeatedForeignEnum(0));
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, builder.getRepeatedForeignEnum(0));
+ builder.clearRepeatedForeignEnum();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(
+ 0, ForeignMessageLite.getDefaultInstance());
+ assertEquals(
+ foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getRepeatedForeignMessage(0));
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(
+ 0, ForeignMessageLite.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property.
+ assertEquals(3, messageAfterBuild.getRepeatedForeignMessage(0).getC());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getRepeatedForeignMessage(0));
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(0, foreignMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(0, foreignMessageBuilder);
+ assertEquals(
+ foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+ // LITE_RUNTIME doesn't implement equals so we compare on a property.
+ assertEquals(3, builder.getRepeatedForeignMessage(0).getC());
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ RepeatedGroup repeatedGroup = RepeatedGroup.newBuilder()
+ .setA(1)
+ .build();
+ builder.addRepeatedGroup(repeatedGroup);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedGroup(0, repeatedGroup);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ RepeatedGroup.Builder repeatedGroupBuilder = RepeatedGroup.newBuilder()
+ .setA(3);
+ builder.addRepeatedGroup(repeatedGroupBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA());
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedGroup(0, repeatedGroupBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA());
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedInt32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedInt32Count());
+ builder.setRepeatedInt32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedInt32(0));
+ assertEquals(0, builder.getRepeatedInt32(0));
+ builder.clearRepeatedInt32();
+
+ message = builder.build();
+ builder.addRepeatedInt64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedInt64Count());
+ builder.setRepeatedInt64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedInt64(0));
+ assertEquals(0L, builder.getRepeatedInt64(0));
+ builder.clearRepeatedInt64();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(0, nestedMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb());
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(0, nestedMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ // LITE_RUNTIME doesn't implement equals so we compare on a property and
+ // ensure the property isn't set on repeatedGroup.
+ assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb());
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedSfixed32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedSfixed32Count());
+ builder.setRepeatedSfixed32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedSfixed32(0));
+ assertEquals(0, builder.getRepeatedSfixed32(0));
+ builder.clearRepeatedSfixed32();
+
+ message = builder.build();
+ builder.addRepeatedSfixed64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedSfixed64Count());
+ builder.setRepeatedSfixed64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedSfixed64(0));
+ assertEquals(0L, builder.getRepeatedSfixed64(0));
+ builder.clearRepeatedSfixed64();
+
+ message = builder.build();
+ builder.addRepeatedSint32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedSint32Count());
+ builder.setRepeatedSint32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedSint32(0));
+ assertEquals(0, builder.getRepeatedSint32(0));
+ builder.clearRepeatedSint32();
+
+ message = builder.build();
+ builder.addRepeatedSint64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedSint64Count());
+ builder.setRepeatedSint64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedSint64(0));
+ assertEquals(0L, builder.getRepeatedSint64(0));
+ builder.clearRepeatedSint64();
+
+ message = builder.build();
+ builder.addRepeatedString("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringCount());
+ builder.setRepeatedString(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedString(0));
+ assertEquals("", builder.getRepeatedString(0));
+ builder.clearRepeatedString();
+
+ message = builder.build();
+ builder.addRepeatedStringBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringCount());
+ builder.setRepeatedString(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"),
+ messageAfterBuild.getRepeatedStringBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedStringBytes(0));
+ builder.clearRepeatedString();
+
+ message = builder.build();
+ builder.addRepeatedStringPiece("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringPieceCount());
+ builder.setRepeatedStringPiece(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedStringPiece(0));
+ assertEquals("", builder.getRepeatedStringPiece(0));
+ builder.clearRepeatedStringPiece();
+
+ message = builder.build();
+ builder.addRepeatedStringPieceBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringPieceCount());
+ builder.setRepeatedStringPiece(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"),
+ messageAfterBuild.getRepeatedStringPieceBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedStringPieceBytes(0));
+ builder.clearRepeatedStringPiece();
+
+ message = builder.build();
+ builder.addRepeatedUint32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedUint32Count());
+ builder.setRepeatedUint32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedUint32(0));
+ assertEquals(0, builder.getRepeatedUint32(0));
+ builder.clearRepeatedUint32();
+
+ message = builder.build();
+ builder.addRepeatedUint64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedUint64Count());
+ builder.setRepeatedUint64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedUint64(0));
+ assertEquals(0L, builder.getRepeatedUint64(0));
+ builder.clearRepeatedUint64();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeFrom(TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .build());
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(true, builder.build().getOptionalBool());
+ builder.clearOptionalBool();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeFrom(TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .build());
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(true, builder.build().getOptionalBool());
+ builder.clear();
+ assertEquals(0, builder.build().getSerializedSize());
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeOptionalForeignMessage(foreignMessage);
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(
+ foreignMessage.getC(),
+ builder.build().getOptionalForeignMessage().getC());
+ builder.clearOptionalForeignMessage();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeOptionalLazyMessage(nestedMessage);
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(
+ nestedMessage.getBb(),
+ builder.build().getOptionalLazyMessage().getBb());
+ builder.clearOptionalLazyMessage();
+
+ message = builder.build();
+ builder.setOneofString("hi");
+ assertEquals(
+ OneofFieldCase.ONEOFFIELD_NOT_SET, message.getOneofFieldCase());
+ assertEquals(OneofFieldCase.ONEOF_STRING, builder.getOneofFieldCase());
+ assertEquals("hi", builder.getOneofString());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+ assertEquals("hi", messageAfterBuild.getOneofString());
+ builder.setOneofUint32(1);
+ assertEquals(
+ OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+ assertEquals("hi", messageAfterBuild.getOneofString());
+ assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase());
+ assertEquals(1, builder.getOneofUint32());
+
+ TestAllExtensionsLite.Builder extendableMessageBuilder =
+ TestAllExtensionsLite.newBuilder();
+ TestAllExtensionsLite extendableMessage = extendableMessageBuilder.build();
+ extendableMessageBuilder.setExtension(
+ UnittestLite.optionalInt32ExtensionLite, 1);
+ assertFalse(extendableMessage.hasExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessage = extendableMessageBuilder.build();
+ assertEquals(
+ 1, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessageBuilder.setExtension(
+ UnittestLite.optionalInt32ExtensionLite, 3);
+ assertEquals(
+ 3, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessage = extendableMessageBuilder.build();
+ assertEquals(
+ 3, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 3, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+
+ // No extension registry, so it should be in unknown fields.
+ extendableMessage =
+ TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray());
+ assertFalse(extendableMessage.hasExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+
+ extendableMessageBuilder = extendableMessage.toBuilder();
+ extendableMessageBuilder.mergeFrom(TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalFixed32ExtensionLite, 11)
+ .build());
+
+ extendableMessage = extendableMessageBuilder.build();
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ UnittestLite.registerAllExtensions(registry);
+ extendableMessage = TestAllExtensionsLite.parseFrom(
+ extendableMessage.toByteArray(), registry);
+
+ // The unknown field was preserved.
+ assertEquals(
+ 3, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 11, (int) extendableMessage.getExtension(
+ UnittestLite.optionalFixed32ExtensionLite));
}
}
diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
index 7b201a9d..958b6a7e 100644
--- a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -307,7 +307,8 @@ public class LiteralByteStringTest extends TestCase {
public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException{
assertSame(classUnderTest + " must be the same string references",
- ByteString.EMPTY.toString(Internal.UTF_8), new LiteralByteString(new byte[]{}).toString(Internal.UTF_8));
+ ByteString.EMPTY.toString(Internal.UTF_8),
+ new LiteralByteString(new byte[]{}).toString(Internal.UTF_8));
}
public void testToString_raisesException() throws UnsupportedEncodingException{
diff --git a/java/src/test/java/com/google/protobuf/LongArrayListTest.java b/java/src/test/java/com/google/protobuf/LongArrayListTest.java
new file mode 100644
index 00000000..3a52ec7f
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/LongArrayListTest.java
@@ -0,0 +1,473 @@
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+
+/**
+ * Tests for {@link LongArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class LongArrayListTest extends TestCase {
+
+ private static final LongArrayList UNARY_LIST = newImmutableLongArrayList(1);
+ private static final LongArrayList TERTIARY_LIST =
+ newImmutableLongArrayList(1, 2, 3);
+
+ private LongArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new LongArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(LongArrayList.emptyList(), LongArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(LongArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addLong(2);
+ list.addLong(4);
+ list.addLong(6);
+ list.addLong(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testCopyConstructor() {
+ LongArrayList copy = new LongArrayList(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new LongArrayList(LongArrayList.emptyList());
+ assertEquals(LongArrayList.emptyList(), copy);
+
+ copy = new LongArrayList(asList(1L, 2L, 3L));
+ assertEquals(asList(1L, 2L, 3L), copy);
+
+ copy = new LongArrayList(Collections.<Long>emptyList());
+ assertEquals(LongArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1L, 2L, 3L, 4L));
+ Iterator<Long> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (long) list.get(0));
+ assertEquals(1, (long) iterator.next());
+ list.set(0, 1L);
+ assertEquals(2, (long) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0L);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1, (long) TERTIARY_LIST.get(0));
+ assertEquals(2, (long) TERTIARY_LIST.get(1));
+ assertEquals(3, (long) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetLong() {
+ assertEquals(1, TERTIARY_LIST.getLong(0));
+ assertEquals(2, TERTIARY_LIST.getLong(1));
+ assertEquals(3, TERTIARY_LIST.getLong(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, LongArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addLong(2);
+ list.addLong(4);
+ list.addLong(6);
+ list.addLong(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(16L);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addLong(2);
+ list.addLong(4);
+
+ assertEquals(2, (long) list.set(0, 0L));
+ assertEquals(0, list.getLong(0));
+
+ assertEquals(4, (long) list.set(1, 0L));
+ assertEquals(0, list.getLong(1));
+
+ try {
+ list.set(-1, 0L);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0L);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetLong() {
+ list.addLong(2);
+ list.addLong(4);
+
+ assertEquals(2, list.setLong(0, 0));
+ assertEquals(0, list.getLong(0));
+
+ assertEquals(4, list.setLong(1, 0));
+ assertEquals(0, list.getLong(1));
+
+ try {
+ list.setLong(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setLong(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2L));
+ assertEquals(asList(2L), list);
+
+ assertTrue(list.add(3L));
+ list.add(0, 4L);
+ assertEquals(asList(4L, 2L, 3L), list);
+
+ list.add(0, 1L);
+ list.add(0, 0L);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Long.valueOf(5 + i));
+ }
+ assertEquals(asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), list);
+
+ try {
+ list.add(-1, 5L);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5L);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddLong() {
+ assertEquals(0, list.size());
+
+ list.addLong(2);
+ assertEquals(asList(2L), list);
+
+ list.addLong(3);
+ assertEquals(asList(2L, 3L), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1L)));
+ assertEquals(1, list.size());
+ assertEquals(1, (long) list.get(0));
+ assertEquals(1, list.getLong(0));
+
+ assertTrue(list.addAll(asList(2L, 3L, 4L, 5L, 6L)));
+ assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L), list);
+
+ assertFalse(list.addAll(Collections.<Long>emptyList()));
+ assertFalse(list.addAll(LongArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1, (long) list.remove(0));
+ assertEquals(asList(2L, 3L), list);
+
+ assertTrue(list.remove(3L));
+ assertEquals(asList(2L), list);
+
+ assertFalse(list.remove(3L));
+ assertEquals(asList(2L), list);
+
+ assertEquals(2, (long) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(LongArrayList list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new LongArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addLong(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setLong(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static LongArrayList newImmutableLongArrayList(long... elements) {
+ LongArrayList list = new LongArrayList();
+ for (long element : elements) {
+ list.addLong(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
index 22dbeb76..6cff689f 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -36,6 +36,11 @@ import map_lite_test.MapForProto2TestProto.TestUnknownEnumValue;
import junit.framework.TestCase;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Unit tests for map fields.
*/
@@ -170,6 +175,140 @@ public class MapForProto2LiteTest extends TestCase {
assertEquals(0, message.getStringToInt32Field().size());
}
+ public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+ // Since builders are implemented as a thin wrapper around a message
+ // instance, we attempt to verify that we can't cause the builder to modify
+ // a produced message.
+
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertTrue(message.getInt32ToInt32Field().isEmpty());
+ message = builder.build();
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+ }
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.getMutableInt32ToStringField().put(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
+
public void testGettersAndSetters() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
TestMap message = builder.build();
@@ -274,4 +413,26 @@ public class MapForProto2LiteTest extends TestCase {
assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
}
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
index 78cba1b4..7e984040 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -40,6 +40,7 @@ import map_test.MapForProto2TestProto.TestUnknownEnumValue;
import junit.framework.TestCase;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -177,6 +178,116 @@ public class MapForProto2Test extends TestCase {
assertEquals(0, message.getInt32ToMessageField().size());
assertEquals(0, message.getStringToInt32Field().size());
}
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.getMutableInt32ToStringField().put(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
public void testGettersAndSetters() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
@@ -513,4 +624,41 @@ public class MapForProto2Test extends TestCase {
assertEquals(2, message.getRecursiveMapField().get(1).getValue());
assertEquals(4, message.getRecursiveMapField().get(3).getValue());
}
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ // Regression test for b/20494788
+ public void testMapInitializationOrder() throws Exception {
+ assertEquals("RedactAllTypes", map_test.RedactAllTypes
+ .getDefaultInstance().getDescriptorForType().getName());
+
+ map_test.Message1.Builder builder =
+ map_test.Message1.newBuilder();
+ builder.getMutableMapField().put("key", true);
+ map_test.Message1 message = builder.build();
+ Message mapEntry = (Message) message.getRepeatedField(
+ message.getDescriptorForType().findFieldByName("map_field"), 0);
+ assertEquals(2, mapEntry.getAllFields().size());
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
}
+
diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java
index b8e67b7c..0509be15 100644
--- a/java/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/src/test/java/com/google/protobuf/MapTest.java
@@ -41,6 +41,7 @@ import map_test.MapTestProto.TestOnChangeEventPropagation;
import junit.framework.TestCase;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -178,7 +179,117 @@ public class MapTest extends TestCase {
assertEquals(0, message.getInt32ToMessageField().size());
assertEquals(0, message.getStringToInt32Field().size());
}
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.getMutableInt32ToStringField().put(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
+
public void testGettersAndSetters() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
TestMap message = builder.build();
@@ -611,4 +722,26 @@ public class MapTest extends TestCase {
assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
}
}
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java b/java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
new file mode 100644
index 00000000..f9f5e9c7
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
@@ -0,0 +1,303 @@
+// 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 static java.util.Arrays.asList;
+
+import junit.framework.TestCase;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Tests for {@link ProtobufArrayList}.
+ */
+public class ProtobufArrayListTest extends TestCase {
+
+ private static final ProtobufArrayList<Integer> UNARY_LIST = newImmutableProtoArrayList(1);
+ private static final ProtobufArrayList<Integer> TERTIARY_LIST =
+ newImmutableProtoArrayList(1, 2, 3);
+
+ private ProtobufArrayList<Integer> list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new ProtobufArrayList<Integer>();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(ProtobufArrayList.<Integer>emptyList());
+ }
+
+ public void testCopyConstructor() {
+ ProtobufArrayList<Integer> copy = new ProtobufArrayList<Integer>(TERTIARY_LIST);
+ assertEquals(TERTIARY_LIST, copy);
+
+ copy = new ProtobufArrayList<Integer>(IntArrayList.emptyList());
+ assertEquals(ProtobufArrayList.emptyList(), copy);
+
+ copy = new ProtobufArrayList<Integer>(asList(1, 2, 3));
+ assertEquals(asList(1, 2, 3), copy);
+
+ copy = new ProtobufArrayList<Integer>(Collections.<Integer>emptyList());
+ assertEquals(ProtobufArrayList.emptyList(), copy);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1, 2, 3, 4));
+ Iterator<Integer> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, (int) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.set(0, 1);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testMakeImmutable() {
+ list.add(2);
+ list.add(4);
+ list.add(6);
+ list.add(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testRemove() {
+ list.add(2);
+ list.add(4);
+ list.add(6);
+
+ list.remove(1);
+ assertEquals(asList(2, 6), list);
+
+ list.remove(1);
+ assertEquals(asList(2), list);
+
+ list.remove(0);
+ assertEquals(asList(), list);
+ }
+
+ public void testGet() {
+ list.add(2);
+ list.add(6);
+
+ assertEquals(2, (int) list.get(0));
+ assertEquals(6, (int) list.get(1));
+ }
+
+ public void testSet() {
+ list.add(2);
+ list.add(6);
+
+ list.set(0, 1);
+ assertEquals(1, (int) list.get(0));
+ list.set(1, 2);
+ assertEquals(2, (int) list.get(1));
+ }
+
+ private void assertImmutable(List<Integer> list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new ProtobufArrayList<Integer>());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static ProtobufArrayList<Integer> newImmutableProtoArrayList(int... elements) {
+ ProtobufArrayList<Integer> list = new ProtobufArrayList<Integer>();
+ for (int element : elements) {
+ list.add(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
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
index 8d8ea8ef..8f3ca8c6 100644
--- a/java/src/test/java/com/google/protobuf/field_presence_test.proto
+++ b/java/src/test/java/com/google/protobuf/field_presence_test.proto
@@ -45,15 +45,15 @@ message TestAllTypes {
BAZ = 2;
}
message NestedMessage {
- optional int32 value = 1;
+ 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;
+ int32 optional_int32 = 1;
+ string optional_string = 2;
+ bytes optional_bytes = 3;
+ NestedEnum optional_nested_enum = 4;
+ NestedMessage optional_nested_message = 5;
+ protobuf_unittest.TestRequired optional_proto2_message = 6;
oneof oneof_field {
int32 oneof_int32 = 11;
@@ -75,12 +75,12 @@ message TestAllTypes {
}
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;
+ int32 optional_int32 = 1;
+ string optional_string = 2;
+ bytes optional_bytes = 3;
+ TestAllTypes.NestedEnum optional_nested_enum = 4;
+ TestAllTypes.NestedMessage optional_nested_message = 5;
+ protobuf_unittest.TestRequired optional_proto2_message = 6;
}
message TestRepeatedFieldsOnly {
diff --git a/java/src/test/java/com/google/protobuf/map_initialization_order_test.proto b/java/src/test/java/com/google/protobuf/map_initialization_order_test.proto
new file mode 100644
index 00000000..b02ac599
--- /dev/null
+++ b/java/src/test/java/com/google/protobuf/map_initialization_order_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.
+
+// Regression test for a map initilaization order bug. The bug only manifests
+// when:
+// 1. A message contains map fields and is also extendable.
+// 2. There is a file-level extension defined in the same file referencing
+// the above message as the extension type.
+// 3. The program executes in the following order:
+// a. getDescriptor() is called on another message in the same file.
+// b. use protobuf reflection to access the map field.
+// The symptom is a NullPointerException being thrown.
+syntax = "proto2";
+
+package map_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapInitializationOrderTest";
+option java_multiple_files = true;
+
+// Mirrors the structure of
+// javatests/com/google/cloud/common/logging/logging_test.proto.
+
+message Message1 {
+ map<string, bool> map_field = 1;
+ extensions 1000 to max;
+}
+
+extend Message1 {
+ optional Message1 recursive_extension = 1001;
+}
+
+message RedactAllTypes {
+}
diff --git a/java/src/test/java/com/google/protobuf/map_test.proto b/java/src/test/java/com/google/protobuf/map_test.proto
index bf692c22..2f7709be 100644
--- a/java/src/test/java/com/google/protobuf/map_test.proto
+++ b/java/src/test/java/com/google/protobuf/map_test.proto
@@ -39,7 +39,7 @@ option java_generate_equals_and_hash = true;
message TestMap {
message MessageValue {
- optional int32 value = 1;
+ int32 value = 1;
}
enum EnumValue {
FOO = 0;
@@ -60,5 +60,5 @@ message TestMap {
// 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;
+ TestMap optional_message = 1;
}
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index f7a58ca0..970b1a88 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -245,9 +245,6 @@ class Descriptor(_NestedDescriptorBase):
is_extendable: Does this type define any extension ranges?
- options: (descriptor_pb2.MessageOptions) Protocol message options or None
- to use default message options.
-
oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields
in this message.
oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|,
@@ -265,7 +262,7 @@ class Descriptor(_NestedDescriptorBase):
file=None, serialized_start=None, serialized_end=None,
syntax=None):
_message.Message._CheckCalledFromGeneratedFile()
- return _message.Message._GetMessageDescriptor(full_name)
+ return _message.default_pool.FindMessageTypeByName(full_name)
# NOTE(tmarek): The file argument redefining a builtin is nothing we can
# fix right now since we don't know how many clients already rely on the
@@ -495,9 +492,9 @@ class FieldDescriptor(DescriptorBase):
has_default_value=True, containing_oneof=None):
_message.Message._CheckCalledFromGeneratedFile()
if is_extension:
- return _message.Message._GetExtensionDescriptor(full_name)
+ return _message.default_pool.FindExtensionByName(full_name)
else:
- return _message.Message._GetFieldDescriptor(full_name)
+ return _message.default_pool.FindFieldByName(full_name)
def __init__(self, name, full_name, index, number, type, cpp_type, label,
default_value, message_type, enum_type, containing_type,
@@ -528,14 +525,9 @@ class FieldDescriptor(DescriptorBase):
self.containing_oneof = containing_oneof
if api_implementation.Type() == 'cpp':
if is_extension:
- # pylint: disable=protected-access
- self._cdescriptor = (
- _message.Message._GetExtensionDescriptor(full_name))
- # pylint: enable=protected-access
+ self._cdescriptor = _message.default_pool.FindExtensionByName(full_name)
else:
- # pylint: disable=protected-access
- self._cdescriptor = _message.Message._GetFieldDescriptor(full_name)
- # pylint: enable=protected-access
+ self._cdescriptor = _message.default_pool.FindFieldByName(full_name)
else:
self._cdescriptor = None
@@ -592,7 +584,7 @@ class EnumDescriptor(_NestedDescriptorBase):
containing_type=None, options=None, file=None,
serialized_start=None, serialized_end=None):
_message.Message._CheckCalledFromGeneratedFile()
- return _message.Message._GetEnumDescriptor(full_name)
+ return _message.default_pool.FindEnumTypeByName(full_name)
def __init__(self, name, full_name, filename, values,
containing_type=None, options=None, file=None,
@@ -677,7 +669,7 @@ class OneofDescriptor(object):
def __new__(cls, name, full_name, index, containing_type, fields):
_message.Message._CheckCalledFromGeneratedFile()
- return _message.Message._GetOneofDescriptor(full_name)
+ return _message.default_pool.FindOneofByName(full_name)
def __init__(self, name, full_name, index, containing_type, fields):
"""Arguments are as described in the attribute description above."""
@@ -788,12 +780,8 @@ class FileDescriptor(DescriptorBase):
dependencies=None, syntax=None):
# FileDescriptor() is called from various places, not only from generated
# files, to register dynamic proto files and messages.
- # TODO(amauryfa): Expose BuildFile() as a public function and make this
- # constructor an implementation detail.
if serialized_pb:
- # pylint: disable=protected-access2
- return _message.Message._BuildFile(serialized_pb)
- # pylint: enable=protected-access
+ return _message.default_pool.AddSerializedFile(serialized_pb)
else:
return super(FileDescriptor, cls).__new__(cls)
@@ -814,9 +802,7 @@ class FileDescriptor(DescriptorBase):
if (api_implementation.Type() == 'cpp' and
self.serialized_pb is not None):
- # pylint: disable=protected-access
- _message.Message._BuildFile(self.serialized_pb)
- # pylint: enable=protected-access
+ _message.default_pool.AddSerializedFile(self.serialized_pb)
def CopyToProto(self, proto):
"""Copies this to a descriptor_pb2.FileDescriptorProto.
@@ -864,10 +850,10 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
file_descriptor_proto = descriptor_pb2.FileDescriptorProto()
file_descriptor_proto.message_type.add().MergeFrom(desc_proto)
- # Generate a random name for this proto file to prevent conflicts with
- # any imported ones. We need to specify a file name so BuildFile accepts
- # our FileDescriptorProto, but it is not important what that file name
- # is actually set to.
+ # Generate a random name for this proto file to prevent conflicts with any
+ # imported ones. We need to specify a file name so the descriptor pool
+ # accepts our FileDescriptorProto, but it is not important what that file
+ # name is actually set to.
proto_name = str(uuid.uuid4())
if package:
@@ -877,10 +863,8 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
else:
file_descriptor_proto.name = proto_name + '.proto'
- # pylint: disable=protected-access
- result = _message.Message._BuildFile(
- file_descriptor_proto.SerializeToString())
- # pylint: enable=protected-access
+ _message.default_pool.Add(file_descriptor_proto)
+ result = _message.default_pool.FindFileByName(file_descriptor_proto.name)
if _USE_C_DESCRIPTORS:
return result.message_types_by_name[desc_proto.name]
diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py
index 7e7701f8..1244ba7c 100644
--- a/python/google/protobuf/descriptor_pool.py
+++ b/python/google/protobuf/descriptor_pool.py
@@ -113,6 +113,20 @@ class DescriptorPool(object):
self._internal_db.Add(file_desc_proto)
+ def AddSerializedFile(self, serialized_file_desc_proto):
+ """Adds the FileDescriptorProto and its types to this pool.
+
+ Args:
+ serialized_file_desc_proto: A bytes string, serialization of the
+ FileDescriptorProto to add.
+ """
+
+ # pylint: disable=g-import-not-at-top
+ from google.protobuf import descriptor_pb2
+ file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString(
+ serialized_file_desc_proto)
+ self.Add(file_desc_proto)
+
def AddDescriptor(self, desc):
"""Adds a Descriptor to the pool, non-recursively.
@@ -320,17 +334,17 @@ class DescriptorPool(object):
file_descriptor, None, scope))
for index, extension_proto in enumerate(file_proto.extension):
- extension_desc = self.MakeFieldDescriptor(
+ extension_desc = self._MakeFieldDescriptor(
extension_proto, file_proto.package, index, is_extension=True)
extension_desc.containing_type = self._GetTypeFromScope(
file_descriptor.package, extension_proto.extendee, scope)
- self.SetFieldType(extension_proto, extension_desc,
+ self._SetFieldType(extension_proto, extension_desc,
file_descriptor.package, scope)
file_descriptor.extensions_by_name[extension_desc.name] = (
extension_desc)
for desc_proto in file_proto.message_type:
- self.SetAllFieldTypes(file_proto.package, desc_proto, scope)
+ self._SetAllFieldTypes(file_proto.package, desc_proto, scope)
if file_proto.package:
desc_proto_prefix = _PrefixWithDot(file_proto.package)
@@ -381,10 +395,11 @@ class DescriptorPool(object):
enums = [
self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
for enum in desc_proto.enum_type]
- fields = [self.MakeFieldDescriptor(field, desc_name, index)
+ fields = [self._MakeFieldDescriptor(field, desc_name, index)
for index, field in enumerate(desc_proto.field)]
extensions = [
- self.MakeFieldDescriptor(extension, desc_name, index, is_extension=True)
+ self._MakeFieldDescriptor(extension, desc_name, index,
+ is_extension=True)
for index, extension in enumerate(desc_proto.extension)]
oneofs = [
descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)),
@@ -464,8 +479,8 @@ class DescriptorPool(object):
self._enum_descriptors[enum_name] = desc
return desc
- def MakeFieldDescriptor(self, field_proto, message_name, index,
- is_extension=False):
+ def _MakeFieldDescriptor(self, field_proto, message_name, index,
+ is_extension=False):
"""Creates a field descriptor from a FieldDescriptorProto.
For message and enum type fields, this method will do a look up
@@ -506,7 +521,7 @@ class DescriptorPool(object):
extension_scope=None,
options=field_proto.options)
- def SetAllFieldTypes(self, package, desc_proto, scope):
+ def _SetAllFieldTypes(self, package, desc_proto, scope):
"""Sets all the descriptor's fields's types.
This method also sets the containing types on any extensions.
@@ -527,18 +542,18 @@ class DescriptorPool(object):
nested_package = '.'.join([package, desc_proto.name])
for field_proto, field_desc in zip(desc_proto.field, main_desc.fields):
- self.SetFieldType(field_proto, field_desc, nested_package, scope)
+ self._SetFieldType(field_proto, field_desc, nested_package, scope)
for extension_proto, extension_desc in (
zip(desc_proto.extension, main_desc.extensions)):
extension_desc.containing_type = self._GetTypeFromScope(
nested_package, extension_proto.extendee, scope)
- self.SetFieldType(extension_proto, extension_desc, nested_package, scope)
+ self._SetFieldType(extension_proto, extension_desc, nested_package, scope)
for nested_type in desc_proto.nested_type:
- self.SetAllFieldTypes(nested_package, nested_type, scope)
+ self._SetAllFieldTypes(nested_package, nested_type, scope)
- def SetFieldType(self, field_proto, field_desc, package, scope):
+ def _SetFieldType(self, field_proto, field_desc, package, scope):
"""Sets the field's type, cpp_type, message_type and enum_type.
Args:
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index d976f9e1..72c2fa01 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -41,6 +41,146 @@ are:
__author__ = 'petar@google.com (Petar Petrov)'
+import sys
+
+if sys.version_info[0] < 3:
+ # We would use collections.MutableMapping all the time, but in Python 2 it
+ # doesn't define __slots__. This causes two significant problems:
+ #
+ # 1. we can't disallow arbitrary attribute assignment, even if our derived
+ # classes *do* define __slots__.
+ #
+ # 2. we can't safely derive a C type from it without __slots__ defined (the
+ # interpreter expects to find a dict at tp_dictoffset, which we can't
+ # robustly provide. And we don't want an instance dict anyway.
+ #
+ # So this is the Python 2.7 definition of Mapping/MutableMapping functions
+ # verbatim, except that:
+ # 1. We declare __slots__.
+ # 2. We don't declare this as a virtual base class. The classes defined
+ # in collections are the interesting base classes, not us.
+ #
+ # Note: deriving from object is critical. It is the only thing that makes
+ # this a true type, allowing us to derive from it in C++ cleanly and making
+ # __slots__ properly disallow arbitrary element assignment.
+ from collections import Mapping as _Mapping
+
+ class Mapping(object):
+ __slots__ = ()
+
+ def get(self, key, default=None):
+ try:
+ return self[key]
+ except KeyError:
+ return default
+
+ def __contains__(self, key):
+ try:
+ self[key]
+ except KeyError:
+ return False
+ else:
+ return True
+
+ def iterkeys(self):
+ return iter(self)
+
+ def itervalues(self):
+ for key in self:
+ yield self[key]
+
+ def iteritems(self):
+ for key in self:
+ yield (key, self[key])
+
+ def keys(self):
+ return list(self)
+
+ def items(self):
+ return [(key, self[key]) for key in self]
+
+ def values(self):
+ return [self[key] for key in self]
+
+ # Mappings are not hashable by default, but subclasses can change this
+ __hash__ = None
+
+ def __eq__(self, other):
+ if not isinstance(other, _Mapping):
+ return NotImplemented
+ return dict(self.items()) == dict(other.items())
+
+ def __ne__(self, other):
+ return not (self == other)
+
+ class MutableMapping(Mapping):
+ __slots__ = ()
+
+ __marker = object()
+
+ def pop(self, key, default=__marker):
+ try:
+ value = self[key]
+ except KeyError:
+ if default is self.__marker:
+ raise
+ return default
+ else:
+ del self[key]
+ return value
+
+ def popitem(self):
+ try:
+ key = next(iter(self))
+ except StopIteration:
+ raise KeyError
+ value = self[key]
+ del self[key]
+ return key, value
+
+ def clear(self):
+ try:
+ while True:
+ self.popitem()
+ except KeyError:
+ pass
+
+ def update(*args, **kwds):
+ if len(args) > 2:
+ raise TypeError("update() takes at most 2 positional "
+ "arguments ({} given)".format(len(args)))
+ elif not args:
+ raise TypeError("update() takes at least 1 argument (0 given)")
+ self = args[0]
+ other = args[1] if len(args) >= 2 else ()
+
+ if isinstance(other, Mapping):
+ for key in other:
+ self[key] = other[key]
+ elif hasattr(other, "keys"):
+ for key in other.keys():
+ self[key] = other[key]
+ else:
+ for key, value in other:
+ self[key] = value
+ for key, value in kwds.items():
+ self[key] = value
+
+ def setdefault(self, key, default=None):
+ try:
+ return self[key]
+ except KeyError:
+ self[key] = default
+ return default
+
+ _Mapping.register(Mapping)
+
+else:
+ # In Python 3 we can just use MutableMapping directly, because it defines
+ # __slots__.
+ from collections import MutableMapping
+
+
class BaseContainer(object):
"""Base container class."""
@@ -286,3 +426,160 @@ class RepeatedCompositeFieldContainer(BaseContainer):
raise TypeError('Can only compare repeated composite fields against '
'other repeated composite fields.')
return self._values == other._values
+
+
+class ScalarMap(MutableMapping):
+
+ """Simple, type-checked, dict-like container for holding repeated scalars."""
+
+ # Disallows assignment to other attributes.
+ __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener']
+
+ def __init__(self, message_listener, key_checker, value_checker):
+ """
+ Args:
+ message_listener: A MessageListener implementation.
+ The ScalarMap will call this object's Modified() method when it
+ is modified.
+ key_checker: A type_checkers.ValueChecker instance to run on keys
+ inserted into this container.
+ value_checker: A type_checkers.ValueChecker instance to run on values
+ inserted into this container.
+ """
+ self._message_listener = message_listener
+ self._key_checker = key_checker
+ self._value_checker = value_checker
+ self._values = {}
+
+ def __getitem__(self, key):
+ try:
+ return self._values[key]
+ except KeyError:
+ key = self._key_checker.CheckValue(key)
+ val = self._value_checker.DefaultValue()
+ self._values[key] = val
+ return val
+
+ def __contains__(self, item):
+ return item in self._values
+
+ # We need to override this explicitly, because our defaultdict-like behavior
+ # will make the default implementation (from our base class) always insert
+ # the key.
+ def get(self, key, default=None):
+ if key in self:
+ return self[key]
+ else:
+ return default
+
+ def __setitem__(self, key, value):
+ checked_key = self._key_checker.CheckValue(key)
+ checked_value = self._value_checker.CheckValue(value)
+ self._values[checked_key] = checked_value
+ self._message_listener.Modified()
+
+ def __delitem__(self, key):
+ del self._values[key]
+ self._message_listener.Modified()
+
+ def __len__(self):
+ return len(self._values)
+
+ def __iter__(self):
+ return iter(self._values)
+
+ def MergeFrom(self, other):
+ self._values.update(other._values)
+ self._message_listener.Modified()
+
+ # This is defined in the abstract base, but we can do it much more cheaply.
+ def clear(self):
+ self._values.clear()
+ self._message_listener.Modified()
+
+
+class MessageMap(MutableMapping):
+
+ """Simple, type-checked, dict-like container for with submessage values."""
+
+ # Disallows assignment to other attributes.
+ __slots__ = ['_key_checker', '_values', '_message_listener',
+ '_message_descriptor']
+
+ def __init__(self, message_listener, message_descriptor, key_checker):
+ """
+ Args:
+ message_listener: A MessageListener implementation.
+ The ScalarMap will call this object's Modified() method when it
+ is modified.
+ key_checker: A type_checkers.ValueChecker instance to run on keys
+ inserted into this container.
+ value_checker: A type_checkers.ValueChecker instance to run on values
+ inserted into this container.
+ """
+ self._message_listener = message_listener
+ self._message_descriptor = message_descriptor
+ self._key_checker = key_checker
+ self._values = {}
+
+ def __getitem__(self, key):
+ try:
+ return self._values[key]
+ except KeyError:
+ key = self._key_checker.CheckValue(key)
+ new_element = self._message_descriptor._concrete_class()
+ new_element._SetListener(self._message_listener)
+ self._values[key] = new_element
+ self._message_listener.Modified()
+
+ return new_element
+
+ def get_or_create(self, key):
+ """get_or_create() is an alias for getitem (ie. map[key]).
+
+ Args:
+ key: The key to get or create in the map.
+
+ This is useful in cases where you want to be explicit that the call is
+ mutating the map. This can avoid lint errors for statements like this
+ that otherwise would appear to be pointless statements:
+
+ msg.my_map[key]
+ """
+ return self[key]
+
+ # We need to override this explicitly, because our defaultdict-like behavior
+ # will make the default implementation (from our base class) always insert
+ # the key.
+ def get(self, key, default=None):
+ if key in self:
+ return self[key]
+ else:
+ return default
+
+ def __contains__(self, item):
+ return item in self._values
+
+ def __setitem__(self, key, value):
+ raise ValueError('May not set values directly, call my_map[key].foo = 5')
+
+ def __delitem__(self, key):
+ del self._values[key]
+ self._message_listener.Modified()
+
+ def __len__(self):
+ return len(self._values)
+
+ def __iter__(self):
+ return iter(self._values)
+
+ def MergeFrom(self, other):
+ for key in other:
+ self[key].MergeFrom(other[key])
+ # self._message_listener.Modified() not required here, because
+ # mutations to submessages already propagate.
+
+ # This is defined in the abstract base, but we can do it much more cheaply.
+ def clear(self):
+ self._values.clear()
+ self._message_listener.Modified()
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index 0f500606..3837eaea 100755
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -733,6 +733,50 @@ def MessageSetItemDecoder(extensions_by_number):
return DecodeItem
# --------------------------------------------------------------------
+
+def MapDecoder(field_descriptor, new_default, is_message_map):
+ """Returns a decoder for a map field."""
+
+ key = field_descriptor
+ tag_bytes = encoder.TagBytes(field_descriptor.number,
+ wire_format.WIRETYPE_LENGTH_DELIMITED)
+ tag_len = len(tag_bytes)
+ local_DecodeVarint = _DecodeVarint
+ # Can't read _concrete_class yet; might not be initialized.
+ message_type = field_descriptor.message_type
+
+ def DecodeMap(buffer, pos, end, message, field_dict):
+ submsg = message_type._concrete_class()
+ value = field_dict.get(key)
+ if value is None:
+ value = field_dict.setdefault(key, new_default(message))
+ while 1:
+ # Read length.
+ (size, pos) = local_DecodeVarint(buffer, pos)
+ new_pos = pos + size
+ if new_pos > end:
+ raise _DecodeError('Truncated message.')
+ # Read sub-message.
+ submsg.Clear()
+ if submsg._InternalParse(buffer, pos, new_pos) != new_pos:
+ # The only reason _InternalParse would return early is if it
+ # encountered an end-group tag.
+ raise _DecodeError('Unexpected end-group tag.')
+
+ if is_message_map:
+ value[submsg.key].MergeFrom(submsg.value)
+ else:
+ value[submsg.key] = submsg.value
+
+ # Predict that the next tag is another copy of the same repeated field.
+ pos = new_pos + tag_len
+ if buffer[new_pos:pos] != tag_bytes or new_pos == end:
+ # Prediction failed. Return.
+ return new_pos
+
+ return DecodeMap
+
+# --------------------------------------------------------------------
# Optimization is not as heavy here because calls to SkipField() are rare,
# except for handling end-group tags.
diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py
index 56fe14e9..8416e157 100644
--- a/python/google/protobuf/internal/descriptor_database_test.py
+++ b/python/google/protobuf/internal/descriptor_database_test.py
@@ -35,7 +35,6 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
import unittest
-
from google.protobuf import descriptor_pb2
from google.protobuf.internal import factory_test2_pb2
from google.protobuf import descriptor_database
diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py
index 7d145f42..d159cc62 100644
--- a/python/google/protobuf/internal/descriptor_pool_test.py
+++ b/python/google/protobuf/internal/descriptor_pool_test.py
@@ -37,6 +37,7 @@ __author__ = 'matthewtoia@google.com (Matt Toia)'
import os
import unittest
+import unittest
from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pb2
from google.protobuf.internal import api_implementation
@@ -226,6 +227,13 @@ class DescriptorPoolTest(unittest.TestCase):
db.Add(self.factory_test2_fd)
self.testFindMessageTypeByName()
+ def testAddSerializedFile(self):
+ db = descriptor_database.DescriptorDatabase()
+ self.pool = descriptor_pool.DescriptorPool(db)
+ self.pool.AddSerializedFile(self.factory_test1_fd.SerializeToString())
+ self.pool.AddSerializedFile(self.factory_test2_fd.SerializeToString())
+ self.testFindMessageTypeByName()
+
def testComplexNesting(self):
test1_desc = descriptor_pb2.FileDescriptorProto.FromString(
descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb)
@@ -510,6 +518,43 @@ class AddDescriptorTest(unittest.TestCase):
'protobuf_unittest.TestAllTypes')
+@unittest.skipIf(
+ api_implementation.Type() != 'cpp',
+ 'default_pool is only supported by the C++ implementation')
+class DefaultPoolTest(unittest.TestCase):
+
+ def testFindMethods(self):
+ # pylint: disable=g-import-not-at-top
+ from google.protobuf.pyext import _message
+ pool = _message.default_pool
+ self.assertIs(
+ pool.FindFileByName('google/protobuf/unittest.proto'),
+ unittest_pb2.DESCRIPTOR)
+ self.assertIs(
+ pool.FindMessageTypeByName('protobuf_unittest.TestAllTypes'),
+ unittest_pb2.TestAllTypes.DESCRIPTOR)
+ self.assertIs(
+ pool.FindFieldByName('protobuf_unittest.TestAllTypes.optional_int32'),
+ unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32'])
+ self.assertIs(
+ pool.FindExtensionByName('protobuf_unittest.optional_int32_extension'),
+ unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension'])
+ self.assertIs(
+ pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'),
+ unittest_pb2.ForeignEnum.DESCRIPTOR)
+ self.assertIs(
+ pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'),
+ unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field'])
+
+ def testAddFileDescriptor(self):
+ # pylint: disable=g-import-not-at-top
+ from google.protobuf.pyext import _message
+ pool = _message.default_pool
+ file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto')
+ pool.Add(file_desc)
+ pool.AddSerializedFile(file_desc.SerializeToString())
+
+
TEST1_FILE = ProtoFile(
'google/protobuf/internal/descriptor_pool_test1.proto',
'google.protobuf.python.internal',
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 335caee6..26866f3a 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -35,8 +35,8 @@
__author__ = 'robinson@google.com (Will Robinson)'
import sys
-import unittest
+import unittest
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
index 38a5138a..752f4eab 100755
--- a/python/google/protobuf/internal/encoder.py
+++ b/python/google/protobuf/internal/encoder.py
@@ -314,7 +314,7 @@ def MessageSizer(field_number, is_repeated, is_packed):
# --------------------------------------------------------------------
-# MessageSet is special.
+# MessageSet is special: it needs custom logic to compute its size properly.
def MessageSetItemSizer(field_number):
@@ -339,6 +339,32 @@ def MessageSetItemSizer(field_number):
return FieldSize
+# --------------------------------------------------------------------
+# Map is special: it needs custom logic to compute its size properly.
+
+
+def MapSizer(field_descriptor):
+ """Returns a sizer for a map field."""
+
+ # Can't look at field_descriptor.message_type._concrete_class because it may
+ # not have been initialized yet.
+ message_type = field_descriptor.message_type
+ message_sizer = MessageSizer(field_descriptor.number, False, False)
+
+ def FieldSize(map_value):
+ total = 0
+ for key in map_value:
+ value = map_value[key]
+ # It's wasteful to create the messages and throw them away one second
+ # later since we'll do the same for the actual encode. But there's not an
+ # obvious way to avoid this within the current design without tons of code
+ # duplication.
+ entry_msg = message_type._concrete_class(key=key, value=value)
+ total += message_sizer(entry_msg)
+ return total
+
+ return FieldSize
+
# ====================================================================
# Encoders!
@@ -786,3 +812,30 @@ def MessageSetItemEncoder(field_number):
return write(end_bytes)
return EncodeField
+
+
+# --------------------------------------------------------------------
+# As before, Map is special.
+
+
+def MapEncoder(field_descriptor):
+ """Encoder for extensions of MessageSet.
+
+ Maps always have a wire format like this:
+ message MapEntry {
+ key_type key = 1;
+ value_type value = 2;
+ }
+ repeated MapEntry map = N;
+ """
+ # Can't look at field_descriptor.message_type._concrete_class because it may
+ # not have been initialized yet.
+ message_type = field_descriptor.message_type
+ encode_message = MessageEncoder(field_descriptor.number, False, False)
+
+ def EncodeField(write, value):
+ for key in value:
+ entry_msg = message_type._concrete_class(key=key, value=value[key])
+ encode_message(write, entry_msg)
+
+ return EncodeField
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index ccc5860b..5c07cbe6 100755
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -42,7 +42,6 @@ further ensures that we can use Python protocol message objects as we expect.
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
-
from google.protobuf.internal import test_bad_identifiers_pb2
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py
index 626c3fc9..b8694f96 100644
--- a/python/google/protobuf/internal/message_factory_test.py
+++ b/python/google/protobuf/internal/message_factory_test.py
@@ -35,7 +35,6 @@
__author__ = 'matthewtoia@google.com (Matt Toia)'
import unittest
-
from google.protobuf import descriptor_pb2
from google.protobuf.internal import factory_test1_pb2
from google.protobuf.internal import factory_test2_pb2
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 4ecaa1c7..320ff0d2 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -50,7 +50,9 @@ import pickle
import sys
import unittest
+import unittest
from google.protobuf.internal import _parameterized
+from google.protobuf import map_unittest_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_proto3_arena_pb2
from google.protobuf.internal import api_implementation
@@ -125,10 +127,17 @@ class MessageTest(unittest.TestCase):
self.assertEqual(unpickled_message, golden_message)
def testPositiveInfinity(self, message_module):
- golden_data = (b'\x5D\x00\x00\x80\x7F'
- b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
- b'\xCD\x02\x00\x00\x80\x7F'
- b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F')
+ if message_module is unittest_pb2:
+ golden_data = (b'\x5D\x00\x00\x80\x7F'
+ b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
+ b'\xCD\x02\x00\x00\x80\x7F'
+ b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F')
+ else:
+ golden_data = (b'\x5D\x00\x00\x80\x7F'
+ b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F'
+ b'\xCA\x02\x04\x00\x00\x80\x7F'
+ b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
+
golden_message = message_module.TestAllTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(IsPosInf(golden_message.optional_float))
@@ -138,10 +147,17 @@ class MessageTest(unittest.TestCase):
self.assertEqual(golden_data, golden_message.SerializeToString())
def testNegativeInfinity(self, message_module):
- golden_data = (b'\x5D\x00\x00\x80\xFF'
- b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
- b'\xCD\x02\x00\x00\x80\xFF'
- b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
+ if message_module is unittest_pb2:
+ golden_data = (b'\x5D\x00\x00\x80\xFF'
+ b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
+ b'\xCD\x02\x00\x00\x80\xFF'
+ b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF')
+ else:
+ golden_data = (b'\x5D\x00\x00\x80\xFF'
+ b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF'
+ b'\xCA\x02\x04\x00\x00\x80\xFF'
+ b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
+
golden_message = message_module.TestAllTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(IsNegInf(golden_message.optional_float))
@@ -1034,64 +1050,132 @@ class Proto2Test(unittest.TestCase):
self.assertEqual(len(parsing_merge.Extensions[
unittest_pb2.TestParsingMerge.repeated_ext]), 3)
+ def testPythonicInit(self):
+ message = unittest_pb2.TestAllTypes(
+ optional_int32=100,
+ optional_fixed32=200,
+ optional_float=300.5,
+ optional_bytes=b'x',
+ optionalgroup={'a': 400},
+ optional_nested_message={'bb': 500},
+ optional_nested_enum='BAZ',
+ repeatedgroup=[{'a': 600},
+ {'a': 700}],
+ repeated_nested_enum=['FOO', unittest_pb2.TestAllTypes.BAR],
+ default_int32=800,
+ oneof_string='y')
+ self.assertTrue(isinstance(message, unittest_pb2.TestAllTypes))
+ self.assertEqual(100, message.optional_int32)
+ self.assertEqual(200, message.optional_fixed32)
+ self.assertEqual(300.5, message.optional_float)
+ self.assertEqual(b'x', message.optional_bytes)
+ self.assertEqual(400, message.optionalgroup.a)
+ self.assertTrue(isinstance(message.optional_nested_message,
+ unittest_pb2.TestAllTypes.NestedMessage))
+ self.assertEqual(500, message.optional_nested_message.bb)
+ self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+ message.optional_nested_enum)
+ self.assertEqual(2, len(message.repeatedgroup))
+ self.assertEqual(600, message.repeatedgroup[0].a)
+ self.assertEqual(700, message.repeatedgroup[1].a)
+ self.assertEqual(2, len(message.repeated_nested_enum))
+ self.assertEqual(unittest_pb2.TestAllTypes.FOO,
+ message.repeated_nested_enum[0])
+ self.assertEqual(unittest_pb2.TestAllTypes.BAR,
+ message.repeated_nested_enum[1])
+ self.assertEqual(800, message.default_int32)
+ self.assertEqual('y', message.oneof_string)
+ self.assertFalse(message.HasField('optional_int64'))
+ self.assertEqual(0, len(message.repeated_float))
+ self.assertEqual(42, message.default_int64)
+
+ message = unittest_pb2.TestAllTypes(optional_nested_enum=u'BAZ')
+ self.assertEqual(unittest_pb2.TestAllTypes.BAZ,
+ message.optional_nested_enum)
+
+ with self.assertRaises(ValueError):
+ unittest_pb2.TestAllTypes(
+ optional_nested_message={'INVALID_NESTED_FIELD': 17})
+
+ with self.assertRaises(TypeError):
+ unittest_pb2.TestAllTypes(
+ optional_nested_message={'bb': 'INVALID_VALUE_TYPE'})
+
+ with self.assertRaises(ValueError):
+ unittest_pb2.TestAllTypes(optional_nested_enum='INVALID_LABEL')
+
+ with self.assertRaises(ValueError):
+ unittest_pb2.TestAllTypes(repeated_nested_enum='FOO')
+
# Class to test proto3-only features/behavior (updated field presence & enums)
class Proto3Test(unittest.TestCase):
+ # Utility method for comparing equality with a map.
+ def assertMapIterEquals(self, map_iter, dict_value):
+ # Avoid mutating caller's copy.
+ dict_value = dict(dict_value)
+
+ for k, v in map_iter:
+ self.assertEqual(v, dict_value[k])
+ del dict_value[k]
+
+ self.assertEqual({}, dict_value)
+
def testFieldPresence(self):
message = unittest_proto3_arena_pb2.TestAllTypes()
# We can't test presence of non-repeated, non-submessage fields.
with self.assertRaises(ValueError):
- message.HasField("optional_int32")
+ message.HasField('optional_int32')
with self.assertRaises(ValueError):
- message.HasField("optional_float")
+ message.HasField('optional_float')
with self.assertRaises(ValueError):
- message.HasField("optional_string")
+ message.HasField('optional_string')
with self.assertRaises(ValueError):
- message.HasField("optional_bool")
+ message.HasField('optional_bool')
# But we can still test presence of submessage fields.
- self.assertFalse(message.HasField("optional_nested_message"))
+ self.assertFalse(message.HasField('optional_nested_message'))
# As with proto2, we can't test presence of fields that don't exist, or
# repeated fields.
with self.assertRaises(ValueError):
- message.HasField("field_doesnt_exist")
+ message.HasField('field_doesnt_exist')
with self.assertRaises(ValueError):
- message.HasField("repeated_int32")
+ message.HasField('repeated_int32')
with self.assertRaises(ValueError):
- message.HasField("repeated_nested_message")
+ message.HasField('repeated_nested_message')
# Fields should default to their type-specific default.
self.assertEqual(0, message.optional_int32)
self.assertEqual(0, message.optional_float)
- self.assertEqual("", message.optional_string)
+ self.assertEqual('', message.optional_string)
self.assertEqual(False, message.optional_bool)
self.assertEqual(0, message.optional_nested_message.bb)
# Setting a submessage should still return proper presence information.
message.optional_nested_message.bb = 0
- self.assertTrue(message.HasField("optional_nested_message"))
+ self.assertTrue(message.HasField('optional_nested_message'))
# Set the fields to non-default values.
message.optional_int32 = 5
message.optional_float = 1.1
- message.optional_string = "abc"
+ message.optional_string = 'abc'
message.optional_bool = True
message.optional_nested_message.bb = 15
# Clearing the fields unsets them and resets their value to default.
- message.ClearField("optional_int32")
- message.ClearField("optional_float")
- message.ClearField("optional_string")
- message.ClearField("optional_bool")
- message.ClearField("optional_nested_message")
+ message.ClearField('optional_int32')
+ message.ClearField('optional_float')
+ message.ClearField('optional_string')
+ message.ClearField('optional_bool')
+ message.ClearField('optional_nested_message')
self.assertEqual(0, message.optional_int32)
self.assertEqual(0, message.optional_float)
- self.assertEqual("", message.optional_string)
+ self.assertEqual('', message.optional_string)
self.assertEqual(False, message.optional_bool)
self.assertEqual(0, message.optional_nested_message.bb)
@@ -1113,6 +1197,393 @@ class Proto3Test(unittest.TestCase):
self.assertEqual(1234567, m2.optional_nested_enum)
self.assertEqual(7654321, m2.repeated_nested_enum[0])
+ # Map isn't really a proto3-only feature. But there is no proto2 equivalent
+ # of google/protobuf/map_unittest.proto right now, so it's not easy to
+ # test both with the same test like we do for the other proto2/proto3 tests.
+ # (google/protobuf/map_protobuf_unittest.proto is very different in the set
+ # of messages and fields it contains).
+ def testScalarMapDefaults(self):
+ msg = map_unittest_pb2.TestMap()
+
+ # Scalars start out unset.
+ self.assertFalse(-123 in msg.map_int32_int32)
+ self.assertFalse(-2**33 in msg.map_int64_int64)
+ self.assertFalse(123 in msg.map_uint32_uint32)
+ self.assertFalse(2**33 in msg.map_uint64_uint64)
+ self.assertFalse('abc' in msg.map_string_string)
+ self.assertFalse(888 in msg.map_int32_enum)
+
+ # Accessing an unset key returns the default.
+ self.assertEqual(0, msg.map_int32_int32[-123])
+ self.assertEqual(0, msg.map_int64_int64[-2**33])
+ self.assertEqual(0, msg.map_uint32_uint32[123])
+ self.assertEqual(0, msg.map_uint64_uint64[2**33])
+ self.assertEqual('', msg.map_string_string['abc'])
+ self.assertEqual(0, msg.map_int32_enum[888])
+
+ # It also sets the value in the map
+ self.assertTrue(-123 in msg.map_int32_int32)
+ self.assertTrue(-2**33 in msg.map_int64_int64)
+ self.assertTrue(123 in msg.map_uint32_uint32)
+ self.assertTrue(2**33 in msg.map_uint64_uint64)
+ self.assertTrue('abc' in msg.map_string_string)
+ self.assertTrue(888 in msg.map_int32_enum)
+
+ self.assertTrue(isinstance(msg.map_string_string['abc'], unicode))
+
+ # Accessing an unset key still throws TypeError of the type of the key
+ # is incorrect.
+ with self.assertRaises(TypeError):
+ msg.map_string_string[123]
+
+ self.assertFalse(123 in msg.map_string_string)
+
+ def testMapGet(self):
+ # Need to test that get() properly returns the default, even though the dict
+ # has defaultdict-like semantics.
+ msg = map_unittest_pb2.TestMap()
+
+ self.assertIsNone(msg.map_int32_int32.get(5))
+ self.assertEquals(10, msg.map_int32_int32.get(5, 10))
+ self.assertIsNone(msg.map_int32_int32.get(5))
+
+ msg.map_int32_int32[5] = 15
+ self.assertEquals(15, msg.map_int32_int32.get(5))
+
+ self.assertIsNone(msg.map_int32_foreign_message.get(5))
+ self.assertEquals(10, msg.map_int32_foreign_message.get(5, 10))
+
+ submsg = msg.map_int32_foreign_message[5]
+ self.assertIs(submsg, msg.map_int32_foreign_message.get(5))
+
+ def testScalarMap(self):
+ msg = map_unittest_pb2.TestMap()
+
+ self.assertEqual(0, len(msg.map_int32_int32))
+ self.assertFalse(5 in msg.map_int32_int32)
+
+ msg.map_int32_int32[-123] = -456
+ msg.map_int64_int64[-2**33] = -2**34
+ msg.map_uint32_uint32[123] = 456
+ msg.map_uint64_uint64[2**33] = 2**34
+ msg.map_string_string['abc'] = '123'
+ msg.map_int32_enum[888] = 2
+
+ self.assertEqual([], msg.FindInitializationErrors())
+
+ self.assertEqual(1, len(msg.map_string_string))
+
+ # Bad key.
+ with self.assertRaises(TypeError):
+ msg.map_string_string[123] = '123'
+
+ # Verify that trying to assign a bad key doesn't actually add a member to
+ # the map.
+ self.assertEqual(1, len(msg.map_string_string))
+
+ # Bad value.
+ with self.assertRaises(TypeError):
+ msg.map_string_string['123'] = 123
+
+ serialized = msg.SerializeToString()
+ msg2 = map_unittest_pb2.TestMap()
+ msg2.ParseFromString(serialized)
+
+ # Bad key.
+ with self.assertRaises(TypeError):
+ msg2.map_string_string[123] = '123'
+
+ # Bad value.
+ with self.assertRaises(TypeError):
+ msg2.map_string_string['123'] = 123
+
+ self.assertEqual(-456, msg2.map_int32_int32[-123])
+ self.assertEqual(-2**34, msg2.map_int64_int64[-2**33])
+ self.assertEqual(456, msg2.map_uint32_uint32[123])
+ self.assertEqual(2**34, msg2.map_uint64_uint64[2**33])
+ self.assertEqual('123', msg2.map_string_string['abc'])
+ self.assertEqual(2, msg2.map_int32_enum[888])
+
+ def testStringUnicodeConversionInMap(self):
+ msg = map_unittest_pb2.TestMap()
+
+ unicode_obj = u'\u1234'
+ bytes_obj = unicode_obj.encode('utf8')
+
+ msg.map_string_string[bytes_obj] = bytes_obj
+
+ (key, value) = msg.map_string_string.items()[0]
+
+ self.assertEqual(key, unicode_obj)
+ self.assertEqual(value, unicode_obj)
+
+ self.assertTrue(isinstance(key, unicode))
+ self.assertTrue(isinstance(value, unicode))
+
+ def testMessageMap(self):
+ msg = map_unittest_pb2.TestMap()
+
+ self.assertEqual(0, len(msg.map_int32_foreign_message))
+ self.assertFalse(5 in msg.map_int32_foreign_message)
+
+ msg.map_int32_foreign_message[123]
+ # get_or_create() is an alias for getitem.
+ msg.map_int32_foreign_message.get_or_create(-456)
+
+ self.assertEqual(2, len(msg.map_int32_foreign_message))
+ self.assertIn(123, msg.map_int32_foreign_message)
+ self.assertIn(-456, msg.map_int32_foreign_message)
+ self.assertEqual(2, len(msg.map_int32_foreign_message))
+
+ # Bad key.
+ with self.assertRaises(TypeError):
+ msg.map_int32_foreign_message['123']
+
+ # Can't assign directly to submessage.
+ with self.assertRaises(ValueError):
+ msg.map_int32_foreign_message[999] = msg.map_int32_foreign_message[123]
+
+ # Verify that trying to assign a bad key doesn't actually add a member to
+ # the map.
+ self.assertEqual(2, len(msg.map_int32_foreign_message))
+
+ serialized = msg.SerializeToString()
+ msg2 = map_unittest_pb2.TestMap()
+ msg2.ParseFromString(serialized)
+
+ self.assertEqual(2, len(msg2.map_int32_foreign_message))
+ self.assertIn(123, msg2.map_int32_foreign_message)
+ self.assertIn(-456, msg2.map_int32_foreign_message)
+ self.assertEqual(2, len(msg2.map_int32_foreign_message))
+
+ def testMergeFrom(self):
+ msg = map_unittest_pb2.TestMap()
+ msg.map_int32_int32[12] = 34
+ msg.map_int32_int32[56] = 78
+ msg.map_int64_int64[22] = 33
+ msg.map_int32_foreign_message[111].c = 5
+ msg.map_int32_foreign_message[222].c = 10
+
+ msg2 = map_unittest_pb2.TestMap()
+ msg2.map_int32_int32[12] = 55
+ msg2.map_int64_int64[88] = 99
+ msg2.map_int32_foreign_message[222].c = 15
+
+ msg2.MergeFrom(msg)
+
+ self.assertEqual(34, msg2.map_int32_int32[12])
+ self.assertEqual(78, msg2.map_int32_int32[56])
+ self.assertEqual(33, msg2.map_int64_int64[22])
+ self.assertEqual(99, msg2.map_int64_int64[88])
+ self.assertEqual(5, msg2.map_int32_foreign_message[111].c)
+ self.assertEqual(10, msg2.map_int32_foreign_message[222].c)
+
+ # Verify that there is only one entry per key, even though the MergeFrom
+ # may have internally created multiple entries for a single key in the
+ # list representation.
+ as_dict = {}
+ for key in msg2.map_int32_foreign_message:
+ self.assertFalse(key in as_dict)
+ as_dict[key] = msg2.map_int32_foreign_message[key].c
+
+ self.assertEqual({111: 5, 222: 10}, as_dict)
+
+ # Special case: test that delete of item really removes the item, even if
+ # there might have physically been duplicate keys due to the previous merge.
+ # This is only a special case for the C++ implementation which stores the
+ # map as an array.
+ del msg2.map_int32_int32[12]
+ self.assertFalse(12 in msg2.map_int32_int32)
+
+ del msg2.map_int32_foreign_message[222]
+ self.assertFalse(222 in msg2.map_int32_foreign_message)
+
+ def testIntegerMapWithLongs(self):
+ msg = map_unittest_pb2.TestMap()
+ msg.map_int32_int32[long(-123)] = long(-456)
+ msg.map_int64_int64[long(-2**33)] = long(-2**34)
+ msg.map_uint32_uint32[long(123)] = long(456)
+ msg.map_uint64_uint64[long(2**33)] = long(2**34)
+
+ serialized = msg.SerializeToString()
+ msg2 = map_unittest_pb2.TestMap()
+ msg2.ParseFromString(serialized)
+
+ self.assertEqual(-456, msg2.map_int32_int32[-123])
+ self.assertEqual(-2**34, msg2.map_int64_int64[-2**33])
+ self.assertEqual(456, msg2.map_uint32_uint32[123])
+ self.assertEqual(2**34, msg2.map_uint64_uint64[2**33])
+
+ def testMapAssignmentCausesPresence(self):
+ msg = map_unittest_pb2.TestMapSubmessage()
+ msg.test_map.map_int32_int32[123] = 456
+
+ serialized = msg.SerializeToString()
+ msg2 = map_unittest_pb2.TestMapSubmessage()
+ msg2.ParseFromString(serialized)
+
+ self.assertEqual(msg, msg2)
+
+ # Now test that various mutations of the map properly invalidate the
+ # cached size of the submessage.
+ msg.test_map.map_int32_int32[888] = 999
+ serialized = msg.SerializeToString()
+ msg2.ParseFromString(serialized)
+ self.assertEqual(msg, msg2)
+
+ msg.test_map.map_int32_int32.clear()
+ serialized = msg.SerializeToString()
+ msg2.ParseFromString(serialized)
+ self.assertEqual(msg, msg2)
+
+ def testMapAssignmentCausesPresenceForSubmessages(self):
+ msg = map_unittest_pb2.TestMapSubmessage()
+ msg.test_map.map_int32_foreign_message[123].c = 5
+
+ serialized = msg.SerializeToString()
+ msg2 = map_unittest_pb2.TestMapSubmessage()
+ msg2.ParseFromString(serialized)
+
+ self.assertEqual(msg, msg2)
+
+ # Now test that various mutations of the map properly invalidate the
+ # cached size of the submessage.
+ msg.test_map.map_int32_foreign_message[888].c = 7
+ serialized = msg.SerializeToString()
+ msg2.ParseFromString(serialized)
+ self.assertEqual(msg, msg2)
+
+ msg.test_map.map_int32_foreign_message[888].MergeFrom(
+ msg.test_map.map_int32_foreign_message[123])
+ serialized = msg.SerializeToString()
+ msg2.ParseFromString(serialized)
+ self.assertEqual(msg, msg2)
+
+ msg.test_map.map_int32_foreign_message.clear()
+ serialized = msg.SerializeToString()
+ msg2.ParseFromString(serialized)
+ self.assertEqual(msg, msg2)
+
+ def testModifyMapWhileIterating(self):
+ msg = map_unittest_pb2.TestMap()
+
+ string_string_iter = iter(msg.map_string_string)
+ int32_foreign_iter = iter(msg.map_int32_foreign_message)
+
+ msg.map_string_string['abc'] = '123'
+ msg.map_int32_foreign_message[5].c = 5
+
+ with self.assertRaises(RuntimeError):
+ for key in string_string_iter:
+ pass
+
+ with self.assertRaises(RuntimeError):
+ for key in int32_foreign_iter:
+ pass
+
+ def testSubmessageMap(self):
+ msg = map_unittest_pb2.TestMap()
+
+ submsg = msg.map_int32_foreign_message[111]
+ self.assertIs(submsg, msg.map_int32_foreign_message[111])
+ self.assertTrue(isinstance(submsg, unittest_pb2.ForeignMessage))
+
+ submsg.c = 5
+
+ serialized = msg.SerializeToString()
+ msg2 = map_unittest_pb2.TestMap()
+ msg2.ParseFromString(serialized)
+
+ self.assertEqual(5, msg2.map_int32_foreign_message[111].c)
+
+ # Doesn't allow direct submessage assignment.
+ with self.assertRaises(ValueError):
+ msg.map_int32_foreign_message[88] = unittest_pb2.ForeignMessage()
+
+ def testMapIteration(self):
+ msg = map_unittest_pb2.TestMap()
+
+ for k, v in msg.map_int32_int32.iteritems():
+ # Should not be reached.
+ self.assertTrue(False)
+
+ msg.map_int32_int32[2] = 4
+ msg.map_int32_int32[3] = 6
+ msg.map_int32_int32[4] = 8
+ self.assertEqual(3, len(msg.map_int32_int32))
+
+ matching_dict = {2: 4, 3: 6, 4: 8}
+ self.assertMapIterEquals(msg.map_int32_int32.iteritems(), matching_dict)
+
+ def testMapIterationClearMessage(self):
+ # Iterator needs to work even if message and map are deleted.
+ msg = map_unittest_pb2.TestMap()
+
+ msg.map_int32_int32[2] = 4
+ msg.map_int32_int32[3] = 6
+ msg.map_int32_int32[4] = 8
+
+ it = msg.map_int32_int32.iteritems()
+ del msg
+
+ matching_dict = {2: 4, 3: 6, 4: 8}
+ self.assertMapIterEquals(it, matching_dict)
+
+ def testMapConstruction(self):
+ msg = map_unittest_pb2.TestMap(map_int32_int32={1: 2, 3: 4})
+ self.assertEqual(2, msg.map_int32_int32[1])
+ self.assertEqual(4, msg.map_int32_int32[3])
+
+ msg = map_unittest_pb2.TestMap(
+ map_int32_foreign_message={3: unittest_pb2.ForeignMessage(c=5)})
+ self.assertEqual(5, msg.map_int32_foreign_message[3].c)
+
+ def testMapValidAfterFieldCleared(self):
+ # Map needs to work even if field is cleared.
+ # For the C++ implementation this tests the correctness of
+ # ScalarMapContainer::Release()
+ msg = map_unittest_pb2.TestMap()
+ map = msg.map_int32_int32
+
+ map[2] = 4
+ map[3] = 6
+ map[4] = 8
+
+ msg.ClearField('map_int32_int32')
+ matching_dict = {2: 4, 3: 6, 4: 8}
+ self.assertMapIterEquals(map.iteritems(), matching_dict)
+
+ def testMapIterValidAfterFieldCleared(self):
+ # Map iterator needs to work even if field is cleared.
+ # For the C++ implementation this tests the correctness of
+ # ScalarMapContainer::Release()
+ msg = map_unittest_pb2.TestMap()
+
+ msg.map_int32_int32[2] = 4
+ msg.map_int32_int32[3] = 6
+ msg.map_int32_int32[4] = 8
+
+ it = msg.map_int32_int32.iteritems()
+
+ msg.ClearField('map_int32_int32')
+ matching_dict = {2: 4, 3: 6, 4: 8}
+ self.assertMapIterEquals(it, matching_dict)
+
+ def testMapDelete(self):
+ msg = map_unittest_pb2.TestMap()
+
+ self.assertEqual(0, len(msg.map_int32_int32))
+
+ msg.map_int32_int32[4] = 6
+ self.assertEqual(1, len(msg.map_int32_int32))
+
+ with self.assertRaises(KeyError):
+ del msg.map_int32_int32[88]
+
+ del msg.map_int32_int32[4]
+ self.assertEqual(0, len(msg.map_int32_int32))
+
+
class ValidTypeNamesTest(unittest.TestCase):
diff --git a/python/google/protobuf/internal/proto_builder_test.py b/python/google/protobuf/internal/proto_builder_test.py
index b1e57f35..edaf3fa3 100644
--- a/python/google/protobuf/internal/proto_builder_test.py
+++ b/python/google/protobuf/internal/proto_builder_test.py
@@ -32,6 +32,7 @@
"""Tests for google.protobuf.proto_builder."""
+import collections
import unittest
from google.protobuf import descriptor_pb2
@@ -43,10 +44,11 @@ from google.protobuf import text_format
class ProtoBuilderTest(unittest.TestCase):
def setUp(self):
- self._fields = {
- 'foo': descriptor_pb2.FieldDescriptorProto.TYPE_INT64,
- 'bar': descriptor_pb2.FieldDescriptorProto.TYPE_STRING,
- }
+ self.ordered_fields = collections.OrderedDict([
+ ('foo', descriptor_pb2.FieldDescriptorProto.TYPE_INT64),
+ ('bar', descriptor_pb2.FieldDescriptorProto.TYPE_STRING),
+ ])
+ self._fields = dict(self.ordered_fields)
def testMakeSimpleProtoClass(self):
"""Test that we can create a proto class."""
@@ -59,6 +61,17 @@ class ProtoBuilderTest(unittest.TestCase):
self.assertMultiLineEqual(
'bar: "asdf"\nfoo: 12345\n', text_format.MessageToString(proto))
+ def testOrderedFields(self):
+ """Test that the field order is maintained when given an OrderedDict."""
+ proto_cls = proto_builder.MakeSimpleProtoClass(
+ self.ordered_fields,
+ full_name='net.proto2.python.public.proto_builder_test.OrderedTest')
+ proto = proto_cls()
+ proto.foo = 12345
+ proto.bar = 'asdf'
+ self.assertMultiLineEqual(
+ 'foo: 12345\nbar: "asdf"\n', text_format.MessageToString(proto))
+
def testMakeSameProtoClassTwice(self):
"""Test that the DescriptorPool is used."""
pool = descriptor_pool.DescriptorPool()
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index 54f584ae..ca9f7675 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -61,9 +61,11 @@ if sys.version_info[0] < 3:
except ImportError:
from StringIO import StringIO as BytesIO
import copy_reg as copyreg
+ _basestring = basestring
else:
from io import BytesIO
import copyreg
+ _basestring = str
import struct
import weakref
@@ -77,6 +79,7 @@ from google.protobuf.internal import type_checkers
from google.protobuf.internal import wire_format
from google.protobuf import descriptor as descriptor_mod
from google.protobuf import message as message_mod
+from google.protobuf import symbol_database
from google.protobuf import text_format
_FieldDescriptor = descriptor_mod.FieldDescriptor
@@ -101,6 +104,7 @@ def InitMessage(descriptor, cls):
for field in descriptor.fields:
_AttachFieldHelpers(cls, field)
+ descriptor._concrete_class = cls # pylint: disable=protected-access
_AddEnumValues(descriptor, cls)
_AddInitMethod(descriptor, cls)
_AddPropertiesForFields(descriptor, cls)
@@ -198,12 +202,37 @@ def _IsMessageSetExtension(field):
field.label == _FieldDescriptor.LABEL_OPTIONAL)
+def _IsMapField(field):
+ return (field.type == _FieldDescriptor.TYPE_MESSAGE and
+ field.message_type.has_options and
+ field.message_type.GetOptions().map_entry)
+
+
+def _IsMessageMapField(field):
+ value_type = field.message_type.fields_by_name["value"]
+ return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE
+
+
def _AttachFieldHelpers(cls, field_descriptor):
is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
- is_packed = (field_descriptor.has_options and
- field_descriptor.GetOptions().packed)
-
- if _IsMessageSetExtension(field_descriptor):
+ is_packable = (is_repeated and
+ wire_format.IsTypePackable(field_descriptor.type))
+ if not is_packable:
+ is_packed = False
+ elif field_descriptor.containing_type.syntax == "proto2":
+ is_packed = (field_descriptor.has_options and
+ field_descriptor.GetOptions().packed)
+ else:
+ has_packed_false = (field_descriptor.has_options and
+ field_descriptor.GetOptions().HasField("packed") and
+ field_descriptor.GetOptions().packed == False)
+ is_packed = not has_packed_false
+ is_map_entry = _IsMapField(field_descriptor)
+
+ if is_map_entry:
+ field_encoder = encoder.MapEncoder(field_descriptor)
+ sizer = encoder.MapSizer(field_descriptor)
+ elif _IsMessageSetExtension(field_descriptor):
field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number)
sizer = encoder.MessageSetItemSizer(field_descriptor.number)
else:
@@ -228,9 +257,16 @@ def _AttachFieldHelpers(cls, field_descriptor):
if field_descriptor.containing_oneof is not None:
oneof_descriptor = field_descriptor
- field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
- field_descriptor.number, is_repeated, is_packed,
- field_descriptor, field_descriptor._default_constructor)
+ if is_map_entry:
+ is_message_map = _IsMessageMapField(field_descriptor)
+
+ field_decoder = decoder.MapDecoder(
+ field_descriptor, _GetInitializeDefaultForMap(field_descriptor),
+ is_message_map)
+ else:
+ field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
+ field_descriptor.number, is_repeated, is_packed,
+ field_descriptor, field_descriptor._default_constructor)
cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor)
@@ -265,6 +301,26 @@ def _AddEnumValues(descriptor, cls):
setattr(cls, enum_value.name, enum_value.number)
+def _GetInitializeDefaultForMap(field):
+ if field.label != _FieldDescriptor.LABEL_REPEATED:
+ raise ValueError('map_entry set on non-repeated field %s' % (
+ field.name))
+ fields_by_name = field.message_type.fields_by_name
+ key_checker = type_checkers.GetTypeChecker(fields_by_name['key'])
+
+ value_field = fields_by_name['value']
+ if _IsMessageMapField(field):
+ def MakeMessageMapDefault(message):
+ return containers.MessageMap(
+ message._listener_for_children, value_field.message_type, key_checker)
+ return MakeMessageMapDefault
+ else:
+ value_checker = type_checkers.GetTypeChecker(value_field)
+ def MakePrimitiveMapDefault(message):
+ return containers.ScalarMap(
+ message._listener_for_children, key_checker, value_checker)
+ return MakePrimitiveMapDefault
+
def _DefaultValueConstructorForField(field):
"""Returns a function which returns a default value for a field.
@@ -279,6 +335,9 @@ def _DefaultValueConstructorForField(field):
value may refer back to |message| via a weak reference.
"""
+ if _IsMapField(field):
+ return _GetInitializeDefaultForMap(field)
+
if field.label == _FieldDescriptor.LABEL_REPEATED:
if field.has_default_value and field.default_value != []:
raise ValueError('Repeated field default value not empty list: %s' % (
@@ -329,7 +388,22 @@ def _ReraiseTypeErrorWithFieldName(message_name, field_name):
def _AddInitMethod(message_descriptor, cls):
"""Adds an __init__ method to cls."""
- fields = message_descriptor.fields
+
+ def _GetIntegerEnumValue(enum_type, value):
+ """Convert a string or integer enum value to an integer.
+
+ If the value is a string, it is converted to the enum value in
+ enum_type with the same name. If the value is not a string, it's
+ returned as-is. (No conversion or bounds-checking is done.)
+ """
+ if isinstance(value, _basestring):
+ try:
+ return enum_type.values_by_name[value].number
+ except KeyError:
+ raise ValueError('Enum type %s: unknown label "%s"' % (
+ enum_type.full_name, value))
+ return value
+
def init(self, **kwargs):
self._cached_byte_size = 0
self._cached_byte_size_dirty = len(kwargs) > 0
@@ -352,19 +426,37 @@ def _AddInitMethod(message_descriptor, cls):
if field.label == _FieldDescriptor.LABEL_REPEATED:
copy = field._default_constructor(self)
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite
- for val in field_value:
- copy.add().MergeFrom(val)
+ if _IsMapField(field):
+ if _IsMessageMapField(field):
+ for key in field_value:
+ copy[key].MergeFrom(field_value[key])
+ else:
+ copy.update(field_value)
+ else:
+ for val in field_value:
+ if isinstance(val, dict):
+ copy.add(**val)
+ else:
+ copy.add().MergeFrom(val)
else: # Scalar
+ if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
+ field_value = [_GetIntegerEnumValue(field.enum_type, val)
+ for val in field_value]
copy.extend(field_value)
self._fields[field] = copy
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
copy = field._default_constructor(self)
+ new_val = field_value
+ if isinstance(field_value, dict):
+ new_val = field.message_type._concrete_class(**field_value)
try:
- copy.MergeFrom(field_value)
+ copy.MergeFrom(new_val)
except TypeError:
_ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name)
self._fields[field] = copy
else:
+ if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
+ field_value = _GetIntegerEnumValue(field.enum_type, field_value)
try:
setattr(self, field_name, field_value)
except TypeError:
@@ -758,6 +850,26 @@ def _AddHasExtensionMethod(cls):
return extension_handle in self._fields
cls.HasExtension = HasExtension
+def _UnpackAny(msg):
+ type_url = msg.type_url
+ db = symbol_database.Default()
+
+ if not type_url:
+ return None
+
+ # TODO(haberman): For now we just strip the hostname. Better logic will be
+ # required.
+ type_name = type_url.split("/")[-1]
+ descriptor = db.pool.FindMessageTypeByName(type_name)
+
+ if descriptor is None:
+ return None
+
+ message_class = db.GetPrototype(descriptor)
+ message = message_class()
+
+ message.ParseFromString(msg.value)
+ return message
def _AddEqualsMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
@@ -769,6 +881,12 @@ def _AddEqualsMethod(message_descriptor, cls):
if self is other:
return True
+ if self.DESCRIPTOR.full_name == "google.protobuf.Any":
+ any_a = _UnpackAny(self)
+ any_b = _UnpackAny(other)
+ if any_a and any_b:
+ return any_a == any_b
+
if not self.ListFields() == other.ListFields():
return False
@@ -961,6 +1079,9 @@ def _AddIsInitializedMethod(message_descriptor, cls):
for field, value in list(self._fields.items()): # dict can change size!
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
+ if (field.message_type.has_options and
+ field.message_type.GetOptions().map_entry):
+ continue
for element in value:
if not element.IsInitialized():
if errors is not None:
@@ -996,16 +1117,26 @@ def _AddIsInitializedMethod(message_descriptor, cls):
else:
name = field.name
- if field.label == _FieldDescriptor.LABEL_REPEATED:
+ if _IsMapField(field):
+ if _IsMessageMapField(field):
+ for key in value:
+ element = value[key]
+ prefix = "%s[%d]." % (name, key)
+ sub_errors = element.FindInitializationErrors()
+ errors += [prefix + error for error in sub_errors]
+ else:
+ # ScalarMaps can't have any initialization errors.
+ pass
+ elif field.label == _FieldDescriptor.LABEL_REPEATED:
for i in xrange(len(value)):
element = value[i]
prefix = "%s[%d]." % (name, i)
sub_errors = element.FindInitializationErrors()
- errors += [ prefix + error for error in sub_errors ]
+ errors += [prefix + error for error in sub_errors]
else:
prefix = name + "."
sub_errors = value.FindInitializationErrors()
- errors += [ prefix + error for error in sub_errors ]
+ errors += [prefix + error for error in sub_errors]
return errors
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index ae79c78b..4eca4989 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -39,8 +39,8 @@ import copy
import gc
import operator
import struct
-import unittest
+import unittest
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
@@ -1798,8 +1798,8 @@ class ReflectionTest(unittest.TestCase):
def testBadArguments(self):
# Some of these assertions used to segfault.
from google.protobuf.pyext import _message
- self.assertRaises(TypeError, _message.Message._GetFieldDescriptor, 3)
- self.assertRaises(TypeError, _message.Message._GetExtensionDescriptor, 42)
+ self.assertRaises(TypeError, _message.default_pool.FindFieldByName, 3)
+ self.assertRaises(TypeError, _message.default_pool.FindExtensionByName, 42)
self.assertRaises(TypeError,
unittest_pb2.TestAllTypes().__getattribute__, 42)
diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py
index de462124..9967255a 100755
--- a/python/google/protobuf/internal/service_reflection_test.py
+++ b/python/google/protobuf/internal/service_reflection_test.py
@@ -35,7 +35,6 @@
__author__ = 'petar@google.com (Petar Petrov)'
import unittest
-
from google.protobuf import unittest_pb2
from google.protobuf import service_reflection
from google.protobuf import service
@@ -81,7 +80,7 @@ class FooUnitTest(unittest.TestCase):
self.assertEqual('Method Bar not implemented.',
rpc_controller.failure_message)
self.assertEqual(None, self.callback_response)
-
+
class MyServiceImpl(unittest_pb2.TestService):
def Foo(self, rpc_controller, request, done):
self.foo_called = True
diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py
index c888aff7..80b83bc2 100644
--- a/python/google/protobuf/internal/symbol_database_test.py
+++ b/python/google/protobuf/internal/symbol_database_test.py
@@ -33,7 +33,6 @@
"""Tests for google.protobuf.symbol_database."""
import unittest
-
from google.protobuf import unittest_pb2
from google.protobuf import symbol_database
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index d84e3836..0cbdbad9 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -75,7 +75,8 @@ def SetAllNonLazyFields(message):
message.optional_string = u'115'
message.optional_bytes = b'116'
- message.optionalgroup.a = 117
+ if IsProto2(message):
+ message.optionalgroup.a = 117
message.optional_nested_message.bb = 118
message.optional_foreign_message.c = 119
message.optional_import_message.d = 120
@@ -109,7 +110,8 @@ def SetAllNonLazyFields(message):
message.repeated_string.append(u'215')
message.repeated_bytes.append(b'216')
- message.repeatedgroup.add().a = 217
+ if IsProto2(message):
+ message.repeatedgroup.add().a = 217
message.repeated_nested_message.add().bb = 218
message.repeated_foreign_message.add().c = 219
message.repeated_import_message.add().d = 220
@@ -140,7 +142,8 @@ def SetAllNonLazyFields(message):
message.repeated_string.append(u'315')
message.repeated_bytes.append(b'316')
- message.repeatedgroup.add().a = 317
+ if IsProto2(message):
+ message.repeatedgroup.add().a = 317
message.repeated_nested_message.add().bb = 318
message.repeated_foreign_message.add().c = 319
message.repeated_import_message.add().d = 320
@@ -396,7 +399,8 @@ def ExpectAllFieldsSet(test_case, message):
test_case.assertTrue(message.HasField('optional_string'))
test_case.assertTrue(message.HasField('optional_bytes'))
- test_case.assertTrue(message.HasField('optionalgroup'))
+ if IsProto2(message):
+ test_case.assertTrue(message.HasField('optionalgroup'))
test_case.assertTrue(message.HasField('optional_nested_message'))
test_case.assertTrue(message.HasField('optional_foreign_message'))
test_case.assertTrue(message.HasField('optional_import_message'))
@@ -430,7 +434,8 @@ def ExpectAllFieldsSet(test_case, message):
test_case.assertEqual('115', message.optional_string)
test_case.assertEqual(b'116', message.optional_bytes)
- test_case.assertEqual(117, message.optionalgroup.a)
+ if IsProto2(message):
+ test_case.assertEqual(117, message.optionalgroup.a)
test_case.assertEqual(118, message.optional_nested_message.bb)
test_case.assertEqual(119, message.optional_foreign_message.c)
test_case.assertEqual(120, message.optional_import_message.d)
@@ -463,7 +468,8 @@ def ExpectAllFieldsSet(test_case, message):
test_case.assertEqual(2, len(message.repeated_string))
test_case.assertEqual(2, len(message.repeated_bytes))
- test_case.assertEqual(2, len(message.repeatedgroup))
+ if IsProto2(message):
+ test_case.assertEqual(2, len(message.repeatedgroup))
test_case.assertEqual(2, len(message.repeated_nested_message))
test_case.assertEqual(2, len(message.repeated_foreign_message))
test_case.assertEqual(2, len(message.repeated_import_message))
@@ -491,7 +497,8 @@ def ExpectAllFieldsSet(test_case, message):
test_case.assertEqual('215', message.repeated_string[0])
test_case.assertEqual(b'216', message.repeated_bytes[0])
- test_case.assertEqual(217, message.repeatedgroup[0].a)
+ if IsProto2(message):
+ test_case.assertEqual(217, message.repeatedgroup[0].a)
test_case.assertEqual(218, message.repeated_nested_message[0].bb)
test_case.assertEqual(219, message.repeated_foreign_message[0].c)
test_case.assertEqual(220, message.repeated_import_message[0].d)
@@ -521,7 +528,8 @@ def ExpectAllFieldsSet(test_case, message):
test_case.assertEqual('315', message.repeated_string[1])
test_case.assertEqual(b'316', message.repeated_bytes[1])
- test_case.assertEqual(317, message.repeatedgroup[1].a)
+ if IsProto2(message):
+ test_case.assertEqual(317, message.repeatedgroup[1].a)
test_case.assertEqual(318, message.repeated_nested_message[1].bb)
test_case.assertEqual(319, message.repeated_foreign_message[1].c)
test_case.assertEqual(320, message.repeated_import_message[1].d)
diff --git a/python/google/protobuf/internal/text_encoding_test.py b/python/google/protobuf/internal/text_encoding_test.py
index 27896b94..5df13b78 100755
--- a/python/google/protobuf/internal/text_encoding_test.py
+++ b/python/google/protobuf/internal/text_encoding_test.py
@@ -33,7 +33,6 @@
"""Tests for google.protobuf.text_encoding."""
import unittest
-
from google.protobuf import text_encoding
TEST_VALUES = [
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index bf7e06ee..06bd1ee5 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -37,8 +37,10 @@ __author__ = 'kenton@google.com (Kenton Varda)'
import re
import unittest
+import unittest
from google.protobuf.internal import _parameterized
+from google.protobuf import map_unittest_pb2
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_proto3_arena_pb2
@@ -309,31 +311,6 @@ class TextFormatTest(TextFormatBase):
r'"unknown_field".'),
text_format.Parse, text, message)
- def testParseGroupNotClosed(self, message_module):
- message = message_module.TestAllTypes()
- text = 'RepeatedGroup: <'
- self.assertRaisesRegexp(
- text_format.ParseError, '1:16 : Expected ">".',
- text_format.Parse, text, message)
-
- text = 'RepeatedGroup: {'
- self.assertRaisesRegexp(
- text_format.ParseError, '1:16 : Expected "}".',
- text_format.Parse, text, message)
-
- def testParseEmptyGroup(self, message_module):
- message = message_module.TestAllTypes()
- text = 'OptionalGroup: {}'
- text_format.Parse(text, message)
- self.assertTrue(message.HasField('optionalgroup'))
-
- message.Clear()
-
- message = message_module.TestAllTypes()
- text = 'OptionalGroup: <>'
- text_format.Parse(text, message)
- self.assertTrue(message.HasField('optionalgroup'))
-
def testParseBadEnumValue(self, message_module):
message = message_module.TestAllTypes()
text = 'optional_nested_enum: BARR'
@@ -408,6 +385,14 @@ class TextFormatTest(TextFormatBase):
# Ideally the schemas would be made more similar so these tests could pass.
class OnlyWorksWithProto2RightNowTests(TextFormatBase):
+ def testPrintAllFieldsPointy(self, message_module):
+ message = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(message)
+ self.CompareToGoldenFile(
+ self.RemoveRedundantZeros(
+ text_format.MessageToString(message, pointy_brackets=True)),
+ 'text_format_unittest_data_pointy_oneof.txt')
+
def testParseGolden(self):
golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
parsed_message = unittest_pb2.TestAllTypes()
@@ -471,8 +456,49 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
test_util.SetAllFields(message)
self.assertEquals(message, parsed_message)
+ def testPrintMap(self):
+ message = map_unittest_pb2.TestMap()
-# Tests of proto2-only features (MessageSet and extensions).
+ message.map_int32_int32[-123] = -456
+ message.map_int64_int64[-2**33] = -2**34
+ message.map_uint32_uint32[123] = 456
+ message.map_uint64_uint64[2**33] = 2**34
+ message.map_string_string["abc"] = "123"
+ message.map_int32_foreign_message[111].c = 5
+
+ # Maps are serialized to text format using their underlying repeated
+ # representation.
+ self.CompareToGoldenText(
+ text_format.MessageToString(message),
+ 'map_int32_int32 {\n'
+ ' key: -123\n'
+ ' value: -456\n'
+ '}\n'
+ 'map_int64_int64 {\n'
+ ' key: -8589934592\n'
+ ' value: -17179869184\n'
+ '}\n'
+ 'map_uint32_uint32 {\n'
+ ' key: 123\n'
+ ' value: 456\n'
+ '}\n'
+ 'map_uint64_uint64 {\n'
+ ' key: 8589934592\n'
+ ' value: 17179869184\n'
+ '}\n'
+ 'map_string_string {\n'
+ ' key: "abc"\n'
+ ' value: "123"\n'
+ '}\n'
+ 'map_int32_foreign_message {\n'
+ ' key: 111\n'
+ ' value {\n'
+ ' c: 5\n'
+ ' }\n'
+ '}\n')
+
+
+# Tests of proto2-only features (MessageSet, extensions, etc.).
class Proto2Tests(TextFormatBase):
def testPrintMessageSet(self):
@@ -620,6 +646,69 @@ class Proto2Tests(TextFormatBase):
'have multiple "optional_int32" fields.'),
text_format.Parse, text, message)
+ def testParseGroupNotClosed(self):
+ message = unittest_pb2.TestAllTypes()
+ text = 'RepeatedGroup: <'
+ self.assertRaisesRegexp(
+ text_format.ParseError, '1:16 : Expected ">".',
+ text_format.Parse, text, message)
+ text = 'RepeatedGroup: {'
+ self.assertRaisesRegexp(
+ text_format.ParseError, '1:16 : Expected "}".',
+ text_format.Parse, text, message)
+
+ def testParseEmptyGroup(self):
+ message = unittest_pb2.TestAllTypes()
+ text = 'OptionalGroup: {}'
+ text_format.Parse(text, message)
+ self.assertTrue(message.HasField('optionalgroup'))
+
+ message.Clear()
+
+ message = unittest_pb2.TestAllTypes()
+ text = 'OptionalGroup: <>'
+ text_format.Parse(text, message)
+ self.assertTrue(message.HasField('optionalgroup'))
+
+ # Maps aren't really proto2-only, but our test schema only has maps for
+ # proto2.
+ def testParseMap(self):
+ text = ('map_int32_int32 {\n'
+ ' key: -123\n'
+ ' value: -456\n'
+ '}\n'
+ 'map_int64_int64 {\n'
+ ' key: -8589934592\n'
+ ' value: -17179869184\n'
+ '}\n'
+ 'map_uint32_uint32 {\n'
+ ' key: 123\n'
+ ' value: 456\n'
+ '}\n'
+ 'map_uint64_uint64 {\n'
+ ' key: 8589934592\n'
+ ' value: 17179869184\n'
+ '}\n'
+ 'map_string_string {\n'
+ ' key: "abc"\n'
+ ' value: "123"\n'
+ '}\n'
+ 'map_int32_foreign_message {\n'
+ ' key: 111\n'
+ ' value {\n'
+ ' c: 5\n'
+ ' }\n'
+ '}\n')
+ message = map_unittest_pb2.TestMap()
+ text_format.Parse(text, message)
+
+ self.assertEqual(-456, message.map_int32_int32[-123])
+ self.assertEqual(-2**34, message.map_int64_int64[-2**33])
+ self.assertEqual(456, message.map_uint32_uint32[123])
+ self.assertEqual(2**34, message.map_uint64_uint64[2**33])
+ self.assertEqual("123", message.map_string_string["abc"])
+ self.assertEqual(5, message.map_int32_foreign_message[111].c)
+
class TokenizerTest(unittest.TestCase):
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index 76c056c4..f20e526a 100755
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -129,6 +129,9 @@ class IntValueChecker(object):
proposed_value = self._TYPE(proposed_value)
return proposed_value
+ def DefaultValue(self):
+ return 0
+
class EnumValueChecker(object):
@@ -146,6 +149,9 @@ class EnumValueChecker(object):
raise ValueError('Unknown enum value: %d' % proposed_value)
return proposed_value
+ def DefaultValue(self):
+ return self._enum_type.values[0].number
+
class UnicodeValueChecker(object):
@@ -171,6 +177,9 @@ class UnicodeValueChecker(object):
(proposed_value))
return proposed_value
+ def DefaultValue(self):
+ return u""
+
class Int32ValueChecker(IntValueChecker):
# We're sure to use ints instead of longs here since comparison may be more
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index 9337ae8a..1b81ae79 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -36,7 +36,6 @@
__author__ = 'bohdank@google.com (Bohdan Koval)'
import unittest
-
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_proto3_arena_pb2
diff --git a/python/google/protobuf/internal/wire_format_test.py b/python/google/protobuf/internal/wire_format_test.py
index 5cd7fcb9..78dc1167 100755
--- a/python/google/protobuf/internal/wire_format_test.py
+++ b/python/google/protobuf/internal/wire_format_test.py
@@ -35,7 +35,6 @@
__author__ = 'robinson@google.com (Will Robinson)'
import unittest
-
from google.protobuf import message
from google.protobuf.internal import wire_format
diff --git a/python/google/protobuf/proto_builder.py b/python/google/protobuf/proto_builder.py
index 1fa28f1a..7489cf63 100644
--- a/python/google/protobuf/proto_builder.py
+++ b/python/google/protobuf/proto_builder.py
@@ -30,6 +30,7 @@
"""Dynamic Protobuf class creator."""
+import collections
import hashlib
import os
@@ -59,7 +60,9 @@ def MakeSimpleProtoClass(fields, full_name, pool=None):
Note: this doesn't validate field names!
Args:
- fields: dict of {name: field_type} mappings for each field in the proto.
+ fields: dict of {name: field_type} mappings for each field in the proto. If
+ this is an OrderedDict the order will be maintained, otherwise the
+ fields will be sorted by name.
full_name: str, the fully-qualified name of the proto type.
pool: optional DescriptorPool instance.
Returns:
@@ -73,12 +76,19 @@ def MakeSimpleProtoClass(fields, full_name, pool=None):
# The factory's DescriptorPool doesn't know about this class yet.
pass
+ # Get a list of (name, field_type) tuples from the fields dict. If fields was
+ # an OrderedDict we keep the order, but otherwise we sort the field to ensure
+ # consistent ordering.
+ field_items = fields.items()
+ if not isinstance(fields, collections.OrderedDict):
+ field_items = sorted(field_items)
+
# 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'))
+ for f_name, f_type in field_items:
+ fields_hash.update(f_name.encode('utf-8'))
+ fields_hash.update(str(f_type).encode('utf-8'))
proto_file_name = fields_hash.hexdigest() + '.proto'
package, name = full_name.rsplit('.', 1)
@@ -87,7 +97,7 @@ def MakeSimpleProtoClass(fields, full_name, pool=None):
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):
+ for f_number, (f_name, f_type) in enumerate(field_items, 1):
field_proto = desc_proto.field.add()
field_proto.name = f_name
field_proto.number = f_number
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index e77d0bb9..2160757b 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -43,8 +43,6 @@
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
-#define C(str) const_cast<char*>(str)
-
#if PY_MAJOR_VERSION >= 3
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#define PyString_Check PyUnicode_Check
@@ -257,8 +255,14 @@ namespace descriptor {
// Creates or retrieve a Python descriptor of the specified type.
// Objects are interned: the same descriptor will return the same object if it
// was kept alive.
+// 'was_created' is an optional pointer to a bool, and is set to true if a new
+// object was allocated.
// Always return a new reference.
-PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor) {
+PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor,
+ bool* was_created) {
+ if (was_created) {
+ *was_created = false;
+ }
if (descriptor == NULL) {
PyErr_BadInternalCall();
return NULL;
@@ -283,6 +287,9 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor) {
GetDescriptorPool()->interned_descriptors->insert(
std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
+ if (was_created) {
+ *was_created = true;
+ }
return reinterpret_cast<PyObject*>(py_descriptor);
}
@@ -298,9 +305,7 @@ static PyGetSetDef Getters[] = {
PyTypeObject PyBaseDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- // Keep the fully qualified _message symbol in a line for opensource.
- "google.protobuf.internal._message."
- "DescriptorBase", // tp_name
+ FULL_MODULE_NAME ".DescriptorBase", // tp_name
sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
(destructor)Dealloc, // tp_dealloc
@@ -357,7 +362,7 @@ static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
}
static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
- return PyFileDescriptor_New(_GetDescriptor(self)->file());
+ return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
}
static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
@@ -367,17 +372,6 @@ static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
return concrete_class;
}
-static int SetConcreteClass(PyBaseDescriptor *self, PyObject *value,
- void *closure) {
- // This attribute is also set from reflection.py. Check that it's actually a
- // no-op.
- if (value != cdescriptor_pool::GetMessageClass(
- GetDescriptorPool(), _GetDescriptor(self))) {
- PyErr_SetString(PyExc_AttributeError, "Cannot change _concrete_class");
- }
- return 0;
-}
-
static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) {
return NewMessageFieldsByName(_GetDescriptor(self));
}
@@ -452,7 +446,7 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
const Descriptor* containing_type =
_GetDescriptor(self)->containing_type();
if (containing_type) {
- return PyMessageDescriptor_New(containing_type);
+ return PyMessageDescriptor_FromDescriptor(containing_type);
} else {
Py_RETURN_NONE;
}
@@ -515,29 +509,34 @@ static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
}
static PyGetSetDef Getters[] = {
- { C("name"), (getter)GetName, NULL, "Last name", NULL},
- { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
- { C("_concrete_class"), (getter)GetConcreteClass, (setter)SetConcreteClass, "concrete class", NULL},
- { C("file"), (getter)GetFile, NULL, "File descriptor", NULL},
-
- { C("fields"), (getter)GetFieldsSeq, NULL, "Fields sequence", NULL},
- { C("fields_by_name"), (getter)GetFieldsByName, NULL, "Fields by name", NULL},
- { C("fields_by_number"), (getter)GetFieldsByNumber, NULL, "Fields by number", NULL},
- { C("nested_types"), (getter)GetNestedTypesSeq, NULL, "Nested types sequence", NULL},
- { C("nested_types_by_name"), (getter)GetNestedTypesByName, NULL, "Nested types by name", NULL},
- { C("extensions"), (getter)GetExtensions, NULL, "Extensions Sequence", NULL},
- { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL},
- { C("extension_ranges"), (getter)GetExtensionRanges, NULL, "Extension ranges", NULL},
- { C("enum_types"), (getter)GetEnumsSeq, NULL, "Enum sequence", NULL},
- { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enum types by name", NULL},
- { C("enum_values_by_name"), (getter)GetEnumValuesByName, NULL, "Enum values by name", NULL},
- { C("oneofs_by_name"), (getter)GetOneofsByName, NULL, "Oneofs by name", NULL},
- { C("oneofs"), (getter)GetOneofsSeq, NULL, "Oneofs by name", NULL},
- { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL},
- { C("is_extendable"), (getter)IsExtendable, (setter)NULL, NULL, NULL},
- { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
- { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
- { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL},
+ { "name", (getter)GetName, NULL, "Last name"},
+ { "full_name", (getter)GetFullName, NULL, "Full name"},
+ { "_concrete_class", (getter)GetConcreteClass, NULL, "concrete class"},
+ { "file", (getter)GetFile, NULL, "File descriptor"},
+
+ { "fields", (getter)GetFieldsSeq, NULL, "Fields sequence"},
+ { "fields_by_name", (getter)GetFieldsByName, NULL, "Fields by name"},
+ { "fields_by_number", (getter)GetFieldsByNumber, NULL, "Fields by number"},
+ { "nested_types", (getter)GetNestedTypesSeq, NULL, "Nested types sequence"},
+ { "nested_types_by_name", (getter)GetNestedTypesByName, NULL,
+ "Nested types by name"},
+ { "extensions", (getter)GetExtensions, NULL, "Extensions Sequence"},
+ { "extensions_by_name", (getter)GetExtensionsByName, NULL,
+ "Extensions by name"},
+ { "extension_ranges", (getter)GetExtensionRanges, NULL, "Extension ranges"},
+ { "enum_types", (getter)GetEnumsSeq, NULL, "Enum sequence"},
+ { "enum_types_by_name", (getter)GetEnumTypesByName, NULL,
+ "Enum types by name"},
+ { "enum_values_by_name", (getter)GetEnumValuesByName, NULL,
+ "Enum values by name"},
+ { "oneofs_by_name", (getter)GetOneofsByName, NULL, "Oneofs by name"},
+ { "oneofs", (getter)GetOneofsSeq, NULL, "Oneofs by name"},
+ { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
+ "Containing type"},
+ { "is_extendable", (getter)IsExtendable, (setter)NULL},
+ { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+ { "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
{NULL}
};
@@ -552,9 +551,7 @@ static PyMethodDef Methods[] = {
PyTypeObject PyMessageDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- // Keep the fully qualified _message symbol in a line for opensource.
- C("google.protobuf.internal._message."
- "MessageDescriptor"), // tp_name
+ FULL_MODULE_NAME ".MessageDescriptor", // tp_name
sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
@@ -573,7 +570,7 @@ PyTypeObject PyMessageDescriptor_Type = {
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
- C("A Message Descriptor"), // tp_doc
+ "A Message Descriptor", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
@@ -586,10 +583,10 @@ PyTypeObject PyMessageDescriptor_Type = {
&descriptor::PyBaseDescriptor_Type, // tp_base
};
-PyObject* PyMessageDescriptor_New(
+PyObject* PyMessageDescriptor_FromDescriptor(
const Descriptor* message_descriptor) {
return descriptor::NewInternedDescriptor(
- &PyMessageDescriptor_Type, message_descriptor);
+ &PyMessageDescriptor_Type, message_descriptor, NULL);
}
const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) {
@@ -715,7 +712,7 @@ static PyObject* GetCDescriptor(PyObject *self, void *closure) {
static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) {
const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type();
if (enum_type) {
- return PyEnumDescriptor_New(enum_type);
+ return PyEnumDescriptor_FromDescriptor(enum_type);
} else {
Py_RETURN_NONE;
}
@@ -728,7 +725,7 @@ static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) {
static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) {
const Descriptor* message_type = _GetDescriptor(self)->message_type();
if (message_type) {
- return PyMessageDescriptor_New(message_type);
+ return PyMessageDescriptor_FromDescriptor(message_type);
} else {
Py_RETURN_NONE;
}
@@ -743,7 +740,7 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
const Descriptor* containing_type =
_GetDescriptor(self)->containing_type();
if (containing_type) {
- return PyMessageDescriptor_New(containing_type);
+ return PyMessageDescriptor_FromDescriptor(containing_type);
} else {
Py_RETURN_NONE;
}
@@ -758,7 +755,7 @@ static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) {
const Descriptor* extension_scope =
_GetDescriptor(self)->extension_scope();
if (extension_scope) {
- return PyMessageDescriptor_New(extension_scope);
+ return PyMessageDescriptor_FromDescriptor(extension_scope);
} else {
Py_RETURN_NONE;
}
@@ -768,7 +765,7 @@ static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) {
const OneofDescriptor* containing_oneof =
_GetDescriptor(self)->containing_oneof();
if (containing_oneof) {
- return PyOneofDescriptor_New(containing_oneof);
+ return PyOneofDescriptor_FromDescriptor(containing_oneof);
} else {
Py_RETURN_NONE;
}
@@ -803,26 +800,30 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
static PyGetSetDef Getters[] = {
- { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
- { C("name"), (getter)GetName, NULL, "Unqualified name", NULL},
- { C("type"), (getter)GetType, NULL, "C++ Type", NULL},
- { C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL},
- { C("label"), (getter)GetLabel, NULL, "Label", NULL},
- { C("number"), (getter)GetNumber, NULL, "Number", NULL},
- { C("index"), (getter)GetIndex, NULL, "Index", NULL},
- { C("default_value"), (getter)GetDefaultValue, NULL, "Default Value", NULL},
- { C("has_default_value"), (getter)HasDefaultValue, NULL, NULL, NULL},
- { C("is_extension"), (getter)IsExtension, NULL, "ID", NULL},
- { C("id"), (getter)GetID, NULL, "ID", NULL},
- { C("_cdescriptor"), (getter)GetCDescriptor, NULL, "HAACK REMOVE ME", NULL},
-
- { C("message_type"), (getter)GetMessageType, (setter)SetMessageType, "Message type", NULL},
- { C("enum_type"), (getter)GetEnumType, (setter)SetEnumType, "Enum type", NULL},
- { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL},
- { C("extension_scope"), (getter)GetExtensionScope, (setter)NULL, "Extension scope", NULL},
- { C("containing_oneof"), (getter)GetContainingOneof, (setter)SetContainingOneof, "Containing oneof", NULL},
- { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
- { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+ { "full_name", (getter)GetFullName, NULL, "Full name"},
+ { "name", (getter)GetName, NULL, "Unqualified name"},
+ { "type", (getter)GetType, NULL, "C++ Type"},
+ { "cpp_type", (getter)GetCppType, NULL, "C++ Type"},
+ { "label", (getter)GetLabel, NULL, "Label"},
+ { "number", (getter)GetNumber, NULL, "Number"},
+ { "index", (getter)GetIndex, NULL, "Index"},
+ { "default_value", (getter)GetDefaultValue, NULL, "Default Value"},
+ { "has_default_value", (getter)HasDefaultValue},
+ { "is_extension", (getter)IsExtension, NULL, "ID"},
+ { "id", (getter)GetID, NULL, "ID"},
+ { "_cdescriptor", (getter)GetCDescriptor, NULL, "HAACK REMOVE ME"},
+
+ { "message_type", (getter)GetMessageType, (setter)SetMessageType,
+ "Message type"},
+ { "enum_type", (getter)GetEnumType, (setter)SetEnumType, "Enum type"},
+ { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
+ "Containing type"},
+ { "extension_scope", (getter)GetExtensionScope, (setter)NULL,
+ "Extension scope"},
+ { "containing_oneof", (getter)GetContainingOneof, (setter)SetContainingOneof,
+ "Containing oneof"},
+ { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+ { "_options", (getter)NULL, (setter)SetOptions, "Options"},
{NULL}
};
@@ -835,8 +836,7 @@ static PyMethodDef Methods[] = {
PyTypeObject PyFieldDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- C("google.protobuf.internal."
- "_message.FieldDescriptor"), // tp_name
+ FULL_MODULE_NAME ".FieldDescriptor", // tp_name
sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
@@ -855,7 +855,7 @@ PyTypeObject PyFieldDescriptor_Type = {
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
- C("A Field Descriptor"), // tp_doc
+ "A Field Descriptor", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
@@ -868,10 +868,10 @@ PyTypeObject PyFieldDescriptor_Type = {
&descriptor::PyBaseDescriptor_Type, // tp_base
};
-PyObject* PyFieldDescriptor_New(
+PyObject* PyFieldDescriptor_FromDescriptor(
const FieldDescriptor* field_descriptor) {
return descriptor::NewInternedDescriptor(
- &PyFieldDescriptor_Type, field_descriptor);
+ &PyFieldDescriptor_Type, field_descriptor, NULL);
}
const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) {
@@ -900,7 +900,7 @@ static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
}
static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
- return PyFileDescriptor_New(_GetDescriptor(self)->file());
+ return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
}
static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) {
@@ -919,7 +919,7 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
const Descriptor* containing_type =
_GetDescriptor(self)->containing_type();
if (containing_type) {
- return PyMessageDescriptor_New(containing_type);
+ return PyMessageDescriptor_FromDescriptor(containing_type);
} else {
Py_RETURN_NONE;
}
@@ -964,16 +964,19 @@ static PyMethodDef Methods[] = {
};
static PyGetSetDef Getters[] = {
- { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
- { C("name"), (getter)GetName, NULL, "last name", NULL},
- { C("file"), (getter)GetFile, NULL, "File descriptor", NULL},
- { C("values"), (getter)GetEnumvaluesSeq, NULL, "values", NULL},
- { C("values_by_name"), (getter)GetEnumvaluesByName, NULL, "Enumvalues by name", NULL},
- { C("values_by_number"), (getter)GetEnumvaluesByNumber, NULL, "Enumvalues by number", NULL},
-
- { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL},
- { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
- { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+ { "full_name", (getter)GetFullName, NULL, "Full name"},
+ { "name", (getter)GetName, NULL, "last name"},
+ { "file", (getter)GetFile, NULL, "File descriptor"},
+ { "values", (getter)GetEnumvaluesSeq, NULL, "values"},
+ { "values_by_name", (getter)GetEnumvaluesByName, NULL,
+ "Enum values by name"},
+ { "values_by_number", (getter)GetEnumvaluesByNumber, NULL,
+ "Enum values by number"},
+
+ { "containing_type", (getter)GetContainingType, (setter)SetContainingType,
+ "Containing type"},
+ { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+ { "_options", (getter)NULL, (setter)SetOptions, "Options"},
{NULL}
};
@@ -981,9 +984,7 @@ static PyGetSetDef Getters[] = {
PyTypeObject PyEnumDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- // Keep the fully qualified _message symbol in a line for opensource.
- C("google.protobuf.internal._message."
- "EnumDescriptor"), // tp_name
+ FULL_MODULE_NAME ".EnumDescriptor", // tp_name
sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
@@ -1002,7 +1003,7 @@ PyTypeObject PyEnumDescriptor_Type = {
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
- C("A Enum Descriptor"), // tp_doc
+ "A Enum Descriptor", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
@@ -1015,10 +1016,10 @@ PyTypeObject PyEnumDescriptor_Type = {
&descriptor::PyBaseDescriptor_Type, // tp_base
};
-PyObject* PyEnumDescriptor_New(
+PyObject* PyEnumDescriptor_FromDescriptor(
const EnumDescriptor* enum_descriptor) {
return descriptor::NewInternedDescriptor(
- &PyEnumDescriptor_Type, enum_descriptor);
+ &PyEnumDescriptor_Type, enum_descriptor, NULL);
}
namespace enumvalue_descriptor {
@@ -1042,7 +1043,7 @@ static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
}
static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
- return PyEnumDescriptor_New(_GetDescriptor(self)->type());
+ return PyEnumDescriptor_FromDescriptor(_GetDescriptor(self)->type());
}
static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
@@ -1069,13 +1070,13 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value,
static PyGetSetDef Getters[] = {
- { C("name"), (getter)GetName, NULL, "name", NULL},
- { C("number"), (getter)GetNumber, NULL, "number", NULL},
- { C("index"), (getter)GetIndex, NULL, "index", NULL},
- { C("type"), (getter)GetType, NULL, "index", NULL},
+ { "name", (getter)GetName, NULL, "name"},
+ { "number", (getter)GetNumber, NULL, "number"},
+ { "index", (getter)GetIndex, NULL, "index"},
+ { "type", (getter)GetType, NULL, "index"},
- { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
- { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+ { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+ { "_options", (getter)NULL, (setter)SetOptions, "Options"},
{NULL}
};
@@ -1088,8 +1089,7 @@ static PyMethodDef Methods[] = {
PyTypeObject PyEnumValueDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- C("google.protobuf.internal."
- "_message.EnumValueDescriptor"), // tp_name
+ FULL_MODULE_NAME ".EnumValueDescriptor", // tp_name
sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
@@ -1108,7 +1108,7 @@ PyTypeObject PyEnumValueDescriptor_Type = {
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
- C("A EnumValue Descriptor"), // tp_doc
+ "A EnumValue Descriptor", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
@@ -1121,10 +1121,10 @@ PyTypeObject PyEnumValueDescriptor_Type = {
&descriptor::PyBaseDescriptor_Type, // tp_base
};
-PyObject* PyEnumValueDescriptor_New(
+PyObject* PyEnumValueDescriptor_FromDescriptor(
const EnumValueDescriptor* enumvalue_descriptor) {
return descriptor::NewInternedDescriptor(
- &PyEnumValueDescriptor_Type, enumvalue_descriptor);
+ &PyEnumValueDescriptor_Type, enumvalue_descriptor, NULL);
}
namespace file_descriptor {
@@ -1218,18 +1218,20 @@ static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) {
}
static PyGetSetDef Getters[] = {
- { C("name"), (getter)GetName, NULL, "name", NULL},
- { C("package"), (getter)GetPackage, NULL, "package", NULL},
- { C("serialized_pb"), (getter)GetSerializedPb, NULL, NULL, NULL},
- { C("message_types_by_name"), (getter)GetMessageTypesByName, NULL, "Messages by name", NULL},
- { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enums by name", NULL},
- { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL},
- { C("dependencies"), (getter)GetDependencies, NULL, "Dependencies", NULL},
- { C("public_dependencies"), (getter)GetPublicDependencies, NULL, "Dependencies", NULL},
-
- { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
- { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
- { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL},
+ { "name", (getter)GetName, NULL, "name"},
+ { "package", (getter)GetPackage, NULL, "package"},
+ { "serialized_pb", (getter)GetSerializedPb},
+ { "message_types_by_name", (getter)GetMessageTypesByName, NULL,
+ "Messages by name"},
+ { "enum_types_by_name", (getter)GetEnumTypesByName, NULL, "Enums by name"},
+ { "extensions_by_name", (getter)GetExtensionsByName, NULL,
+ "Extensions by name"},
+ { "dependencies", (getter)GetDependencies, NULL, "Dependencies"},
+ { "public_dependencies", (getter)GetPublicDependencies, NULL, "Dependencies"},
+
+ { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"},
+ { "_options", (getter)NULL, (setter)SetOptions, "Options"},
+ { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"},
{NULL}
};
@@ -1243,11 +1245,10 @@ static PyMethodDef Methods[] = {
PyTypeObject PyFileDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- C("google.protobuf.internal."
- "_message.FileDescriptor"), // tp_name
+ FULL_MODULE_NAME ".FileDescriptor", // tp_name
sizeof(PyFileDescriptor), // tp_basicsize
0, // tp_itemsize
- (destructor)file_descriptor::Dealloc, // tp_dealloc
+ (destructor)file_descriptor::Dealloc, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
@@ -1263,7 +1264,7 @@ PyTypeObject PyFileDescriptor_Type = {
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
- C("A File Descriptor"), // tp_doc
+ "A File Descriptor", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
@@ -1284,23 +1285,28 @@ PyTypeObject PyFileDescriptor_Type = {
PyObject_Del, // tp_free
};
-PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor) {
- return descriptor::NewInternedDescriptor(
- &PyFileDescriptor_Type, file_descriptor);
+PyObject* PyFileDescriptor_FromDescriptor(
+ const FileDescriptor* file_descriptor) {
+ return PyFileDescriptor_FromDescriptorWithSerializedPb(file_descriptor,
+ NULL);
}
-PyObject* PyFileDescriptor_NewWithPb(
+PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
const FileDescriptor* file_descriptor, PyObject *serialized_pb) {
- PyObject* py_descriptor = PyFileDescriptor_New(file_descriptor);
+ bool was_created;
+ PyObject* py_descriptor = descriptor::NewInternedDescriptor(
+ &PyFileDescriptor_Type, file_descriptor, &was_created);
if (py_descriptor == NULL) {
return NULL;
}
- if (serialized_pb != NULL) {
+ if (was_created) {
PyFileDescriptor* cfile_descriptor =
reinterpret_cast<PyFileDescriptor*>(py_descriptor);
Py_XINCREF(serialized_pb);
cfile_descriptor->serialized_pb = serialized_pb;
}
+ // TODO(amauryfa): In the case of a cached object, check that serialized_pb
+ // is the same as before.
return py_descriptor;
}
@@ -1333,19 +1339,19 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
const Descriptor* containing_type =
_GetDescriptor(self)->containing_type();
if (containing_type) {
- return PyMessageDescriptor_New(containing_type);
+ return PyMessageDescriptor_FromDescriptor(containing_type);
} else {
Py_RETURN_NONE;
}
}
static PyGetSetDef Getters[] = {
- { C("name"), (getter)GetName, NULL, "Name", NULL},
- { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
- { C("index"), (getter)GetIndex, NULL, "Index", NULL},
+ { "name", (getter)GetName, NULL, "Name"},
+ { "full_name", (getter)GetFullName, NULL, "Full name"},
+ { "index", (getter)GetIndex, NULL, "Index"},
- { C("containing_type"), (getter)GetContainingType, NULL, "Containing type", NULL},
- { C("fields"), (getter)GetFields, NULL, "Fields", NULL},
+ { "containing_type", (getter)GetContainingType, NULL, "Containing type"},
+ { "fields", (getter)GetFields, NULL, "Fields"},
{NULL}
};
@@ -1353,8 +1359,7 @@ static PyGetSetDef Getters[] = {
PyTypeObject PyOneofDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- C("google.protobuf.internal."
- "_message.OneofDescriptor"), // tp_name
+ FULL_MODULE_NAME ".OneofDescriptor", // tp_name
sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
0, // tp_dealloc
@@ -1373,7 +1378,7 @@ PyTypeObject PyOneofDescriptor_Type = {
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
- C("A Oneof Descriptor"), // tp_doc
+ "A Oneof Descriptor", // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
@@ -1386,10 +1391,10 @@ PyTypeObject PyOneofDescriptor_Type = {
&descriptor::PyBaseDescriptor_Type, // tp_base
};
-PyObject* PyOneofDescriptor_New(
+PyObject* PyOneofDescriptor_FromDescriptor(
const OneofDescriptor* oneof_descriptor) {
return descriptor::NewInternedDescriptor(
- &PyOneofDescriptor_Type, oneof_descriptor);
+ &PyOneofDescriptor_Type, oneof_descriptor, NULL);
}
// Add a enum values to a type dictionary.
diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h
index ba6e7298..b2550406 100644
--- a/python/google/protobuf/pyext/descriptor.h
+++ b/python/google/protobuf/pyext/descriptor.h
@@ -48,21 +48,24 @@ extern PyTypeObject PyEnumValueDescriptor_Type;
extern PyTypeObject PyFileDescriptor_Type;
extern PyTypeObject PyOneofDescriptor_Type;
-// Return a new reference to a Descriptor object.
+// Wraps a Descriptor in a Python object.
// The C++ pointer is usually borrowed from the global DescriptorPool.
// In any case, it must stay alive as long as the Python object.
-PyObject* PyMessageDescriptor_New(const Descriptor* descriptor);
-PyObject* PyFieldDescriptor_New(const FieldDescriptor* descriptor);
-PyObject* PyEnumDescriptor_New(const EnumDescriptor* descriptor);
-PyObject* PyEnumValueDescriptor_New(const EnumValueDescriptor* descriptor);
-PyObject* PyOneofDescriptor_New(const OneofDescriptor* descriptor);
-PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor);
+// Returns a new reference.
+PyObject* PyMessageDescriptor_FromDescriptor(const Descriptor* descriptor);
+PyObject* PyFieldDescriptor_FromDescriptor(const FieldDescriptor* descriptor);
+PyObject* PyEnumDescriptor_FromDescriptor(const EnumDescriptor* descriptor);
+PyObject* PyEnumValueDescriptor_FromDescriptor(
+ const EnumValueDescriptor* descriptor);
+PyObject* PyOneofDescriptor_FromDescriptor(const OneofDescriptor* descriptor);
+PyObject* PyFileDescriptor_FromDescriptor(
+ const FileDescriptor* file_descriptor);
// Alternate constructor of PyFileDescriptor, used when we already have a
// serialized FileDescriptorProto that can be cached.
// Returns a new reference.
-PyObject* PyFileDescriptor_NewWithPb(const FileDescriptor* file_descriptor,
- PyObject* serialized_pb);
+PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb(
+ const FileDescriptor* file_descriptor, PyObject* serialized_pb);
// Return the C++ descriptor pointer.
// This function checks the parameter type; on error, return NULL with a Python
diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc
index 06edebf8..92e11e31 100644
--- a/python/google/protobuf/pyext/descriptor_containers.cc
+++ b/python/google/protobuf/pyext/descriptor_containers.cc
@@ -898,7 +898,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyFieldDescriptor_New(item);
+ return PyFieldDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -956,7 +956,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyMessageDescriptor_New(item);
+ return PyMessageDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1006,7 +1006,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyEnumDescriptor_New(item);
+ return PyEnumDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1082,7 +1082,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyEnumValueDescriptor_New(item);
+ return PyEnumValueDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1124,7 +1124,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyFieldDescriptor_New(item);
+ return PyFieldDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1174,7 +1174,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyOneofDescriptor_New(item);
+ return PyOneofDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1238,7 +1238,7 @@ static ItemDescriptor GetByNumber(PyContainer* self, int number) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyEnumValueDescriptor_New(item);
+ return PyEnumValueDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1302,7 +1302,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyFieldDescriptor_New(item);
+ return PyFieldDescriptor_FromDescriptor(item);
}
static int GetItemIndex(ItemDescriptor item) {
@@ -1354,7 +1354,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyMessageDescriptor_New(item);
+ return PyMessageDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1400,7 +1400,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyEnumDescriptor_New(item);
+ return PyEnumDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1446,7 +1446,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyFieldDescriptor_New(item);
+ return PyFieldDescriptor_FromDescriptor(item);
}
static const string& GetItemName(ItemDescriptor item) {
@@ -1488,7 +1488,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyFileDescriptor_New(item);
+ return PyFileDescriptor_FromDescriptor(item);
}
static DescriptorContainerDef ContainerDef = {
@@ -1522,7 +1522,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) {
}
static PyObject* NewObjectFromItem(ItemDescriptor item) {
- return PyFileDescriptor_New(item);
+ return PyFileDescriptor_FromDescriptor(item);
}
static DescriptorContainerDef ContainerDef = {
diff --git a/python/google/protobuf/pyext/descriptor_containers.h b/python/google/protobuf/pyext/descriptor_containers.h
index d81537de..8fbdaff9 100644
--- a/python/google/protobuf/pyext/descriptor_containers.h
+++ b/python/google/protobuf/pyext/descriptor_containers.h
@@ -28,6 +28,9 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__
+
// Mappings and Sequences of descriptors.
// They implement containers like fields_by_name, EnumDescriptor.values...
// See descriptor_containers.cc for more description.
@@ -92,4 +95,6 @@ PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor);
} // namespace python
} // namespace protobuf
+
} // namespace google
+#endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index bc3077bc..ecd90847 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -35,10 +35,9 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/pyext/descriptor_pool.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)
-
#if PY_MAJOR_VERSION >= 3
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#if PY_VERSION_HEX < 0x03030000
@@ -108,11 +107,11 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
self->pool->FindMessageTypeByName(string(name, name_size));
if (message_descriptor == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't find message %.200s", name);
+ PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name);
return NULL;
}
- return PyMessageDescriptor_New(message_descriptor);
+ return PyMessageDescriptor_FromDescriptor(message_descriptor);
}
// Add a message class to our database.
@@ -158,6 +157,24 @@ PyObject *GetMessageClass(PyDescriptorPool* self,
}
}
+PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) {
+ Py_ssize_t name_size;
+ char* name;
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+ return NULL;
+ }
+
+ const FileDescriptor* file_descriptor =
+ self->pool->FindFileByName(string(name, name_size));
+ if (file_descriptor == NULL) {
+ PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s",
+ name);
+ return NULL;
+ }
+
+ return PyFileDescriptor_FromDescriptor(file_descriptor);
+}
+
PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
Py_ssize_t name_size;
char* name;
@@ -168,12 +185,12 @@ PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
const FieldDescriptor* field_descriptor =
self->pool->FindFieldByName(string(name, name_size));
if (field_descriptor == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
+ PyErr_Format(PyExc_KeyError, "Couldn't find field %.200s",
name);
return NULL;
}
- return PyFieldDescriptor_New(field_descriptor);
+ return PyFieldDescriptor_FromDescriptor(field_descriptor);
}
PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
@@ -186,11 +203,11 @@ PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
const FieldDescriptor* field_descriptor =
self->pool->FindExtensionByName(string(name, name_size));
if (field_descriptor == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", name);
+ PyErr_Format(PyExc_KeyError, "Couldn't find extension field %.200s", name);
return NULL;
}
- return PyFieldDescriptor_New(field_descriptor);
+ return PyFieldDescriptor_FromDescriptor(field_descriptor);
}
PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
@@ -203,11 +220,11 @@ PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
const EnumDescriptor* enum_descriptor =
self->pool->FindEnumTypeByName(string(name, name_size));
if (enum_descriptor == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't find enum %.200s", name);
+ PyErr_Format(PyExc_KeyError, "Couldn't find enum %.200s", name);
return NULL;
}
- return PyEnumDescriptor_New(enum_descriptor);
+ return PyEnumDescriptor_FromDescriptor(enum_descriptor);
}
PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
@@ -220,70 +237,13 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
const OneofDescriptor* oneof_descriptor =
self->pool->FindOneofByName(string(name, name_size));
if (oneof_descriptor == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't find oneof %.200s", name);
+ PyErr_Format(PyExc_KeyError, "Couldn't find oneof %.200s", name);
return NULL;
}
- return PyOneofDescriptor_New(oneof_descriptor);
+ return PyOneofDescriptor_FromDescriptor(oneof_descriptor);
}
-static PyMethodDef Methods[] = {
- { C("FindFieldByName"),
- (PyCFunction)FindFieldByName,
- METH_O,
- C("Searches for a field descriptor by full name.") },
- { C("FindExtensionByName"),
- (PyCFunction)FindExtensionByName,
- METH_O,
- C("Searches for extension descriptor by full name.") },
- {NULL}
-};
-
-} // namespace cdescriptor_pool
-
-PyTypeObject PyDescriptorPool_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- C("google.protobuf.internal."
- "_message.DescriptorPool"), // tp_name
- sizeof(PyDescriptorPool), // tp_basicsize
- 0, // tp_itemsize
- (destructor)cdescriptor_pool::Dealloc, // tp_dealloc
- 0, // tp_print
- 0, // tp_getattr
- 0, // tp_setattr
- 0, // tp_compare
- 0, // tp_repr
- 0, // tp_as_number
- 0, // tp_as_sequence
- 0, // tp_as_mapping
- 0, // tp_hash
- 0, // tp_call
- 0, // tp_str
- 0, // tp_getattro
- 0, // tp_setattro
- 0, // tp_as_buffer
- Py_TPFLAGS_DEFAULT, // tp_flags
- C("A Descriptor Pool"), // tp_doc
- 0, // tp_traverse
- 0, // tp_clear
- 0, // tp_richcompare
- 0, // tp_weaklistoffset
- 0, // tp_iter
- 0, // tp_iternext
- cdescriptor_pool::Methods, // tp_methods
- 0, // tp_members
- 0, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
- 0, // tp_alloc
- 0, // tp_new
- PyObject_Del, // tp_free
-};
-
// The code below loads new Descriptors from a serialized FileDescriptorProto.
@@ -301,6 +261,7 @@ class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
if (!had_errors) {
error_message +=
("Invalid proto descriptor for file \"" + filename + "\":\n");
+ had_errors = true;
}
// As this only happens on failure and will result in the program not
// running at all, no effort is made to optimize this string manipulation.
@@ -311,7 +272,7 @@ class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
bool had_errors;
};
-PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) {
+PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) {
char* message_type;
Py_ssize_t message_len;
@@ -330,13 +291,14 @@ PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) {
const FileDescriptor* generated_file =
DescriptorPool::generated_pool()->FindFileByName(file_proto.name());
if (generated_file != NULL) {
- return PyFileDescriptor_NewWithPb(generated_file, serialized_pb);
+ return PyFileDescriptor_FromDescriptorWithSerializedPb(
+ generated_file, serialized_pb);
}
BuildFileErrorCollector error_collector;
const FileDescriptor* descriptor =
- GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto,
- &error_collector);
+ self->pool->BuildFileCollectingErrors(file_proto,
+ &error_collector);
if (descriptor == NULL) {
PyErr_Format(PyExc_TypeError,
"Couldn't build proto file into descriptor pool!\n%s",
@@ -344,9 +306,84 @@ PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) {
return NULL;
}
- return PyFileDescriptor_NewWithPb(descriptor, serialized_pb);
+ return PyFileDescriptor_FromDescriptorWithSerializedPb(
+ descriptor, serialized_pb);
+}
+
+PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) {
+ ScopedPyObjectPtr serialized_pb(
+ PyObject_CallMethod(file_descriptor_proto, "SerializeToString", NULL));
+ if (serialized_pb == NULL) {
+ return NULL;
+ }
+ return AddSerializedFile(self, serialized_pb);
}
+static PyMethodDef Methods[] = {
+ { "Add", (PyCFunction)Add, METH_O,
+ "Adds the FileDescriptorProto and its types to this pool." },
+ { "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O,
+ "Adds a serialized FileDescriptorProto to this pool." },
+
+ { "FindFileByName", (PyCFunction)FindFileByName, METH_O,
+ "Searches for a file descriptor by its .proto name." },
+ { "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O,
+ "Searches for a message descriptor by full name." },
+ { "FindFieldByName", (PyCFunction)FindFieldByName, METH_O,
+ "Searches for a field descriptor by full name." },
+ { "FindExtensionByName", (PyCFunction)FindExtensionByName, METH_O,
+ "Searches for extension descriptor by full name." },
+ { "FindEnumTypeByName", (PyCFunction)FindEnumTypeByName, METH_O,
+ "Searches for enum type descriptor by full name." },
+ { "FindOneofByName", (PyCFunction)FindOneofByName, METH_O,
+ "Searches for oneof descriptor by full name." },
+ {NULL}
+};
+
+} // namespace cdescriptor_pool
+
+PyTypeObject PyDescriptorPool_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".DescriptorPool", // tp_name
+ sizeof(PyDescriptorPool), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)cdescriptor_pool::Dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ "A Descriptor Pool", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ cdescriptor_pool::Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ 0, // tp_alloc
+ 0, // tp_new
+ PyObject_Del, // tp_free
+};
+
static PyDescriptorPool* global_cdescriptor_pool = NULL;
bool InitDescriptorPool() {
diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h
index 4e494b89..efb1abeb 100644
--- a/python/google/protobuf/pyext/descriptor_pool.h
+++ b/python/google/protobuf/pyext/descriptor_pool.h
@@ -95,6 +95,8 @@ const Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
const Descriptor* RegisterMessageClass(
PyDescriptorPool* self, PyObject* message_class, PyObject* descriptor);
+// The function below are also exposed as methods of the DescriptorPool type.
+
// Retrieves the Python class registered with the given message descriptor.
//
// Returns a *borrowed* reference if found, otherwise returns NULL with an
@@ -134,12 +136,8 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg);
} // namespace cdescriptor_pool
-// Implement the Python "_BuildFile" method, it takes a serialized
-// FileDescriptorProto, and adds it to the C++ DescriptorPool.
-// It returns a new FileDescriptor object, or NULL when an exception is raised.
-PyObject* Python_BuildFile(PyObject* ignored, PyObject* args);
-
// Retrieve the global descriptor pool owned by the _message module.
+// Returns a *borrowed* reference.
PyDescriptorPool* GetDescriptorPool();
// Initialize objects used by this module.
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index 8e38fc42..b8d18f8d 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -51,16 +51,6 @@ namespace python {
namespace extension_dict {
-// TODO(tibell): Always use self->message for clarity, just like in
-// RepeatedCompositeContainer.
-static Message* GetMessage(ExtensionDict* self) {
- if (self->parent != NULL) {
- return self->parent->message;
- } else {
- return self->message;
- }
-}
-
PyObject* len(ExtensionDict* self) {
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(PyDict_Size(self->values));
@@ -89,7 +79,7 @@ int ReleaseExtension(ExtensionDict* self,
}
} else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (cmessage::ReleaseSubMessage(
- GetMessage(self), descriptor,
+ self->parent, descriptor,
reinterpret_cast<CMessage*>(extension)) < 0) {
return -1;
}
@@ -109,7 +99,7 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
if (descriptor->label() != FieldDescriptor::LABEL_REPEATED &&
descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
- return cmessage::InternalGetScalar(self->parent, descriptor);
+ return cmessage::InternalGetScalar(self->parent->message, descriptor);
}
PyObject* value = PyDict_GetItem(self->values, key);
@@ -266,8 +256,7 @@ static PyMethodDef Methods[] = {
PyTypeObject ExtensionDict_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "google.protobuf.internal."
- "cpp._message.ExtensionDict", // tp_name
+ FULL_MODULE_NAME ".ExtensionDict", // tp_name
sizeof(ExtensionDict), // tp_basicsize
0, // tp_itemsize
(destructor)extension_dict::dealloc, // tp_dealloc
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index a2b357b2..a4843e8d 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -59,6 +59,8 @@
#include <google/protobuf/pyext/extension_dict.h>
#include <google/protobuf/pyext/repeated_composite_container.h>
#include <google/protobuf/pyext/repeated_scalar_container.h>
+#include <google/protobuf/pyext/message_map_container.h>
+#include <google/protobuf/pyext/scalar_map_container.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
#include <google/protobuf/stubs/strutil.h>
@@ -93,9 +95,9 @@ static const FieldDescriptor* GetFieldDescriptor(
static const Descriptor* GetMessageDescriptor(PyTypeObject* cls);
static string GetMessageName(CMessage* self);
int InternalReleaseFieldByDescriptor(
+ CMessage* self,
const FieldDescriptor* field_descriptor,
- PyObject* composite_field,
- Message* parent_message);
+ PyObject* composite_field);
} // namespace cmessage
// ---------------------------------------------------------------------
@@ -127,10 +129,29 @@ static int VisitCompositeField(const FieldDescriptor* descriptor,
Visitor visitor) {
if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- RepeatedCompositeContainer* container =
- reinterpret_cast<RepeatedCompositeContainer*>(child);
- if (visitor.VisitRepeatedCompositeContainer(container) == -1)
- return -1;
+ if (descriptor->is_map()) {
+ const Descriptor* entry_type = descriptor->message_type();
+ const FieldDescriptor* value_type =
+ entry_type->FindFieldByName("value");
+ if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ MessageMapContainer* container =
+ reinterpret_cast<MessageMapContainer*>(child);
+ if (visitor.VisitMessageMapContainer(container) == -1) {
+ return -1;
+ }
+ } else {
+ ScalarMapContainer* container =
+ reinterpret_cast<ScalarMapContainer*>(child);
+ if (visitor.VisitScalarMapContainer(container) == -1) {
+ return -1;
+ }
+ }
+ } else {
+ RepeatedCompositeContainer* container =
+ reinterpret_cast<RepeatedCompositeContainer*>(child);
+ if (visitor.VisitRepeatedCompositeContainer(container) == -1)
+ return -1;
+ }
} else {
RepeatedScalarContainer* container =
reinterpret_cast<RepeatedScalarContainer*>(child);
@@ -444,7 +465,7 @@ static int MaybeReleaseOverlappingOneofField(
}
if (InternalReleaseFieldByDescriptor(
- existing_field, child_message, message) < 0) {
+ cmessage, existing_field, child_message) < 0) {
return -1;
}
return PyDict_DelItemString(cmessage->composite_fields, field_name);
@@ -483,6 +504,16 @@ struct FixupMessageReference : public ChildVisitor {
return 0;
}
+ int VisitScalarMapContainer(ScalarMapContainer* container) {
+ container->message = message_;
+ return 0;
+ }
+
+ int VisitMessageMapContainer(MessageMapContainer* container) {
+ container->message = message_;
+ return 0;
+ }
+
private:
Message* message_;
};
@@ -500,6 +531,9 @@ int AssureWritable(CMessage* self) {
self->message->GetDescriptor());
self->message = prototype->New();
self->owner.reset(self->message);
+ // Cascade the new owner to eventual children: even if this message is
+ // empty, some submessages or repeated containers might exist already.
+ SetOwner(self, self->owner);
} else {
// Otherwise, we need a mutable child message.
if (AssureWritable(self->parent) == -1)
@@ -520,8 +554,9 @@ int AssureWritable(CMessage* self) {
// When a CMessage is made writable its Message pointer is updated
// to point to a new mutable Message. When that happens we need to
// update any references to the old, read-only CMessage. There are
- // three places such references occur: RepeatedScalarContainer,
- // RepeatedCompositeContainer, and ExtensionDict.
+ // five places such references occur: RepeatedScalarContainer,
+ // RepeatedCompositeContainer, ScalarMapContainer, MessageMapContainer,
+ // and ExtensionDict.
if (self->extensions != NULL)
self->extensions->message = self->message;
if (ForEachCompositeField(self, FixupMessageReference(self->message)) == -1)
@@ -583,15 +618,43 @@ const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
return PyFieldDescriptor_AsDescriptor(extension);
}
+// If value is a string, convert it into an enum value based on the labels in
+// descriptor, otherwise simply return value. Always returns a new reference.
+static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor,
+ PyObject* value) {
+ if (PyString_Check(value) || PyUnicode_Check(value)) {
+ const EnumDescriptor* enum_descriptor = descriptor.enum_type();
+ if (enum_descriptor == NULL) {
+ PyErr_SetString(PyExc_TypeError, "not an enum field");
+ return NULL;
+ }
+ char* enum_label;
+ Py_ssize_t size;
+ if (PyString_AsStringAndSize(value, &enum_label, &size) < 0) {
+ return NULL;
+ }
+ const EnumValueDescriptor* enum_value_descriptor =
+ enum_descriptor->FindValueByName(string(enum_label, size));
+ if (enum_value_descriptor == NULL) {
+ PyErr_SetString(PyExc_ValueError, "unknown enum label");
+ return NULL;
+ }
+ return PyInt_FromLong(enum_value_descriptor->number());
+ }
+ Py_INCREF(value);
+ return value;
+}
+
// If cmessage_list is not NULL, this function releases values into the
// container CMessages instead of just removing. Repeated composite container
// needs to do this to make sure CMessages stay alive if they're still
// referenced after deletion. Repeated scalar container doesn't need to worry.
int InternalDeleteRepeatedField(
- Message* message,
+ CMessage* self,
const FieldDescriptor* field_descriptor,
PyObject* slice,
PyObject* cmessage_list) {
+ Message* message = self->message;
Py_ssize_t length, from, to, step, slice_length;
const Reflection* reflection = message->GetReflection();
int min, max;
@@ -665,7 +728,7 @@ int InternalDeleteRepeatedField(
CMessage* last_cmessage = reinterpret_cast<CMessage*>(
PyList_GET_ITEM(cmessage_list, PyList_GET_SIZE(cmessage_list) - 1));
repeated_composite_container::ReleaseLastTo(
- field_descriptor, message, last_cmessage);
+ self, field_descriptor, last_cmessage);
if (PySequence_DelItem(cmessage_list, -1) < 0) {
return -1;
}
@@ -696,16 +759,90 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
PyString_AsString(name));
return -1;
}
- if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+ if (descriptor->is_map()) {
+ ScopedPyObjectPtr map(GetAttr(self, name));
+ const FieldDescriptor* value_descriptor =
+ descriptor->message_type()->FindFieldByName("value");
+ if (value_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ Py_ssize_t map_pos = 0;
+ PyObject* map_key;
+ PyObject* map_value;
+ while (PyDict_Next(value, &map_pos, &map_key, &map_value)) {
+ ScopedPyObjectPtr function_return;
+ function_return.reset(PyObject_GetItem(map.get(), map_key));
+ if (function_return.get() == NULL) {
+ return -1;
+ }
+ ScopedPyObjectPtr ok(PyObject_CallMethod(
+ function_return.get(), "MergeFrom", "O", map_value));
+ if (ok.get() == NULL) {
+ return -1;
+ }
+ }
+ } else {
+ ScopedPyObjectPtr function_return;
+ function_return.reset(
+ PyObject_CallMethod(map.get(), "update", "O", value));
+ if (function_return.get() == NULL) {
+ return -1;
+ }
+ }
+ } else if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
ScopedPyObjectPtr container(GetAttr(self, name));
if (container == NULL) {
return -1;
}
if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- if (repeated_composite_container::Extend(
- reinterpret_cast<RepeatedCompositeContainer*>(container.get()),
- value)
- == NULL) {
+ RepeatedCompositeContainer* rc_container =
+ reinterpret_cast<RepeatedCompositeContainer*>(container.get());
+ ScopedPyObjectPtr iter(PyObject_GetIter(value));
+ if (iter == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+ return -1;
+ }
+ ScopedPyObjectPtr next;
+ while ((next.reset(PyIter_Next(iter))) != NULL) {
+ PyObject* kwargs = (PyDict_Check(next) ? next.get() : NULL);
+ ScopedPyObjectPtr new_msg(
+ repeated_composite_container::Add(rc_container, NULL, kwargs));
+ if (new_msg == NULL) {
+ return -1;
+ }
+ if (kwargs == NULL) {
+ // next was not a dict, it's a message we need to merge
+ ScopedPyObjectPtr merged(
+ MergeFrom(reinterpret_cast<CMessage*>(new_msg.get()), next));
+ if (merged == NULL) {
+ return -1;
+ }
+ }
+ }
+ if (PyErr_Occurred()) {
+ // Check to see how PyIter_Next() exited.
+ return -1;
+ }
+ } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ RepeatedScalarContainer* rs_container =
+ reinterpret_cast<RepeatedScalarContainer*>(container.get());
+ ScopedPyObjectPtr iter(PyObject_GetIter(value));
+ if (iter == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+ return -1;
+ }
+ ScopedPyObjectPtr next;
+ while ((next.reset(PyIter_Next(iter))) != NULL) {
+ ScopedPyObjectPtr enum_value(GetIntegerEnumValue(*descriptor, next));
+ if (enum_value == NULL) {
+ return -1;
+ }
+ ScopedPyObjectPtr new_msg(
+ repeated_scalar_container::Append(rs_container, enum_value));
+ if (new_msg == NULL) {
+ return -1;
+ }
+ }
+ if (PyErr_Occurred()) {
+ // Check to see how PyIter_Next() exited.
return -1;
}
} else {
@@ -721,12 +858,26 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
if (message == NULL) {
return -1;
}
- if (MergeFrom(reinterpret_cast<CMessage*>(message.get()),
- value) == NULL) {
- return -1;
+ CMessage* cmessage = reinterpret_cast<CMessage*>(message.get());
+ if (PyDict_Check(value)) {
+ if (InitAttributes(cmessage, value) < 0) {
+ return -1;
+ }
+ } else {
+ ScopedPyObjectPtr merged(MergeFrom(cmessage, value));
+ if (merged == NULL) {
+ return -1;
+ }
}
} else {
- if (SetAttr(self, name, value) < 0) {
+ ScopedPyObjectPtr new_val;
+ if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ new_val.reset(GetIntegerEnumValue(*descriptor, value));
+ if (new_val == NULL) {
+ return -1;
+ }
+ }
+ if (SetAttr(self, name, (new_val == NULL) ? value : new_val) < 0) {
return -1;
}
}
@@ -789,7 +940,6 @@ static PyObject* New(PyTypeObject* type,
}
self->message = default_message->New();
self->owner.reset(self->message);
-
return reinterpret_cast<PyObject*>(self);
}
@@ -830,6 +980,16 @@ struct ClearWeakReferences : public ChildVisitor {
return 0;
}
+ int VisitScalarMapContainer(ScalarMapContainer* container) {
+ container->parent = NULL;
+ return 0;
+ }
+
+ int VisitMessageMapContainer(MessageMapContainer* container) {
+ container->parent = NULL;
+ return 0;
+ }
+
int VisitCMessage(CMessage* cmessage,
const FieldDescriptor* field_descriptor) {
cmessage->parent = NULL;
@@ -1064,6 +1224,16 @@ struct SetOwnerVisitor : public ChildVisitor {
return 0;
}
+ int VisitScalarMapContainer(ScalarMapContainer* container) {
+ scalar_map_container::SetOwner(container, new_owner_);
+ return 0;
+ }
+
+ int VisitMessageMapContainer(MessageMapContainer* container) {
+ message_map_container::SetOwner(container, new_owner_);
+ return 0;
+ }
+
int VisitCMessage(CMessage* cmessage,
const FieldDescriptor* field_descriptor) {
return SetOwner(cmessage, new_owner_);
@@ -1084,11 +1254,11 @@ int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) {
// Releases the message specified by 'field' and returns the
// pointer. If the field does not exist a new message is created using
// 'descriptor'. The caller takes ownership of the returned pointer.
-Message* ReleaseMessage(Message* message,
+Message* ReleaseMessage(CMessage* self,
const Descriptor* descriptor,
const FieldDescriptor* field_descriptor) {
- Message* released_message = message->GetReflection()->ReleaseMessage(
- message, field_descriptor, message_factory);
+ Message* released_message = self->message->GetReflection()->ReleaseMessage(
+ self->message, field_descriptor, message_factory);
// ReleaseMessage will return NULL which differs from
// child_cmessage->message, if the field does not exist. In this case,
// the latter points to the default instance via a const_cast<>, so we
@@ -1102,12 +1272,12 @@ Message* ReleaseMessage(Message* message,
return released_message;
}
-int ReleaseSubMessage(Message* message,
+int ReleaseSubMessage(CMessage* self,
const FieldDescriptor* field_descriptor,
CMessage* child_cmessage) {
// Release the Message
shared_ptr<Message> released_message(ReleaseMessage(
- message, child_cmessage->message->GetDescriptor(), field_descriptor));
+ self, child_cmessage->message->GetDescriptor(), field_descriptor));
child_cmessage->message = released_message.get();
child_cmessage->owner.swap(released_message);
child_cmessage->parent = NULL;
@@ -1119,8 +1289,8 @@ int ReleaseSubMessage(Message* message,
struct ReleaseChild : public ChildVisitor {
// message must outlive this object.
- explicit ReleaseChild(Message* parent_message) :
- parent_message_(parent_message) {}
+ explicit ReleaseChild(CMessage* parent) :
+ parent_(parent) {}
int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
return repeated_composite_container::Release(
@@ -1132,23 +1302,33 @@ struct ReleaseChild : public ChildVisitor {
reinterpret_cast<RepeatedScalarContainer*>(container));
}
+ int VisitScalarMapContainer(ScalarMapContainer* container) {
+ return scalar_map_container::Release(
+ reinterpret_cast<ScalarMapContainer*>(container));
+ }
+
+ int VisitMessageMapContainer(MessageMapContainer* container) {
+ return message_map_container::Release(
+ reinterpret_cast<MessageMapContainer*>(container));
+ }
+
int VisitCMessage(CMessage* cmessage,
const FieldDescriptor* field_descriptor) {
- return ReleaseSubMessage(parent_message_, field_descriptor,
+ return ReleaseSubMessage(parent_, field_descriptor,
reinterpret_cast<CMessage*>(cmessage));
}
- Message* parent_message_;
+ CMessage* parent_;
};
int InternalReleaseFieldByDescriptor(
+ CMessage* self,
const FieldDescriptor* field_descriptor,
- PyObject* composite_field,
- Message* parent_message) {
+ PyObject* composite_field) {
return VisitCompositeField(
field_descriptor,
composite_field,
- ReleaseChild(parent_message));
+ ReleaseChild(self));
}
PyObject* ClearFieldByDescriptor(
@@ -1200,8 +1380,8 @@ PyObject* ClearField(CMessage* self, PyObject* arg) {
// Only release the field if there's a possibility that there are
// references to it.
if (composite_field != NULL) {
- if (InternalReleaseFieldByDescriptor(field_descriptor,
- composite_field, message) < 0) {
+ if (InternalReleaseFieldByDescriptor(self, field_descriptor,
+ composite_field) < 0) {
return NULL;
}
PyDict_DelItem(self->composite_fields, arg);
@@ -1219,7 +1399,7 @@ PyObject* ClearField(CMessage* self, PyObject* arg) {
PyObject* Clear(CMessage* self) {
AssureWritable(self);
- if (ForEachCompositeField(self, ReleaseChild(self->message)) == -1)
+ if (ForEachCompositeField(self, ReleaseChild(self)) == -1)
return NULL;
// The old ExtensionDict still aliases this CMessage, but all its
@@ -1582,7 +1762,8 @@ static PyObject* ListFields(CMessage* self) {
}
if (fields[i]->is_extension()) {
- ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(fields[i]));
+ ScopedPyObjectPtr extension_field(
+ PyFieldDescriptor_FromDescriptor(fields[i]));
if (extension_field == NULL) {
return NULL;
}
@@ -1616,7 +1797,8 @@ static PyObject* ListFields(CMessage* self) {
PyErr_SetString(PyExc_ValueError, "bad string");
return NULL;
}
- ScopedPyObjectPtr field_descriptor(PyFieldDescriptor_New(fields[i]));
+ ScopedPyObjectPtr field_descriptor(
+ PyFieldDescriptor_FromDescriptor(fields[i]));
if (field_descriptor == NULL) {
return NULL;
}
@@ -1683,10 +1865,8 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
}
}
-PyObject* InternalGetScalar(
- CMessage* self,
- const FieldDescriptor* field_descriptor) {
- Message* message = self->message;
+PyObject* InternalGetScalar(const Message* message,
+ const FieldDescriptor* field_descriptor) {
const Reflection* reflection = message->GetReflection();
if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
@@ -1739,12 +1919,12 @@ PyObject* InternalGetScalar(
if (!message->GetReflection()->SupportsUnknownEnumValues() &&
!message->GetReflection()->HasField(*message, field_descriptor)) {
// Look for the value in the unknown fields.
- UnknownFieldSet* unknown_field_set =
- message->GetReflection()->MutableUnknownFields(message);
- for (int i = 0; i < unknown_field_set->field_count(); ++i) {
- if (unknown_field_set->field(i).number() ==
+ const UnknownFieldSet& unknown_field_set =
+ message->GetReflection()->GetUnknownFields(*message);
+ for (int i = 0; i < unknown_field_set.field_count(); ++i) {
+ if (unknown_field_set.field(i).number() ==
field_descriptor->number()) {
- result = PyInt_FromLong(unknown_field_set->field(i).varint());
+ result = PyInt_FromLong(unknown_field_set.field(i).varint());
break;
}
}
@@ -1793,21 +1973,16 @@ PyObject* InternalGetSubMessage(
return reinterpret_cast<PyObject*>(cmsg);
}
-int InternalSetScalar(
- CMessage* self,
+int InternalSetNonOneofScalar(
+ Message* message,
const FieldDescriptor* field_descriptor,
PyObject* arg) {
- Message* message = self->message;
const Reflection* reflection = message->GetReflection();
if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
return -1;
}
- if (MaybeReleaseOverlappingOneofField(self, field_descriptor) < 0) {
- return -1;
- }
-
switch (field_descriptor->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32: {
GOOGLE_CHECK_GET_INT32(arg, value, -1);
@@ -1878,6 +2053,21 @@ int InternalSetScalar(
return 0;
}
+int InternalSetScalar(
+ CMessage* self,
+ const FieldDescriptor* field_descriptor,
+ PyObject* arg) {
+ if (!CheckFieldBelongsToMessage(field_descriptor, self->message)) {
+ return -1;
+ }
+
+ if (MaybeReleaseOverlappingOneofField(self, field_descriptor) < 0) {
+ return -1;
+ }
+
+ return InternalSetNonOneofScalar(self->message, field_descriptor, arg);
+}
+
PyObject* FromString(PyTypeObject* cls, PyObject* serialized) {
PyObject* py_cmsg = PyObject_CallObject(
reinterpret_cast<PyObject*>(cls), NULL);
@@ -1955,7 +2145,8 @@ static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) {
// which was built previously.
for (int i = 0; i < message_descriptor->enum_type_count(); ++i) {
const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i);
- ScopedPyObjectPtr enum_type(PyEnumDescriptor_New(enum_descriptor));
+ ScopedPyObjectPtr enum_type(
+ PyEnumDescriptor_FromDescriptor(enum_descriptor));
if (enum_type == NULL) {
return NULL;
}
@@ -1993,7 +2184,7 @@ static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) {
// which was defined previously.
for (int i = 0; i < message_descriptor->extension_count(); ++i) {
const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i);
- ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(field));
+ ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field));
if (extension_field == NULL) {
return NULL;
}
@@ -2097,26 +2288,6 @@ PyObject* SetState(CMessage* self, PyObject* state) {
}
// CMessage static methods:
-PyObject* _GetMessageDescriptor(PyObject* unused, PyObject* arg) {
- return cdescriptor_pool::FindMessageByName(GetDescriptorPool(), arg);
-}
-
-PyObject* _GetFieldDescriptor(PyObject* unused, PyObject* arg) {
- return cdescriptor_pool::FindFieldByName(GetDescriptorPool(), arg);
-}
-
-PyObject* _GetExtensionDescriptor(PyObject* unused, PyObject* arg) {
- return cdescriptor_pool::FindExtensionByName(GetDescriptorPool(), arg);
-}
-
-PyObject* _GetEnumDescriptor(PyObject* unused, PyObject* arg) {
- return cdescriptor_pool::FindEnumTypeByName(GetDescriptorPool(), arg);
-}
-
-PyObject* _GetOneofDescriptor(PyObject* unused, PyObject* arg) {
- return cdescriptor_pool::FindOneofByName(GetDescriptorPool(), arg);
-}
-
PyObject* _CheckCalledFromGeneratedFile(PyObject* unused,
PyObject* unused_arg) {
if (!_CalledFromGeneratedFile(1)) {
@@ -2188,21 +2359,6 @@ static PyMethodDef Methods[] = {
"or None if no field is set." },
// Static Methods.
- { "_BuildFile", (PyCFunction)Python_BuildFile, METH_O | METH_STATIC,
- "Registers a new protocol buffer file in the global C++ descriptor pool." },
- { "_GetMessageDescriptor", (PyCFunction)_GetMessageDescriptor,
- METH_O | METH_STATIC, "Finds a message descriptor in the message pool." },
- { "_GetFieldDescriptor", (PyCFunction)_GetFieldDescriptor,
- METH_O | METH_STATIC, "Finds a field descriptor in the message pool." },
- { "_GetExtensionDescriptor", (PyCFunction)_GetExtensionDescriptor,
- METH_O | METH_STATIC,
- "Finds a extension descriptor in the message pool." },
- { "_GetEnumDescriptor", (PyCFunction)_GetEnumDescriptor,
- METH_O | METH_STATIC,
- "Finds an enum descriptor in the message pool." },
- { "_GetOneofDescriptor", (PyCFunction)_GetOneofDescriptor,
- METH_O | METH_STATIC,
- "Finds an oneof descriptor in the message pool." },
{ "_CheckCalledFromGeneratedFile", (PyCFunction)_CheckCalledFromGeneratedFile,
METH_NOARGS | METH_STATIC,
"Raises TypeError if the caller is not in a _pb2.py file."},
@@ -2234,6 +2390,31 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
reinterpret_cast<PyObject*>(self), name);
}
+ if (field_descriptor->is_map()) {
+ PyObject* py_container = NULL;
+ const Descriptor* entry_type = field_descriptor->message_type();
+ const FieldDescriptor* value_type = entry_type->FindFieldByName("value");
+ if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ PyObject* value_class = cdescriptor_pool::GetMessageClass(
+ GetDescriptorPool(), value_type->message_type());
+ if (value_class == NULL) {
+ return NULL;
+ }
+ py_container = message_map_container::NewContainer(self, field_descriptor,
+ value_class);
+ } else {
+ py_container = scalar_map_container::NewContainer(self, field_descriptor);
+ }
+ if (py_container == NULL) {
+ return NULL;
+ }
+ if (!SetCompositeField(self, name, py_container)) {
+ Py_DECREF(py_container);
+ return NULL;
+ }
+ return py_container;
+ }
+
if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
PyObject* py_container = NULL;
if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
@@ -2267,7 +2448,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
return sub_message;
}
- return InternalGetScalar(self, field_descriptor);
+ return InternalGetScalar(self->message, field_descriptor);
}
int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
@@ -2304,9 +2485,7 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
PyTypeObject CMessage_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- // Keep the fully qualified _message symbol in a line for opensource.
- "google.protobuf.pyext._message."
- "CMessage", // tp_name
+ FULL_MODULE_NAME ".CMessage", // tp_name
sizeof(CMessage), // tp_basicsize
0, // tp_itemsize
(destructor)cmessage::Dealloc, // tp_dealloc
@@ -2401,7 +2580,7 @@ void InitGlobals() {
k_extensions_by_name = PyString_FromString("_extensions_by_name");
k_extensions_by_number = PyString_FromString("_extensions_by_number");
- message_factory = new DynamicMessageFactory(GetDescriptorPool()->pool);
+ message_factory = new DynamicMessageFactory();
message_factory->SetDelegateToGeneratedFactory(true);
}
@@ -2469,6 +2648,61 @@ bool InitProto2MessageModule(PyObject *m) {
reinterpret_cast<PyObject*>(
&RepeatedCompositeContainer_Type));
+ // ScalarMapContainer_Type derives from our MutableMapping type.
+ PyObject* containers =
+ PyImport_ImportModule("google.protobuf.internal.containers");
+ if (containers == NULL) {
+ return false;
+ }
+
+ PyObject* mutable_mapping =
+ PyObject_GetAttrString(containers, "MutableMapping");
+ Py_DECREF(containers);
+
+ if (mutable_mapping == NULL) {
+ return false;
+ }
+
+ if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) {
+ Py_DECREF(mutable_mapping);
+ return false;
+ }
+
+ ScalarMapContainer_Type.tp_base =
+ reinterpret_cast<PyTypeObject*>(mutable_mapping);
+
+ if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
+ return false;
+ }
+
+ PyModule_AddObject(m, "ScalarMapContainer",
+ reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
+
+ if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
+ return false;
+ }
+
+ PyModule_AddObject(m, "ScalarMapIterator",
+ reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
+
+ Py_INCREF(mutable_mapping);
+ MessageMapContainer_Type.tp_base =
+ reinterpret_cast<PyTypeObject*>(mutable_mapping);
+
+ if (PyType_Ready(&MessageMapContainer_Type) < 0) {
+ return false;
+ }
+
+ PyModule_AddObject(m, "MessageMapContainer",
+ reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
+
+ if (PyType_Ready(&MessageMapIterator_Type) < 0) {
+ return false;
+ }
+
+ PyModule_AddObject(m, "MessageMapIterator",
+ reinterpret_cast<PyObject*>(&MessageMapIterator_Type));
+
ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
if (PyType_Ready(&ExtensionDict_Type) < 0) {
return false;
@@ -2478,6 +2712,12 @@ bool InitProto2MessageModule(PyObject *m) {
m, "ExtensionDict",
reinterpret_cast<PyObject*>(&ExtensionDict_Type));
+ // Expose the DescriptorPool used to hold all descriptors added from generated
+ // pb2.py files.
+ Py_INCREF(GetDescriptorPool()); // PyModule_AddObject steals a reference.
+ PyModule_AddObject(
+ m, "default_pool", reinterpret_cast<PyObject*>(GetDescriptorPool()));
+
// This implementation provides full Descriptor types, we advertise it so that
// descriptor.py can use them in replacement of the Python classes.
PyModule_AddIntConstant(m, "_USE_C_DESCRIPTORS", 1);
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 2f2da795..7360b207 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -120,7 +120,7 @@ CMessage* NewEmptyMessage(PyObject* type, const Descriptor* descriptor);
// A new message will be created if this is a read-only default instance.
//
// Corresponds to reflection api method ReleaseMessage.
-int ReleaseSubMessage(Message* message,
+int ReleaseSubMessage(CMessage* self,
const FieldDescriptor* field_descriptor,
CMessage* child_cmessage);
@@ -144,7 +144,7 @@ PyObject* InternalGetSubMessage(
// by slice will be removed from cmessage_list by this function.
//
// Corresponds to reflection api method RemoveLast.
-int InternalDeleteRepeatedField(Message* message,
+int InternalDeleteRepeatedField(CMessage* self,
const FieldDescriptor* field_descriptor,
PyObject* slice, PyObject* cmessage_list);
@@ -153,10 +153,15 @@ int InternalSetScalar(CMessage* self,
const FieldDescriptor* field_descriptor,
PyObject* value);
+// Sets the specified scalar value to the message. Requires it is not a Oneof.
+int InternalSetNonOneofScalar(Message* message,
+ const FieldDescriptor* field_descriptor,
+ PyObject* arg);
+
// Retrieves the specified scalar value from the message.
//
// Returns a new python reference.
-PyObject* InternalGetScalar(CMessage* self,
+PyObject* InternalGetScalar(const Message* message,
const FieldDescriptor* field_descriptor);
// Clears the message, removing all contained data. Extension dictionary and
@@ -279,7 +284,7 @@ extern PyObject* kint64min_py;
extern PyObject* kint64max_py;
extern PyObject* kuint64max_py;
-#define C(str) const_cast<char*>(str)
+#define FULL_MODULE_NAME "google.protobuf.pyext._message"
void FormatTypeError(PyObject* arg, char* expected_types);
template<class T>
diff --git a/python/google/protobuf/pyext/message_map_container.cc b/python/google/protobuf/pyext/message_map_container.cc
new file mode 100644
index 00000000..ab8d8fb9
--- /dev/null
+++ b/python/google/protobuf/pyext/message_map_container.cc
@@ -0,0 +1,540 @@
+// 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: haberman@google.com (Josh Haberman)
+
+#include <google/protobuf/pyext/message_map_container.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+struct MessageMapIterator {
+ PyObject_HEAD;
+
+ // This dict contains the full contents of what we want to iterate over.
+ // There's no way to avoid building this, because the list representation
+ // (which is canonical) can contain duplicate keys. So at the very least we
+ // need a set that lets us skip duplicate keys. And at the point that we're
+ // doing that, we might as well just build the actual dict we're iterating
+ // over and use dict's built-in iterator.
+ PyObject* dict;
+
+ // An iterator on dict.
+ PyObject* iter;
+
+ // A pointer back to the container, so we can notice changes to the version.
+ MessageMapContainer* container;
+
+ // The version of the map when we took the iterator to it.
+ //
+ // We store this so that if the map is modified during iteration we can throw
+ // an error.
+ uint64 version;
+};
+
+static MessageMapIterator* GetIter(PyObject* obj) {
+ return reinterpret_cast<MessageMapIterator*>(obj);
+}
+
+namespace message_map_container {
+
+static MessageMapContainer* GetMap(PyObject* obj) {
+ return reinterpret_cast<MessageMapContainer*>(obj);
+}
+
+// The private constructor of MessageMapContainer objects.
+PyObject* NewContainer(CMessage* parent,
+ const google::protobuf::FieldDescriptor* parent_field_descriptor,
+ PyObject* concrete_class) {
+ if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+ return NULL;
+ }
+
+ PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0);
+ if (obj == NULL) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Could not allocate new container.");
+ }
+
+ MessageMapContainer* self = GetMap(obj);
+
+ self->message = parent->message;
+ self->parent = parent;
+ self->parent_field_descriptor = parent_field_descriptor;
+ self->owner = parent->owner;
+ self->version = 0;
+
+ self->key_field_descriptor =
+ parent_field_descriptor->message_type()->FindFieldByName("key");
+ self->value_field_descriptor =
+ parent_field_descriptor->message_type()->FindFieldByName("value");
+
+ self->message_dict = PyDict_New();
+ if (self->message_dict == NULL) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Could not allocate message dict.");
+ }
+
+ Py_INCREF(concrete_class);
+ self->subclass_init = concrete_class;
+
+ if (self->key_field_descriptor == NULL ||
+ self->value_field_descriptor == NULL) {
+ Py_DECREF(obj);
+ return PyErr_Format(PyExc_KeyError,
+ "Map entry descriptor did not have key/value fields");
+ }
+
+ return obj;
+}
+
+// Initializes the underlying Message object of "to" so it becomes a new parent
+// repeated scalar, and copies all the values from "from" to it. A child scalar
+// container can be released by passing it as both from and to (e.g. making it
+// the recipient of the new parent message and copying the values from itself).
+static int InitializeAndCopyToParentContainer(
+ MessageMapContainer* from,
+ MessageMapContainer* to) {
+ // For now we require from == to, re-evaluate if we want to support deep copy
+ // as in repeated_composite_container.cc.
+ GOOGLE_DCHECK(from == to);
+ Message* old_message = from->message;
+ Message* new_message = old_message->New();
+ to->parent = NULL;
+ to->parent_field_descriptor = from->parent_field_descriptor;
+ to->message = new_message;
+ to->owner.reset(new_message);
+
+ vector<const FieldDescriptor*> fields;
+ fields.push_back(from->parent_field_descriptor);
+ old_message->GetReflection()->SwapFields(old_message, new_message, fields);
+ return 0;
+}
+
+static PyObject* GetCMessage(MessageMapContainer* self, Message* entry) {
+ // Get or create the CMessage object corresponding to this message.
+ Message* message = entry->GetReflection()->MutableMessage(
+ entry, self->value_field_descriptor);
+ ScopedPyObjectPtr key(PyLong_FromVoidPtr(message));
+ PyObject* ret = PyDict_GetItem(self->message_dict, key);
+
+ if (ret == NULL) {
+ CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init,
+ message->GetDescriptor());
+ ret = reinterpret_cast<PyObject*>(cmsg);
+
+ if (cmsg == NULL) {
+ return NULL;
+ }
+ cmsg->owner = self->owner;
+ cmsg->message = message;
+ cmsg->parent = self->parent;
+
+ if (PyDict_SetItem(self->message_dict, key, ret) < 0) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ } else {
+ Py_INCREF(ret);
+ }
+
+ return ret;
+}
+
+int Release(MessageMapContainer* self) {
+ InitializeAndCopyToParentContainer(self, self);
+ return 0;
+}
+
+void SetOwner(MessageMapContainer* self,
+ const shared_ptr<Message>& new_owner) {
+ self->owner = new_owner;
+}
+
+Py_ssize_t Length(PyObject* _self) {
+ MessageMapContainer* self = GetMap(_self);
+ google::protobuf::Message* message = self->message;
+ return message->GetReflection()->FieldSize(*message,
+ self->parent_field_descriptor);
+}
+
+int MapKeyMatches(MessageMapContainer* self, const Message* entry,
+ PyObject* key) {
+ // TODO(haberman): do we need more strict type checking?
+ ScopedPyObjectPtr entry_key(
+ cmessage::InternalGetScalar(entry, self->key_field_descriptor));
+ int ret = PyObject_RichCompareBool(key, entry_key, Py_EQ);
+ return ret;
+}
+
+int SetItem(PyObject *_self, PyObject *key, PyObject *v) {
+ if (v) {
+ PyErr_Format(PyExc_ValueError,
+ "Direct assignment of submessage not allowed");
+ return -1;
+ }
+
+ // Now we know that this is a delete, not a set.
+
+ MessageMapContainer* self = GetMap(_self);
+ cmessage::AssureWritable(self->parent);
+
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+ size_t size =
+ reflection->FieldSize(*message, self->parent_field_descriptor);
+
+ // Right now the Reflection API doesn't support map lookup, so we implement it
+ // via linear search. We need to search from the end because the underlying
+ // representation can have duplicates if a user calls MergeFrom(); the last
+ // one needs to win.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ bool found = false;
+ for (int i = size - 1; i >= 0; i--) {
+ Message* entry = reflection->MutableRepeatedMessage(
+ message, self->parent_field_descriptor, i);
+ int matches = MapKeyMatches(self, entry, key);
+ if (matches < 0) return -1;
+ if (matches) {
+ found = true;
+ if (i != size - 1) {
+ reflection->SwapElements(message, self->parent_field_descriptor, i,
+ size - 1);
+ }
+ reflection->RemoveLast(message, self->parent_field_descriptor);
+
+ // Can't exit now, the repeated field representation of maps allows
+ // duplicate keys, and we have to be sure to remove all of them.
+ }
+ }
+
+ if (!found) {
+ PyErr_Format(PyExc_KeyError, "Key not present in map");
+ return -1;
+ }
+
+ self->version++;
+
+ return 0;
+}
+
+PyObject* GetIterator(PyObject *_self) {
+ MessageMapContainer* self = GetMap(_self);
+
+ ScopedPyObjectPtr obj(PyType_GenericAlloc(&MessageMapIterator_Type, 0));
+ if (obj == NULL) {
+ return PyErr_Format(PyExc_KeyError, "Could not allocate iterator");
+ }
+
+ MessageMapIterator* iter = GetIter(obj);
+
+ Py_INCREF(self);
+ iter->container = self;
+ iter->version = self->version;
+ iter->dict = PyDict_New();
+ if (iter->dict == NULL) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Could not allocate dict for iterator.");
+ }
+
+ // Build the entire map into a dict right now. Start from the beginning so
+ // that later entries win in the case of duplicates.
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ // Right now the Reflection API doesn't support map lookup, so we implement it
+ // via linear search. We need to search from the end because the underlying
+ // representation can have duplicates if a user calls MergeFrom(); the last
+ // one needs to win.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ size_t size =
+ reflection->FieldSize(*message, self->parent_field_descriptor);
+ for (int i = size - 1; i >= 0; i--) {
+ Message* entry = reflection->MutableRepeatedMessage(
+ message, self->parent_field_descriptor, i);
+ ScopedPyObjectPtr key(
+ cmessage::InternalGetScalar(entry, self->key_field_descriptor));
+ if (PyDict_SetItem(iter->dict, key.get(), GetCMessage(self, entry)) < 0) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "SetItem failed in iterator construction.");
+ }
+ }
+
+ iter->iter = PyObject_GetIter(iter->dict);
+
+ return obj.release();
+}
+
+PyObject* GetItem(PyObject* _self, PyObject* key) {
+ MessageMapContainer* self = GetMap(_self);
+ cmessage::AssureWritable(self->parent);
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ // Right now the Reflection API doesn't support map lookup, so we implement it
+ // via linear search. We need to search from the end because the underlying
+ // representation can have duplicates if a user calls MergeFrom(); the last
+ // one needs to win.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ size_t size =
+ reflection->FieldSize(*message, self->parent_field_descriptor);
+ for (int i = size - 1; i >= 0; i--) {
+ Message* entry = reflection->MutableRepeatedMessage(
+ message, self->parent_field_descriptor, i);
+ int matches = MapKeyMatches(self, entry, key);
+ if (matches < 0) return NULL;
+ if (matches) {
+ return GetCMessage(self, entry);
+ }
+ }
+
+ // Key is not already present; insert a new entry.
+ Message* entry =
+ reflection->AddMessage(message, self->parent_field_descriptor);
+
+ self->version++;
+
+ if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor,
+ key) < 0) {
+ reflection->RemoveLast(message, self->parent_field_descriptor);
+ return NULL;
+ }
+
+ return GetCMessage(self, entry);
+}
+
+PyObject* Contains(PyObject* _self, PyObject* key) {
+ MessageMapContainer* self = GetMap(_self);
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ // Right now the Reflection API doesn't support map lookup, so we implement it
+ // via linear search.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ size_t size =
+ reflection->FieldSize(*message, self->parent_field_descriptor);
+ for (int i = 0; i < size; i++) {
+ Message* entry = reflection->MutableRepeatedMessage(
+ message, self->parent_field_descriptor, i);
+ int matches = MapKeyMatches(self, entry, key);
+ if (matches < 0) return NULL;
+ if (matches) {
+ Py_RETURN_TRUE;
+ }
+ }
+
+ Py_RETURN_FALSE;
+}
+
+PyObject* Clear(PyObject* _self) {
+ MessageMapContainer* self = GetMap(_self);
+ cmessage::AssureWritable(self->parent);
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ self->version++;
+ reflection->ClearField(message, self->parent_field_descriptor);
+
+ Py_RETURN_NONE;
+}
+
+PyObject* Get(PyObject* self, PyObject* args) {
+ PyObject* key;
+ PyObject* default_value = NULL;
+ if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
+ return NULL;
+ }
+
+ ScopedPyObjectPtr is_present(Contains(self, key));
+ if (is_present.get() == NULL) {
+ return NULL;
+ }
+
+ if (PyObject_IsTrue(is_present.get())) {
+ return GetItem(self, key);
+ } else {
+ if (default_value != NULL) {
+ Py_INCREF(default_value);
+ return default_value;
+ } else {
+ Py_RETURN_NONE;
+ }
+ }
+}
+
+static PyMappingMethods MpMethods = {
+ Length, // mp_length
+ GetItem, // mp_subscript
+ SetItem, // mp_ass_subscript
+};
+
+static void Dealloc(PyObject* _self) {
+ MessageMapContainer* self = GetMap(_self);
+ self->owner.reset();
+ Py_DECREF(self->message_dict);
+ Py_TYPE(_self)->tp_free(_self);
+}
+
+static PyMethodDef Methods[] = {
+ { "__contains__", (PyCFunction)Contains, METH_O,
+ "Tests whether the map contains this element."},
+ { "clear", (PyCFunction)Clear, METH_NOARGS,
+ "Removes all elements from the map."},
+ { "get", Get, METH_VARARGS,
+ "Gets the value for the given key if present, or otherwise a default" },
+ { "get_or_create", GetItem, METH_O,
+ "Alias for getitem, useful to make explicit that the map is mutated." },
+ /*
+ { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
+ "Makes a deep copy of the class." },
+ { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
+ "Outputs picklable representation of the repeated field." },
+ */
+ {NULL, NULL},
+};
+
+} // namespace message_map_container
+
+namespace message_map_iterator {
+
+static void Dealloc(PyObject* _self) {
+ MessageMapIterator* self = GetIter(_self);
+ Py_DECREF(self->dict);
+ Py_DECREF(self->iter);
+ Py_DECREF(self->container);
+ Py_TYPE(_self)->tp_free(_self);
+}
+
+PyObject* IterNext(PyObject* _self) {
+ MessageMapIterator* self = GetIter(_self);
+
+ // This won't catch mutations to the map performed by MergeFrom(); no easy way
+ // to address that.
+ if (self->version != self->container->version) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Map modified during iteration.");
+ }
+
+ return PyIter_Next(self->iter);
+}
+
+} // namespace message_map_iterator
+
+PyTypeObject MessageMapContainer_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".MessageMapContainer", // tp_name
+ sizeof(MessageMapContainer), // tp_basicsize
+ 0, // tp_itemsize
+ message_map_container::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
+ &message_map_container::MpMethods, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ "A map container for message", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ message_map_container::GetIterator, // tp_iter
+ 0, // tp_iternext
+ message_map_container::Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+};
+
+PyTypeObject MessageMapIterator_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".MessageMapIterator", // tp_name
+ sizeof(MessageMapIterator), // tp_basicsize
+ 0, // tp_itemsize
+ message_map_iterator::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
+ "A scalar map iterator", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ PyObject_SelfIter, // tp_iter
+ message_map_iterator::IterNext, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+};
+
+} // namespace python
+} // namespace protobuf
+} // namespace google
diff --git a/python/google/protobuf/pyext/message_map_container.h b/python/google/protobuf/pyext/message_map_container.h
new file mode 100644
index 00000000..4ca0aecc
--- /dev/null
+++ b/python/google/protobuf/pyext/message_map_container.h
@@ -0,0 +1,117 @@
+// 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_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__
+
+#include <Python.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+using internal::shared_ptr;
+
+namespace python {
+
+struct CMessage;
+
+struct MessageMapContainer {
+ PyObject_HEAD;
+
+ // This is the top-level C++ Message object that owns the whole
+ // proto tree. Every Python MessageMapContainer 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;
+
+ // Pointer to the C++ Message that contains this container. The
+ // MessageMapContainer does not own this pointer.
+ Message* message;
+
+ // Weak reference to a parent CMessage object (i.e. may be NULL.)
+ //
+ // Used to make sure all ancestors are also mutable when first
+ // modifying the container.
+ CMessage* parent;
+
+ // Pointer to the parent's descriptor that describes this
+ // field. Used together with the parent's message when making a
+ // default message instance mutable.
+ // The pointer is owned by the global DescriptorPool.
+ const FieldDescriptor* parent_field_descriptor;
+ const FieldDescriptor* key_field_descriptor;
+ const FieldDescriptor* value_field_descriptor;
+
+ // A callable that is used to create new child messages.
+ PyObject* subclass_init;
+
+ // A dict mapping Message* -> CMessage.
+ PyObject* message_dict;
+
+ // We bump this whenever we perform a mutation, to invalidate existing
+ // iterators.
+ uint64 version;
+};
+
+extern PyTypeObject MessageMapContainer_Type;
+extern PyTypeObject MessageMapIterator_Type;
+
+namespace message_map_container {
+
+// Builds a MessageMapContainer object, from a parent message and a
+// field descriptor.
+extern PyObject* NewContainer(CMessage* parent,
+ const FieldDescriptor* parent_field_descriptor,
+ PyObject* concrete_class);
+
+// Releases the messages in the container to a new message.
+//
+// Returns 0 on success, -1 on failure.
+int Release(MessageMapContainer* self);
+
+// Set the owner field of self and any children of self.
+void SetOwner(MessageMapContainer* self,
+ const shared_ptr<Message>& new_owner);
+
+} // namespace message_map_container
+} // namespace python
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 0fe98e73..86b75d0f 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -367,8 +367,8 @@ int AssignSubscript(RepeatedCompositeContainer* self,
}
// Delete from the underlying Message, if any.
- if (self->message != NULL) {
- if (cmessage::InternalDeleteRepeatedField(self->message,
+ if (self->parent != NULL) {
+ if (cmessage::InternalDeleteRepeatedField(self->parent,
self->parent_field_descriptor,
slice,
self->child_messages) < 0) {
@@ -572,47 +572,35 @@ static PyObject* Pop(RepeatedCompositeContainer* self,
return item;
}
-// The caller takes ownership of the returned Message.
-Message* ReleaseLast(const FieldDescriptor* field,
- const Descriptor* type,
- Message* message) {
+// Release field of parent message and transfer the ownership to target.
+void ReleaseLastTo(CMessage* parent,
+ const FieldDescriptor* field,
+ CMessage* target) {
+ GOOGLE_CHECK_NOTNULL(parent);
GOOGLE_CHECK_NOTNULL(field);
- GOOGLE_CHECK_NOTNULL(type);
- GOOGLE_CHECK_NOTNULL(message);
+ GOOGLE_CHECK_NOTNULL(target);
- Message* released_message = message->GetReflection()->ReleaseLast(
- message, field);
+ shared_ptr<Message> released_message(
+ parent->message->GetReflection()->ReleaseLast(parent->message, field));
// TODO(tibell): Deal with proto1.
// ReleaseMessage will return NULL which differs from
// child_cmessage->message, if the field does not exist. In this case,
// the latter points to the default instance via a const_cast<>, so we
// have to reset it to a new mutable object since we are taking ownership.
- if (released_message == NULL) {
+ if (released_message.get() == NULL) {
const Message* prototype =
- cmessage::GetMessageFactory()->GetPrototype(type);
+ cmessage::GetMessageFactory()->GetPrototype(
+ target->message->GetDescriptor());
GOOGLE_CHECK_NOTNULL(prototype);
- return prototype->New();
- } else {
- return released_message;
+ released_message.reset(prototype->New());
}
-}
-// Release field of message and transfer the ownership to cmessage.
-void ReleaseLastTo(const FieldDescriptor* field,
- Message* message,
- CMessage* cmessage) {
- GOOGLE_CHECK_NOTNULL(field);
- GOOGLE_CHECK_NOTNULL(message);
- GOOGLE_CHECK_NOTNULL(cmessage);
-
- shared_ptr<Message> released_message(
- ReleaseLast(field, cmessage->message->GetDescriptor(), message));
- cmessage->parent = NULL;
- cmessage->parent_field_descriptor = NULL;
- cmessage->message = released_message.get();
- cmessage->read_only = false;
- cmessage::SetOwner(cmessage, released_message);
+ target->parent = NULL;
+ target->parent_field_descriptor = NULL;
+ target->message = released_message.get();
+ target->read_only = false;
+ cmessage::SetOwner(target, released_message);
}
// Called to release a container using
@@ -635,7 +623,7 @@ int Release(RepeatedCompositeContainer* self) {
for (Py_ssize_t i = size - 1; i >= 0; --i) {
CMessage* child_cmessage = reinterpret_cast<CMessage*>(
PyList_GET_ITEM(self->child_messages, i));
- ReleaseLastTo(field, message, child_cmessage);
+ ReleaseLastTo(self->parent, field, child_cmessage);
}
// Detach from containing message.
@@ -732,9 +720,7 @@ static PyMethodDef Methods[] = {
PyTypeObject RepeatedCompositeContainer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- // Keep the fully qualified _message symbol in a line for opensource.
- "google.protobuf.pyext._message."
- "RepeatedCompositeContainer", // tp_name
+ FULL_MODULE_NAME ".RepeatedCompositeContainer", // tp_name
sizeof(RepeatedCompositeContainer), // tp_basicsize
0, // tp_itemsize
(destructor)repeated_composite_container::Dealloc, // tp_dealloc
diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h
index ce7cee0f..e0f21360 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.h
+++ b/python/google/protobuf/pyext/repeated_composite_container.h
@@ -161,13 +161,13 @@ int SetOwner(RepeatedCompositeContainer* self,
const shared_ptr<Message>& new_owner);
// Removes the last element of the repeated message field 'field' on
-// the Message 'message', and transfers the ownership of the released
-// Message to 'cmessage'.
+// the Message 'parent', and transfers the ownership of the released
+// Message to 'target'.
//
// Corresponds to reflection api method ReleaseMessage.
-void ReleaseLastTo(const FieldDescriptor* field,
- Message* message,
- CMessage* cmessage);
+void ReleaseLastTo(CMessage* parent,
+ const FieldDescriptor* field,
+ CMessage* target);
} // namespace repeated_composite_container
} // namespace python
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 110a4c85..fd196836 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -102,7 +102,7 @@ static int AssignItem(RepeatedScalarContainer* self,
if (arg == NULL) {
ScopedPyObjectPtr py_index(PyLong_FromLong(index));
- return cmessage::InternalDeleteRepeatedField(message, field_descriptor,
+ return cmessage::InternalDeleteRepeatedField(self->parent, field_descriptor,
py_index, NULL);
}
@@ -470,7 +470,7 @@ static int AssSubscript(RepeatedScalarContainer* self,
if (value == NULL) {
return cmessage::InternalDeleteRepeatedField(
- message, field_descriptor, slice, NULL);
+ self->parent, field_descriptor, slice, NULL);
}
if (!create_list) {
@@ -769,9 +769,7 @@ static PyMethodDef Methods[] = {
PyTypeObject RepeatedScalarContainer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- // Keep the fully qualified _message symbol in a line for opensource.
- "google.protobuf.pyext._message."
- "RepeatedScalarContainer", // tp_name
+ FULL_MODULE_NAME ".RepeatedScalarContainer", // tp_name
sizeof(RepeatedScalarContainer), // tp_basicsize
0, // tp_itemsize
(destructor)repeated_scalar_container::Dealloc, // tp_dealloc
diff --git a/python/google/protobuf/pyext/scalar_map_container.cc b/python/google/protobuf/pyext/scalar_map_container.cc
new file mode 100644
index 00000000..6f731d27
--- /dev/null
+++ b/python/google/protobuf/pyext/scalar_map_container.cc
@@ -0,0 +1,514 @@
+// 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: haberman@google.com (Josh Haberman)
+
+#include <google/protobuf/pyext/scalar_map_container.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+struct ScalarMapIterator {
+ PyObject_HEAD;
+
+ // This dict contains the full contents of what we want to iterate over.
+ // There's no way to avoid building this, because the list representation
+ // (which is canonical) can contain duplicate keys. So at the very least we
+ // need a set that lets us skip duplicate keys. And at the point that we're
+ // doing that, we might as well just build the actual dict we're iterating
+ // over and use dict's built-in iterator.
+ PyObject* dict;
+
+ // An iterator on dict.
+ PyObject* iter;
+
+ // A pointer back to the container, so we can notice changes to the version.
+ ScalarMapContainer* container;
+
+ // The version of the map when we took the iterator to it.
+ //
+ // We store this so that if the map is modified during iteration we can throw
+ // an error.
+ uint64 version;
+};
+
+static ScalarMapIterator* GetIter(PyObject* obj) {
+ return reinterpret_cast<ScalarMapIterator*>(obj);
+}
+
+namespace scalar_map_container {
+
+static ScalarMapContainer* GetMap(PyObject* obj) {
+ return reinterpret_cast<ScalarMapContainer*>(obj);
+}
+
+// The private constructor of ScalarMapContainer objects.
+PyObject *NewContainer(
+ CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) {
+ if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
+ return NULL;
+ }
+
+ ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0));
+ if (obj.get() == NULL) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Could not allocate new container.");
+ }
+
+ ScalarMapContainer* self = GetMap(obj);
+
+ self->message = parent->message;
+ self->parent = parent;
+ self->parent_field_descriptor = parent_field_descriptor;
+ self->owner = parent->owner;
+ self->version = 0;
+
+ self->key_field_descriptor =
+ parent_field_descriptor->message_type()->FindFieldByName("key");
+ self->value_field_descriptor =
+ parent_field_descriptor->message_type()->FindFieldByName("value");
+
+ if (self->key_field_descriptor == NULL ||
+ self->value_field_descriptor == NULL) {
+ return PyErr_Format(PyExc_KeyError,
+ "Map entry descriptor did not have key/value fields");
+ }
+
+ return obj.release();
+}
+
+// Initializes the underlying Message object of "to" so it becomes a new parent
+// repeated scalar, and copies all the values from "from" to it. A child scalar
+// container can be released by passing it as both from and to (e.g. making it
+// the recipient of the new parent message and copying the values from itself).
+static int InitializeAndCopyToParentContainer(
+ ScalarMapContainer* from,
+ ScalarMapContainer* to) {
+ // For now we require from == to, re-evaluate if we want to support deep copy
+ // as in repeated_scalar_container.cc.
+ GOOGLE_DCHECK(from == to);
+ Message* old_message = from->message;
+ Message* new_message = old_message->New();
+ to->parent = NULL;
+ to->parent_field_descriptor = from->parent_field_descriptor;
+ to->message = new_message;
+ to->owner.reset(new_message);
+
+ vector<const FieldDescriptor*> fields;
+ fields.push_back(from->parent_field_descriptor);
+ old_message->GetReflection()->SwapFields(old_message, new_message, fields);
+ return 0;
+}
+
+int Release(ScalarMapContainer* self) {
+ return InitializeAndCopyToParentContainer(self, self);
+}
+
+void SetOwner(ScalarMapContainer* self,
+ const shared_ptr<Message>& new_owner) {
+ self->owner = new_owner;
+}
+
+Py_ssize_t Length(PyObject* _self) {
+ ScalarMapContainer* self = GetMap(_self);
+ google::protobuf::Message* message = self->message;
+ return message->GetReflection()->FieldSize(*message,
+ self->parent_field_descriptor);
+}
+
+int MapKeyMatches(ScalarMapContainer* self, const Message* entry,
+ PyObject* key) {
+ // TODO(haberman): do we need more strict type checking?
+ ScopedPyObjectPtr entry_key(
+ cmessage::InternalGetScalar(entry, self->key_field_descriptor));
+ int ret = PyObject_RichCompareBool(key, entry_key, Py_EQ);
+ return ret;
+}
+
+PyObject* GetItem(PyObject* _self, PyObject* key) {
+ ScalarMapContainer* self = GetMap(_self);
+
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ // Right now the Reflection API doesn't support map lookup, so we implement it
+ // via linear search.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ size_t size = reflection->FieldSize(*message, self->parent_field_descriptor);
+ for (int i = size - 1; i >= 0; i--) {
+ const Message& entry = reflection->GetRepeatedMessage(
+ *message, self->parent_field_descriptor, i);
+ int matches = MapKeyMatches(self, &entry, key);
+ if (matches < 0) return NULL;
+ if (matches) {
+ return cmessage::InternalGetScalar(&entry, self->value_field_descriptor);
+ }
+ }
+
+ // Need to add a new entry.
+ Message* entry =
+ reflection->AddMessage(message, self->parent_field_descriptor);
+ PyObject* ret = NULL;
+
+ if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor,
+ key) >= 0) {
+ ret = cmessage::InternalGetScalar(entry, self->value_field_descriptor);
+ }
+
+ self->version++;
+
+ // If there was a type error above, it set the Python exception.
+ return ret;
+}
+
+int SetItem(PyObject *_self, PyObject *key, PyObject *v) {
+ ScalarMapContainer* self = GetMap(_self);
+ cmessage::AssureWritable(self->parent);
+
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+ size_t size =
+ reflection->FieldSize(*message, self->parent_field_descriptor);
+ self->version++;
+
+ if (v) {
+ // Set item.
+ //
+ // Right now the Reflection API doesn't support map lookup, so we implement
+ // it via linear search.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ for (int i = size - 1; i >= 0; i--) {
+ Message* entry = reflection->MutableRepeatedMessage(
+ message, self->parent_field_descriptor, i);
+ int matches = MapKeyMatches(self, entry, key);
+ if (matches < 0) return -1;
+ if (matches) {
+ return cmessage::InternalSetNonOneofScalar(
+ entry, self->value_field_descriptor, v);
+ }
+ }
+
+ // Key is not already present; insert a new entry.
+ Message* entry =
+ reflection->AddMessage(message, self->parent_field_descriptor);
+
+ if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor,
+ key) < 0 ||
+ cmessage::InternalSetNonOneofScalar(entry, self->value_field_descriptor,
+ v) < 0) {
+ reflection->RemoveLast(message, self->parent_field_descriptor);
+ return -1;
+ }
+
+ return 0;
+ } else {
+ bool found = false;
+ for (int i = size - 1; i >= 0; i--) {
+ Message* entry = reflection->MutableRepeatedMessage(
+ message, self->parent_field_descriptor, i);
+ int matches = MapKeyMatches(self, entry, key);
+ if (matches < 0) return -1;
+ if (matches) {
+ found = true;
+ if (i != size - 1) {
+ reflection->SwapElements(message, self->parent_field_descriptor, i,
+ size - 1);
+ }
+ reflection->RemoveLast(message, self->parent_field_descriptor);
+
+ // Can't exit now, the repeated field representation of maps allows
+ // duplicate keys, and we have to be sure to remove all of them.
+ }
+ }
+
+ if (found) {
+ return 0;
+ } else {
+ PyErr_Format(PyExc_KeyError, "Key not present in map");
+ return -1;
+ }
+ }
+}
+
+PyObject* GetIterator(PyObject *_self) {
+ ScalarMapContainer* self = GetMap(_self);
+
+ ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapIterator_Type, 0));
+ if (obj == NULL) {
+ return PyErr_Format(PyExc_KeyError, "Could not allocate iterator");
+ }
+
+ ScalarMapIterator* iter = GetIter(obj.get());
+
+ Py_INCREF(self);
+ iter->container = self;
+ iter->version = self->version;
+ iter->dict = PyDict_New();
+ if (iter->dict == NULL) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Could not allocate dict for iterator.");
+ }
+
+ // Build the entire map into a dict right now. Start from the beginning so
+ // that later entries win in the case of duplicates.
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ // Right now the Reflection API doesn't support map lookup, so we implement it
+ // via linear search. We need to search from the end because the underlying
+ // representation can have duplicates if a user calls MergeFrom(); the last
+ // one needs to win.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ size_t size =
+ reflection->FieldSize(*message, self->parent_field_descriptor);
+ for (int i = 0; i < size; i++) {
+ Message* entry = reflection->MutableRepeatedMessage(
+ message, self->parent_field_descriptor, i);
+ ScopedPyObjectPtr key(
+ cmessage::InternalGetScalar(entry, self->key_field_descriptor));
+ ScopedPyObjectPtr val(
+ cmessage::InternalGetScalar(entry, self->value_field_descriptor));
+ if (PyDict_SetItem(iter->dict, key.get(), val.get()) < 0) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "SetItem failed in iterator construction.");
+ }
+ }
+
+
+ iter->iter = PyObject_GetIter(iter->dict);
+
+
+ return obj.release();
+}
+
+PyObject* Clear(PyObject* _self) {
+ ScalarMapContainer* self = GetMap(_self);
+ cmessage::AssureWritable(self->parent);
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ reflection->ClearField(message, self->parent_field_descriptor);
+
+ Py_RETURN_NONE;
+}
+
+PyObject* Contains(PyObject* _self, PyObject* key) {
+ ScalarMapContainer* self = GetMap(_self);
+
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+
+ // Right now the Reflection API doesn't support map lookup, so we implement it
+ // via linear search.
+ //
+ // TODO(haberman): add lookup API to Reflection API.
+ size_t size = reflection->FieldSize(*message, self->parent_field_descriptor);
+ for (int i = size - 1; i >= 0; i--) {
+ const Message& entry = reflection->GetRepeatedMessage(
+ *message, self->parent_field_descriptor, i);
+ int matches = MapKeyMatches(self, &entry, key);
+ if (matches < 0) return NULL;
+ if (matches) {
+ Py_RETURN_TRUE;
+ }
+ }
+
+ Py_RETURN_FALSE;
+}
+
+PyObject* Get(PyObject* self, PyObject* args) {
+ PyObject* key;
+ PyObject* default_value = NULL;
+ if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) {
+ return NULL;
+ }
+
+ ScopedPyObjectPtr is_present(Contains(self, key));
+ if (is_present.get() == NULL) {
+ return NULL;
+ }
+
+ if (PyObject_IsTrue(is_present.get())) {
+ return GetItem(self, key);
+ } else {
+ if (default_value != NULL) {
+ Py_INCREF(default_value);
+ return default_value;
+ } else {
+ Py_RETURN_NONE;
+ }
+ }
+}
+
+static PyMappingMethods MpMethods = {
+ Length, // mp_length
+ GetItem, // mp_subscript
+ SetItem, // mp_ass_subscript
+};
+
+static void Dealloc(PyObject* _self) {
+ ScalarMapContainer* self = GetMap(_self);
+ self->owner.reset();
+ Py_TYPE(_self)->tp_free(_self);
+}
+
+static PyMethodDef Methods[] = {
+ { "__contains__", Contains, METH_O,
+ "Tests whether a key is a member of the map." },
+ { "clear", (PyCFunction)Clear, METH_NOARGS,
+ "Removes all elements from the map." },
+ { "get", Get, METH_VARARGS,
+ "Gets the value for the given key if present, or otherwise a default" },
+ /*
+ { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS,
+ "Makes a deep copy of the class." },
+ { "__reduce__", (PyCFunction)Reduce, METH_NOARGS,
+ "Outputs picklable representation of the repeated field." },
+ */
+ {NULL, NULL},
+};
+
+} // namespace scalar_map_container
+
+namespace scalar_map_iterator {
+
+static void Dealloc(PyObject* _self) {
+ ScalarMapIterator* self = GetIter(_self);
+ Py_DECREF(self->dict);
+ Py_DECREF(self->iter);
+ Py_DECREF(self->container);
+ Py_TYPE(_self)->tp_free(_self);
+}
+
+PyObject* IterNext(PyObject* _self) {
+ ScalarMapIterator* self = GetIter(_self);
+
+ // This won't catch mutations to the map performed by MergeFrom(); no easy way
+ // to address that.
+ if (self->version != self->container->version) {
+ return PyErr_Format(PyExc_RuntimeError,
+ "Map modified during iteration.");
+ }
+
+ return PyIter_Next(self->iter);
+}
+
+} // namespace scalar_map_iterator
+
+PyTypeObject ScalarMapContainer_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".ScalarMapContainer", // tp_name
+ sizeof(ScalarMapContainer), // tp_basicsize
+ 0, // tp_itemsize
+ scalar_map_container::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
+ &scalar_map_container::MpMethods, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ "A scalar map container", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ scalar_map_container::GetIterator, // tp_iter
+ 0, // tp_iternext
+ scalar_map_container::Methods, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+};
+
+PyTypeObject ScalarMapIterator_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".ScalarMapIterator", // tp_name
+ sizeof(ScalarMapIterator), // tp_basicsize
+ 0, // tp_itemsize
+ scalar_map_iterator::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
+ "A scalar map iterator", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ PyObject_SelfIter, // tp_iter
+ scalar_map_iterator::IterNext, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ 0, // tp_getset
+ 0, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+};
+
+} // namespace python
+} // namespace protobuf
+} // namespace google
diff --git a/python/google/protobuf/pyext/scalar_map_container.h b/python/google/protobuf/pyext/scalar_map_container.h
new file mode 100644
index 00000000..254e6e98
--- /dev/null
+++ b/python/google/protobuf/pyext/scalar_map_container.h
@@ -0,0 +1,110 @@
+// 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_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__
+
+#include <Python.h>
+
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+using internal::shared_ptr;
+
+namespace python {
+
+struct CMessage;
+
+struct ScalarMapContainer {
+ PyObject_HEAD;
+
+ // This is the top-level C++ Message object that owns the whole
+ // proto tree. Every Python ScalarMapContainer 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;
+
+ // Pointer to the C++ Message that contains this container. The
+ // ScalarMapContainer does not own this pointer.
+ Message* message;
+
+ // Weak reference to a parent CMessage object (i.e. may be NULL.)
+ //
+ // Used to make sure all ancestors are also mutable when first
+ // modifying the container.
+ CMessage* parent;
+
+ // Pointer to the parent's descriptor that describes this
+ // field. Used together with the parent's message when making a
+ // default message instance mutable.
+ // The pointer is owned by the global DescriptorPool.
+ const FieldDescriptor* parent_field_descriptor;
+ const FieldDescriptor* key_field_descriptor;
+ const FieldDescriptor* value_field_descriptor;
+
+ // We bump this whenever we perform a mutation, to invalidate existing
+ // iterators.
+ uint64 version;
+};
+
+extern PyTypeObject ScalarMapContainer_Type;
+extern PyTypeObject ScalarMapIterator_Type;
+
+namespace scalar_map_container {
+
+// Builds a ScalarMapContainer object, from a parent message and a
+// field descriptor.
+extern PyObject *NewContainer(
+ CMessage* parent, const FieldDescriptor* parent_field_descriptor);
+
+// Releases the messages in the container to a new message.
+//
+// Returns 0 on success, -1 on failure.
+int Release(ScalarMapContainer* self);
+
+// Set the owner field of self and any children of self.
+void SetOwner(ScalarMapContainer* self,
+ const shared_ptr<Message>& new_owner);
+
+} // namespace scalar_map_container
+} // namespace python
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 55e653a0..82fca661 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -144,7 +144,6 @@ class GeneratedProtocolMessageType(type):
_InitMessage(descriptor, cls)
superclass = super(GeneratedProtocolMessageType, cls)
superclass.__init__(name, bases, dictionary)
- setattr(descriptor, '_concrete_class', cls)
def ParseMessage(descriptor, byte_str):
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index a47ce3e3..8cbd6822 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -100,6 +100,10 @@ def MessageToString(message, as_utf8=False, as_one_line=False,
return result.rstrip()
return result
+def _IsMapEntry(field):
+ return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
+ field.message_type.has_options and
+ field.message_type.GetOptions().map_entry)
def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False,
pointy_brackets=False, use_index_order=False,
@@ -108,7 +112,19 @@ def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False,
if use_index_order:
fields.sort(key=lambda x: x[0].index)
for field, value in fields:
- if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+ if _IsMapEntry(field):
+ for key in value:
+ # This is slow for maps with submessage entires because it copies the
+ # entire tree. Unfortunately this would take significant refactoring
+ # of this file to work around.
+ #
+ # TODO(haberman): refactor and optimize if this becomes an issue.
+ entry_submsg = field.message_type._concrete_class(
+ key=key, value=value[key])
+ PrintField(field, entry_submsg, out, indent, as_utf8, as_one_line,
+ pointy_brackets=pointy_brackets,
+ use_index_order=use_index_order, float_format=float_format)
+ elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
for element in value:
PrintField(field, element, out, indent, as_utf8, as_one_line,
pointy_brackets=pointy_brackets,
@@ -367,6 +383,7 @@ def _MergeField(tokenizer, message, allow_multiple_scalars):
message_descriptor.full_name, name))
if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+ is_map_entry = _IsMapEntry(field)
tokenizer.TryConsume(':')
if tokenizer.TryConsume('<'):
@@ -378,6 +395,8 @@ def _MergeField(tokenizer, message, allow_multiple_scalars):
if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
if field.is_extension:
sub_message = message.Extensions[field].add()
+ elif is_map_entry:
+ sub_message = field.message_type._concrete_class()
else:
sub_message = getattr(message, field.name).add()
else:
@@ -391,6 +410,14 @@ def _MergeField(tokenizer, message, allow_multiple_scalars):
if tokenizer.AtEnd():
raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token))
_MergeField(tokenizer, sub_message, allow_multiple_scalars)
+
+ if is_map_entry:
+ value_cpptype = field.message_type.fields_by_name['value'].cpp_type
+ if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+ value = getattr(message, field.name)[sub_message.key]
+ value.MergeFrom(sub_message.value)
+ else:
+ getattr(message, field.name)[sub_message.key] = sub_message.value
else:
_MergeScalarField(tokenizer, message, field, allow_multiple_scalars)
@@ -701,13 +728,16 @@ class _Tokenizer(object):
String literals (whether bytes or text) can come in multiple adjacent
tokens which are automatically concatenated, like in C or Python. This
method only consumes one token.
+
+ Raises:
+ ParseError: When the wrong format data is found.
"""
text = self.token
if len(text) < 1 or text[0] not in ('\'', '"'):
- raise self._ParseError('Expected string but found: "%r"' % text)
+ raise self._ParseError('Expected string but found: %r' % (text,))
if len(text) < 2 or text[-1] != text[0]:
- raise self._ParseError('String missing ending quote.')
+ raise self._ParseError('String missing ending quote: %r' % (text,))
try:
result = text_encoding.CUnescape(text[1:-1])
diff --git a/python/setup.py b/python/setup.py
index a1365fba..5c321f50 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -91,6 +91,7 @@ def GenerateUnittestProtos():
if not os.path.exists("../.git"):
return
+ generate_proto("../src/google/protobuf/map_unittest.proto")
generate_proto("../src/google/protobuf/unittest.proto")
generate_proto("../src/google/protobuf/unittest_custom_options.proto")
generate_proto("../src/google/protobuf/unittest_import.proto")
diff --git a/ruby/tests/generated_code.proto b/ruby/tests/generated_code.proto
index b1d63232..42d82a6b 100644
--- a/ruby/tests/generated_code.proto
+++ b/ruby/tests/generated_code.proto
@@ -3,17 +3,17 @@ syntax = "proto3";
package A.B.C;
message TestMessage {
- optional int32 optional_int32 = 1;
- optional int64 optional_int64 = 2;
- optional uint32 optional_uint32 = 3;
- optional uint64 optional_uint64 = 4;
- optional bool optional_bool = 5;
- optional double optional_double = 6;
- optional float optional_float = 7;
- optional string optional_string = 8;
- optional bytes optional_bytes = 9;
- optional TestEnum optional_enum = 10;
- optional TestMessage optional_msg = 11;
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ bool optional_bool = 5;
+ double optional_double = 6;
+ float optional_float = 7;
+ string optional_string = 8;
+ bytes optional_bytes = 9;
+ TestEnum optional_enum = 10;
+ TestMessage optional_msg = 11;
repeated int32 repeated_int32 = 21;
repeated int64 repeated_int64 = 22;
@@ -53,10 +53,10 @@ message TestMessage {
map<string, bool> map_string_bool = 70;
message NestedMessage {
- optional int32 foo = 1;
+ int32 foo = 1;
}
- optional NestedMessage nested_message = 80;
+ NestedMessage nested_message = 80;
}
enum TestEnum {
diff --git a/src/Makefile.am b/src/Makefile.am
index fd10b789..2ecf6028 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -88,6 +88,7 @@ nobase_include_HEADERS = \
google/protobuf/stubs/type_traits.h \
google/protobuf/any.pb.h \
google/protobuf/api.pb.h \
+ google/protobuf/any.h \
google/protobuf/arena.h \
google/protobuf/arenastring.h \
google/protobuf/descriptor_database.h \
@@ -186,6 +187,7 @@ libprotobuf_la_SOURCES = \
$(libprotobuf_lite_la_SOURCES) \
google/protobuf/any.pb.cc \
google/protobuf/api.pb.cc \
+ google/protobuf/any.cc \
google/protobuf/descriptor.cc \
google/protobuf/descriptor_database.cc \
google/protobuf/descriptor.pb.cc \
@@ -264,6 +266,8 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_enum.cc \
google/protobuf/compiler/java/java_enum_field.cc \
google/protobuf/compiler/java/java_enum_field.h \
+ google/protobuf/compiler/java/java_enum_field_lite.cc \
+ google/protobuf/compiler/java/java_enum_field_lite.h \
google/protobuf/compiler/java/java_enum.h \
google/protobuf/compiler/java/java_extension.cc \
google/protobuf/compiler/java/java_extension.h \
@@ -278,22 +282,38 @@ 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_lazy_message_field_lite.cc\
+ google/protobuf/compiler/java/java_lazy_message_field_lite.h \
google/protobuf/compiler/java/java_map_field.cc \
google/protobuf/compiler/java/java_map_field.h \
+ google/protobuf/compiler/java/java_map_field_lite.cc \
+ google/protobuf/compiler/java/java_map_field_lite.h \
google/protobuf/compiler/java/java_message.cc \
+ google/protobuf/compiler/java/java_message_lite.cc \
+ google/protobuf/compiler/java/java_message_builder.cc \
+ google/protobuf/compiler/java/java_message_builder_lite.cc \
google/protobuf/compiler/java/java_message_field.cc \
google/protobuf/compiler/java/java_message_field.h \
+ google/protobuf/compiler/java/java_message_field_lite.cc \
+ google/protobuf/compiler/java/java_message_field_lite.h \
google/protobuf/compiler/java/java_message.h \
+ google/protobuf/compiler/java/java_message_lite.h \
+ google/protobuf/compiler/java/java_message_builder.h \
+ google/protobuf/compiler/java/java_message_builder_lite.h \
google/protobuf/compiler/java/java_name_resolver.cc \
google/protobuf/compiler/java/java_name_resolver.h \
google/protobuf/compiler/java/java_primitive_field.cc \
google/protobuf/compiler/java/java_primitive_field.h \
+ google/protobuf/compiler/java/java_primitive_field_lite.cc \
+ google/protobuf/compiler/java/java_primitive_field_lite.h \
google/protobuf/compiler/java/java_shared_code_generator.cc \
google/protobuf/compiler/java/java_shared_code_generator.h \
google/protobuf/compiler/java/java_service.cc \
google/protobuf/compiler/java/java_service.h \
google/protobuf/compiler/java/java_string_field.cc \
google/protobuf/compiler/java/java_string_field.h \
+ google/protobuf/compiler/java/java_string_field_lite.cc \
+ google/protobuf/compiler/java/java_string_field_lite.h \
google/protobuf/compiler/java/java_doc_comment.cc \
google/protobuf/compiler/java/java_doc_comment.h \
google/protobuf/compiler/javanano/javanano_enum.cc \
@@ -381,6 +401,7 @@ protoc_SOURCES = google/protobuf/compiler/main.cc
# Tests ==============================================================
protoc_inputs = \
+ google/protobuf/any_test.proto \
google/protobuf/map_lite_unittest.proto \
google/protobuf/map_proto2_unittest.proto \
google/protobuf/map_unittest.proto \
@@ -419,6 +440,7 @@ EXTRA_DIST = \
google/protobuf/testdata/golden_message_proto3 \
google/protobuf/testdata/golden_packed_fields_message \
google/protobuf/testdata/bad_utf8_string \
+ google/protobuf/testdata/map_test_data.txt \
google/protobuf/testdata/text_format_unittest_data.txt \
google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt \
google/protobuf/testdata/text_format_unittest_data_pointy.txt \
@@ -443,6 +465,8 @@ protoc_lite_outputs = \
protoc_outputs = \
$(protoc_lite_outputs) \
+ google/protobuf/any_test.pb.cc \
+ google/protobuf/any_test.pb.h \
google/protobuf/map_proto2_unittest.pb.cc \
google/protobuf/map_proto2_unittest.pb.h \
google/protobuf/map_unittest.pb.cc \
@@ -543,6 +567,7 @@ 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/any_test.cc \
google/protobuf/arenastring_unittest.cc \
google/protobuf/arena_unittest.cc \
google/protobuf/descriptor_database_unittest.cc \
@@ -604,6 +629,8 @@ nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la
protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
protobuf_lite_test_SOURCES = \
+ google/protobuf/arena_test_util.cc \
+ google/protobuf/arena_test_util.h \
google/protobuf/lite_unittest.cc \
google/protobuf/map_lite_test_util.cc \
google/protobuf/map_lite_test_util.h \
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
new file mode 100644
index 00000000..c66fdfad
--- /dev/null
+++ b/src/google/protobuf/any.cc
@@ -0,0 +1,100 @@
+// 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/any.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+string GetTypeUrl(const Descriptor* message) {
+ return string(kTypeGoogleApisComPrefix) + message->full_name();
+}
+
+} // namespace
+
+const char kAnyFullTypeName[] = "google.protobuf.Any";
+const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/";
+
+AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
+ : type_url_(type_url), value_(value) {
+}
+
+void AnyMetadata::PackFrom(const Message& message) {
+ type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
+ GetTypeUrl(message.GetDescriptor()));
+ message.SerializeToString(value_->MutableNoArena(
+ &::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+}
+
+bool AnyMetadata::UnpackTo(Message* message) const {
+ if (!InternalIs(message->GetDescriptor())) {
+ return false;
+ }
+ return message->ParseFromString(
+ value_->GetNoArena(&::google::protobuf::internal::GetEmptyString()));
+}
+
+bool AnyMetadata::InternalIs(const Descriptor* descriptor) const {
+ return type_url_->GetNoArena(
+ &::google::protobuf::internal::GetEmptyString()) ==
+ GetTypeUrl(descriptor);
+}
+
+bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
+ const int prefix_len = strlen(kTypeGoogleApisComPrefix);
+ if (strncmp(type_url.c_str(), kTypeGoogleApisComPrefix, prefix_len) == 0) {
+ full_type_name->assign(type_url.data() + prefix_len,
+ type_url.size() - prefix_len);
+ return true;
+ }
+ return true;
+}
+
+
+bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field) {
+ const Descriptor* descriptor = message.GetDescriptor();
+ if (descriptor->full_name() != kAnyFullTypeName) {
+ return false;
+ }
+ *type_url_field = descriptor->FindFieldByNumber(1);
+ *value_field = descriptor->FindFieldByNumber(2);
+ return (*type_url_field != NULL &&
+ (*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
+ *value_field != NULL &&
+ (*value_field)->type() == FieldDescriptor::TYPE_BYTES);
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
new file mode 100644
index 00000000..757b45aa
--- /dev/null
+++ b/src/google/protobuf/any.h
@@ -0,0 +1,90 @@
+// 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_ANY_H__
+#define GOOGLE_PROTOBUF_ANY_H__
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/message.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// Helper class used to implement google::protobuf::Any.
+class AnyMetadata {
+ typedef ArenaStringPtr UrlType;
+ typedef ArenaStringPtr ValueType;
+ public:
+ // AnyMetadata does not take ownership of "type_url" and "value".
+ AnyMetadata(UrlType* type_url, ValueType* value);
+
+ void PackFrom(const Message& message);
+
+ bool UnpackTo(Message* message) const;
+
+ template<typename T>
+ bool Is() const {
+ return InternalIs(T::default_instance().GetDescriptor());
+ }
+
+ private:
+ bool InternalIs(const Descriptor* message) const;
+
+ UrlType* type_url_;
+ ValueType* value_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
+};
+
+extern const char kAnyFullTypeName[]; // "google.protobuf.Any".
+extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/".
+
+// Get the proto type name from Any::type_url value. For example, passing
+// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in
+// *full_type_name. Returns false if type_url does not start with
+// "type.googleapis.com".
+bool ParseAnyTypeUrl(const string& type_url, string* full_type_name);
+
+// See if message is of type google.protobuf.Any, if so, return the descriptors
+// for "type_url" and "value" fields.
+bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field);
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_ANY_H__
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index 75cc8754..2c492b04 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -111,13 +111,21 @@ static void MergeFromFail(int line) {
// ===================================================================
+void Any::PackFrom(const ::google::protobuf::Message& message) {
+ _any_metadata_.PackFrom(message);
+}
+
+bool Any::UnpackTo(::google::protobuf::Message* message) const {
+ return _any_metadata_.UnpackTo(message);
+}
+
#ifndef _MSC_VER
const int Any::kTypeUrlFieldNumber;
const int Any::kValueFieldNumber;
#endif // !_MSC_VER
Any::Any()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Any)
}
@@ -128,7 +136,8 @@ void Any::InitAsDefaultInstance() {
Any::Any(const Any& from)
: ::google::protobuf::Message(),
- _internal_metadata_(NULL) {
+ _internal_metadata_(NULL),
+ _any_metadata_(&type_url_, &value_) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.Any)
@@ -316,9 +325,9 @@ int Any::ByteSize() const {
void Any::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Any* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Any*>(
- &from);
+ const Any* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Any>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -378,7 +387,7 @@ void Any::InternalSwap(Any* other) {
// Any
// optional string type_url = 1;
- void Any::clear_type_url() {
+void Any::clear_type_url() {
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Any::type_url() const {
@@ -421,7 +430,7 @@ void Any::InternalSwap(Any* other) {
}
// optional bytes value = 2;
- void Any::clear_value() {
+void Any::clear_value() {
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Any::value() const {
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index b2c238c1..c324c4af 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -27,6 +27,7 @@
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/any.h"
// @@protoc_insertion_point(includes)
namespace google {
@@ -56,6 +57,14 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message {
static const ::google::protobuf::Descriptor* descriptor();
static const Any& default_instance();
+ // implements Any -----------------------------------------------
+
+ void PackFrom(const ::google::protobuf::Message& message);
+ bool UnpackTo(::google::protobuf::Message* message) const;
+ template<typename T> bool Is() const {
+ return _any_metadata_.Is<T>();
+ }
+
void Swap(Any* other);
// implements Message ----------------------------------------------
@@ -127,6 +136,7 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message {
::google::protobuf::internal::ArenaStringPtr type_url_;
::google::protobuf::internal::ArenaStringPtr value_;
mutable int _cached_size_;
+ ::google::protobuf::internal::AnyMetadata _any_metadata_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto();
diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc
new file mode 100644
index 00000000..1bfaa63d
--- /dev/null
+++ b/src/google/protobuf/any_test.cc
@@ -0,0 +1,89 @@
+// 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/any_test.pb.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace {
+
+TEST(AnyTest, TestPackAndUnpack) {
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(submessage);
+
+ string data = message.SerializeAsString();
+
+ ASSERT_TRUE(message.ParseFromString(data));
+ EXPECT_TRUE(message.has_any_value());
+ ASSERT_TRUE(message.any_value().UnpackTo(&submessage));
+ EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestPackAndUnpackAny) {
+ // We can pack a Any message inside another Any message.
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ google::protobuf::Any any;
+ any.PackFrom(submessage);
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(any);
+
+ string data = message.SerializeAsString();
+
+ ASSERT_TRUE(message.ParseFromString(data));
+ EXPECT_TRUE(message.has_any_value());
+ ASSERT_TRUE(message.any_value().UnpackTo(&any));
+ ASSERT_TRUE(any.UnpackTo(&submessage));
+ EXPECT_EQ(12345, submessage.int32_value());
+}
+
+TEST(AnyTest, TestIs) {
+ protobuf_unittest::TestAny submessage;
+ submessage.set_int32_value(12345);
+ google::protobuf::Any any;
+ any.PackFrom(submessage);
+ ASSERT_TRUE(any.ParseFromString(any.SerializeAsString()));
+ EXPECT_TRUE(any.Is<protobuf_unittest::TestAny>());
+ EXPECT_FALSE(any.Is<google::protobuf::Any>());
+
+ protobuf_unittest::TestAny message;
+ message.mutable_any_value()->PackFrom(any);
+ ASSERT_TRUE(message.ParseFromString(message.SerializeAsString()));
+ EXPECT_FALSE(message.any_value().Is<protobuf_unittest::TestAny>());
+ EXPECT_TRUE(message.any_value().Is<google::protobuf::Any>());
+}
+
+} // namespace
+} // namespace protobuf
+
+} // namespace google
diff --git a/src/google/protobuf/any_test.proto b/src/google/protobuf/any_test.proto
new file mode 100644
index 00000000..0c5b30ba
--- /dev/null
+++ b/src/google/protobuf/any_test.proto
@@ -0,0 +1,41 @@
+// 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 protobuf_unittest;
+
+import "google/protobuf/any.proto";
+
+message TestAny {
+ int32 int32_value = 1;
+ google.protobuf.Any any_value = 2;
+ repeated google.protobuf.Any repeated_any_value = 3;
+}
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index b34ce803..434320dc 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -162,7 +162,7 @@ const int Api::kSourceContextFieldNumber;
#endif // !_MSC_VER
Api::Api()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Api)
}
@@ -230,7 +230,7 @@ Api* Api::New(::google::protobuf::Arena* arena) const {
void Api::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- if (source_context_ != NULL) delete source_context_;
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
methods_.Clear();
options_.Clear();
@@ -266,26 +266,31 @@ bool Api::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_methods:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_methods:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_methods()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_methods;
- if (input->ExpectTag(26)) goto parse_options;
+ if (input->ExpectTag(18)) goto parse_loop_methods;
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.Option options = 3;
case 3: {
if (tag == 26) {
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_options()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(26)) goto parse_options;
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(34)) goto parse_version;
break;
}
@@ -483,9 +488,9 @@ int Api::ByteSize() const {
void Api::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Api* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Api*>(
- &from);
+ const Api* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Api>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -553,7 +558,7 @@ void Api::InternalSwap(Api* other) {
// Api
// optional string name = 1;
- void Api::clear_name() {
+void Api::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Api::name() const {
@@ -596,10 +601,10 @@ void Api::InternalSwap(Api* other) {
}
// repeated .google.protobuf.Method methods = 2;
- int Api::methods_size() const {
+int Api::methods_size() const {
return methods_.size();
}
- void Api::clear_methods() {
+void Api::clear_methods() {
methods_.Clear();
}
const ::google::protobuf::Method& Api::methods(int index) const {
@@ -626,10 +631,10 @@ Api::mutable_methods() {
}
// repeated .google.protobuf.Option options = 3;
- int Api::options_size() const {
+int Api::options_size() const {
return options_.size();
}
- void Api::clear_options() {
+void Api::clear_options() {
options_.Clear();
}
const ::google::protobuf::Option& Api::options(int index) const {
@@ -656,7 +661,7 @@ Api::mutable_options() {
}
// optional string version = 4;
- void Api::clear_version() {
+void Api::clear_version() {
version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Api::version() const {
@@ -699,11 +704,11 @@ Api::mutable_options() {
}
// optional .google.protobuf.SourceContext source_context = 5;
- bool Api::has_source_context() const {
+bool Api::has_source_context() const {
return !_is_default_instance_ && source_context_ != NULL;
}
- void Api::clear_source_context() {
- if (source_context_ != NULL) delete source_context_;
+void Api::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
const ::google::protobuf::SourceContext& Api::source_context() const {
@@ -749,7 +754,7 @@ const int Method::kOptionsFieldNumber;
#endif // !_MSC_VER
Method::Method()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Method)
}
@@ -929,12 +934,15 @@ bool Method::MergePartialFromCodedStream(
case 6: {
if (tag == 50) {
parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_options()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(50)) goto parse_options;
+ if (input->ExpectTag(50)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1119,9 +1127,9 @@ int Method::ByteSize() const {
void Method::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Method* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Method*>(
- &from);
+ const Method* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Method>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1196,7 +1204,7 @@ void Method::InternalSwap(Method* other) {
// Method
// optional string name = 1;
- void Method::clear_name() {
+void Method::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Method::name() const {
@@ -1239,7 +1247,7 @@ void Method::InternalSwap(Method* other) {
}
// optional string request_type_url = 2;
- void Method::clear_request_type_url() {
+void Method::clear_request_type_url() {
request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Method::request_type_url() const {
@@ -1282,7 +1290,7 @@ void Method::InternalSwap(Method* other) {
}
// optional bool request_streaming = 3;
- void Method::clear_request_streaming() {
+void Method::clear_request_streaming() {
request_streaming_ = false;
}
bool Method::request_streaming() const {
@@ -1296,7 +1304,7 @@ void Method::InternalSwap(Method* other) {
}
// optional string response_type_url = 4;
- void Method::clear_response_type_url() {
+void Method::clear_response_type_url() {
response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Method::response_type_url() const {
@@ -1339,7 +1347,7 @@ void Method::InternalSwap(Method* other) {
}
// optional bool response_streaming = 5;
- void Method::clear_response_streaming() {
+void Method::clear_response_streaming() {
response_streaming_ = false;
}
bool Method::response_streaming() const {
@@ -1353,10 +1361,10 @@ void Method::InternalSwap(Method* other) {
}
// repeated .google.protobuf.Option options = 6;
- int Method::options_size() const {
+int Method::options_size() const {
return options_.size();
}
- void Method::clear_options() {
+void Method::clear_options() {
options_.Clear();
}
const ::google::protobuf::Option& Method::options(int index) const {
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index f459af0f..985adc5d 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -466,7 +466,7 @@ inline bool Api::has_source_context() const {
return !_is_default_instance_ && source_context_ != NULL;
}
inline void Api::clear_source_context() {
- if (source_context_ != NULL) delete source_context_;
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
inline const ::google::protobuf::SourceContext& Api::source_context() const {
@@ -690,6 +690,8 @@ Method::mutable_options() {
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index f7059d26..96009645 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -29,7 +29,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/arena.h>
-#include <google/protobuf/stubs/common.h>
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
@@ -155,10 +154,16 @@ void Arena::AddListNode(void* elem, void (*cleanup)(void*)) {
reinterpret_cast<google::protobuf::internal::AtomicWord>(node)));
}
-void* Arena::AllocateAligned(size_t n) {
+void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) {
// Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
n = (n + 7) & -8;
+ // Monitor allocation if needed.
+ if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL) &&
+ options_.on_arena_allocation != NULL) {
+ options_.on_arena_allocation(allocated, n, hooks_cookie_);
+ }
+
// 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.
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index b48bef92..4adcd677 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -28,12 +28,12 @@
// (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__
+#if __cplusplus >= 201103L
+#include <google/protobuf/stubs/type_traits.h>
+#endif
#include <typeinfo>
#include <google/protobuf/stubs/atomic_sequence_num.h>
@@ -113,10 +113,13 @@ struct ArenaOptions {
void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used);
void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used);
- // type_name is promised to be a static string - its lifetime extends to
- // match program's lifetime.
- void (*on_arena_allocation)(const char* type_name, uint64 alloc_size,
- Arena* arena, void* cookie);
+ // type_info is promised to be static - its lifetime extends to
+ // match program's lifetime (It is given by typeid operator).
+ // Note: typeid(void) will be passed as allocated_type every time we
+ // intentionally want to avoid monitoring an allocation. (i.e. internal
+ // allocations for managing the arena)
+ void (*on_arena_allocation)(const std::type_info* allocated_type,
+ uint64 alloc_size, void* cookie);
ArenaOptions()
: start_block_size(kDefaultStartBlockSize),
@@ -137,6 +140,14 @@ struct ArenaOptions {
static const size_t kDefaultMaxBlockSize = 8192;
};
+// Support for non-RTTI environments. (The metrics hooks API uses type
+// information.)
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
+#define RTTI_TYPE_ID(type) (&typeid(type))
+#else
+#define RTTI_TYPE_ID(type) (NULL)
+#endif
+
// 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
@@ -146,6 +157,44 @@ struct ArenaOptions {
// 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.
+//
+// An arena provides two allocation interfaces: CreateMessage<T>, which works
+// for arena-enabled proto2 message types as well as other types that satisfy
+// the appropriate protocol (described below), and Create<T>, which works for
+// any arbitrary type T. CreateMessage<T> is better when the type T supports it,
+// because this interface (i) passes the arena pointer to the created object so
+// that its sub-objects and internal allocations can use the arena too, and (ii)
+// elides the object's destructor call when possible. Create<T> does not place
+// any special requirements on the type T, and will invoke the object's
+// destructor when the arena is destroyed.
+//
+// The arena message allocation protocol, required by CreateMessage<T>, is as
+// follows:
+//
+// - The type T must have (at least) two constructors: a constructor with no
+// arguments, called when a T is allocated on the heap; and a constructor with
+// a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the
+// second constructor is called with a NULL arena pointer, it must be
+// equivalent to invoking the first (no-argument) constructor.
+//
+// - The type T must have a particular type trait: a nested type
+// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no
+// such type trait exists, then the instantiation CreateMessage<T> will fail
+// to compile.
+//
+// - The type T *may* have the type trait |DestructorSkippable_|. If this type
+// trait is present in the type, then its destructor will not be called if and
+// only if it was passed a non-NULL arena pointer. If this type trait is not
+// present on the type, then its destructor is always called when the
+// containing arena is destroyed.
+//
+// - One- and two-user-argument forms of CreateMessage<T>() also exist that
+// forward these constructor arguments to T's constructor: for example,
+// CreateMessage<T>(Arena*, arg1, arg2) forwards to a constructor T(Arena*,
+// arg1, arg2).
+//
+// This protocol is implemented by all arena-enabled proto2 message classes as
+// well as RepeatedPtrField.
class LIBPROTOBUF_EXPORT Arena {
public:
// Arena constructor taking custom options. See ArenaOptions below for
@@ -172,8 +221,10 @@ class LIBPROTOBUF_EXPORT Arena {
// 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.
+ // arena with this method.
+ //
+ // This function also accepts any type T that satisfies the arena message
+ // allocation protocol, documented above.
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
static T* CreateMessage(::google::protobuf::Arena* arena) {
if (arena == NULL) {
@@ -183,17 +234,55 @@ class LIBPROTOBUF_EXPORT Arena {
}
}
+ // One-argument form of CreateMessage. This is useful for constructing objects
+ // that implement the arena message construction protocol described above but
+ // take additional constructor arguments.
+ template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
+ if (arena == NULL) {
+ return new T(NULL, arg);
+ } else {
+ return arena->CreateMessageInternal<T>(static_cast<T*>(0),
+ arg);
+ }
+ }
+
+ // Two-argument form of CreateMessage. This is useful for constructing objects
+ // that implement the arena message construction protocol described above but
+ // take additional constructor arguments.
+ template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static T* CreateMessage(::google::protobuf::Arena* arena,
+ const Arg1& arg1,
+ const Arg2& arg2) {
+ if (arena == NULL) {
+ return new T(NULL, arg1, arg2);
+ } else {
+ return arena->CreateMessageInternal<T>(static_cast<T*>(0),
+ arg1, arg2);
+ }
+ }
+
// 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.
+ //
+ // Note that even if T satisfies the arena message construction protocol
+ // (InternalArenaConstructable_ trait and optional DestructorSkippable_
+ // trait), as described above, this function does not follow the protocol;
+ // instead, it treats T as a black-box type, just as if it did not have these
+ // traits. Specifically, T's constructor arguments will always be only those
+ // passed to Create<T>() -- no additional arena pointer is implicitly added.
+ // Furthermore, the destructor will always be called at arena destruction time
+ // (unless the destructor is trivial). Hence, from T's point of view, it is as
+ // if the object were allocated on the heap (except that the underlying memory
+ // is obtained from the arena).
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)));
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value);
}
}
@@ -203,7 +292,7 @@ class LIBPROTOBUF_EXPORT Arena {
if (arena == NULL) {
return new T(arg);
} else {
- return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
arg);
}
}
@@ -214,9 +303,8 @@ class LIBPROTOBUF_EXPORT Arena {
if (arena == NULL) {
return new T(arg1, arg2);
} else {
- return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
- arg1,
- arg2);
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2);
}
}
@@ -229,10 +317,8 @@ class LIBPROTOBUF_EXPORT Arena {
if (arena == NULL) {
return new T(arg1, arg2, arg3);
} else {
- return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
- arg1,
- arg2,
- arg3);
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3);
}
}
@@ -246,20 +332,95 @@ class LIBPROTOBUF_EXPORT Arena {
if (arena == NULL) {
return new T(arg1, arg2, arg3, arg4);
} else {
- return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
- arg1,
- arg2,
- arg3,
- arg4);
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4);
}
}
- // 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.
+ // Version of the above with five constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5);
+ }
+ }
+
+ // Version of the above with six constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5, arg6);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5, arg6);
+ }
+ }
+
+ // Version of the above with seven constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6,
+ const Arg7& arg7) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ } else {
+ return arena->CreateInternal<T>(google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ }
+ }
+
+ // Version of the above with eight constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7,
+ typename Arg8>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4,
+ const Arg5& arg5, const Arg6& arg6,
+ const Arg7& arg7, const Arg8& arg8) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ } else {
+ return arena->CreateInternal<T>(
+ google::protobuf::internal::has_trivial_destructor<T>::value,
+ arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ }
+ }
+
+ // Create an array of object type T on the arena *without* invoking the
+ // constructor of T. If `arena` is null, then the return value should be freed
+ // with `delete[] x;` (or `::operator delete[](x);`).
+ // To ensure safe uses, this function checks at compile time
+ // (when compiled as C++11) that T is trivially default-constructible and
+ // trivially destructible.
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
+#if __cplusplus >= 201103L
+ static_assert(std::is_trivially_default_constructible<T>::value,
+ "CreateArray requires a trivially constructible type");
+ static_assert(std::is_trivially_destructible<T>::value,
+ "CreateArray requires a trivially destructible type");
+#endif
if (arena == NULL) {
- return new T[num_elements];
+ return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
} else {
return arena->CreateInternalRawArray<T>(num_elements);
}
@@ -374,27 +535,26 @@ class LIBPROTOBUF_EXPORT Arena {
// wrap them in static functions.
static ThreadCache& thread_cache();
#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
- // Android ndk does not support __thread keyword so we use a custom thread
+ // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
// local storage class we implemented.
- // iOS also does not support the __thread keyword.
+ // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
#endif
- // 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>.
- //
+ // SFINAE for skipping addition to delete list for a message type when created
+ // with CreateMessage. 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.
+ // For message objects that don't have the DestructorSkippable_ trait, we
+ // always add to the delete list.
template<typename T>
static inline bool SkipDeleteList(...) {
return google::protobuf::internal::has_trivial_destructor<T>::value;
@@ -419,14 +579,15 @@ class LIBPROTOBUF_EXPORT Arena {
// Just allocate the required size for the given type assuming the
// type has a trivial constructor.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternalRawArray(uint32 num_elements) {
- return static_cast<T*>(AllocateAligned(sizeof(T) * num_elements));
+ inline T* CreateInternalRawArray(size_t num_elements) {
+ return static_cast<T*>(
+ AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
}
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
inline T* CreateInternal(
bool skip_explicit_ownership) {
- T* t = new (AllocateAligned(sizeof(T))) T();
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -436,7 +597,7 @@ class LIBPROTOBUF_EXPORT Arena {
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);
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -446,7 +607,7 @@ class LIBPROTOBUF_EXPORT Arena {
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);
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -458,7 +619,8 @@ class LIBPROTOBUF_EXPORT Arena {
const Arg1& arg1,
const Arg2& arg2,
const Arg3& arg3) {
- T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3);
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -472,7 +634,79 @@ class LIBPROTOBUF_EXPORT Arena {
const Arg2& arg2,
const Arg3& arg3,
const Arg4& arg4) {
- T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3, arg4);
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5, arg6);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5, typename Arg6, typename Arg7,
+ typename Arg8>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7,
+ const Arg8& arg8) {
+ T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+ T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
}
@@ -485,6 +719,20 @@ class LIBPROTOBUF_EXPORT Arena {
this);
}
+ template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg& arg) {
+ return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+ this, arg);
+ }
+
+ template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg1& arg1, const Arg2& arg2) {
+ return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
+ this, arg1, arg2);
+ }
+
// CreateInArenaStorage is used to implement map field. Without it,
// google::protobuf::Map need to call generated message's protected arena constructor,
// which needs to declare google::protobuf::Map as friend of generated message.
@@ -536,8 +784,15 @@ class LIBPROTOBUF_EXPORT Arena {
return NULL;
}
+ // Allocate and also optionally call on_arena_allocation callback with the
+ // allocated type info when the hooks are in place in ArenaOptions and
+ // the cookie is not null.
+ void* AllocateAligned(const std::type_info* allocated, size_t n);
- void* AllocateAligned(size_t size);
+ // Allocate an internal allocation, avoiding optional typed monitoring.
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline void* AllocateAligned(size_t n) {
+ return AllocateAligned(NULL, n);
+ }
void Init();
@@ -596,6 +851,9 @@ class LIBPROTOBUF_EXPORT Arena {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
};
+// Defined above for supporting environments without RTTI.
+#undef RTTI_TYPE_ID
+
template<typename T>
const typename Arena::is_arena_constructable<T>::type
Arena::is_arena_constructable<T>::value =
diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
index f390df36..87a69b2a 100644
--- a/src/google/protobuf/arena_nc_test.py
+++ b/src/google/protobuf/arena_nc_test.py
@@ -35,6 +35,7 @@
import unittest
from google3.testing.pybase import fake_target_util
+import unittest
class ArenaNcTest(unittest.TestCase):
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
index 7db7a90e..690cc706 100644
--- a/src/google/protobuf/arena_test_util.h
+++ b/src/google/protobuf/arena_test_util.h
@@ -31,6 +31,7 @@
#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
+
namespace google {
namespace protobuf {
namespace internal {
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index d9b198e0..873e85ae 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
#include <string>
+#include <typeinfo>
#include <vector>
#include <google/protobuf/stubs/common.h>
@@ -47,11 +48,14 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_arena.pb.h>
#include <google/protobuf/unittest_no_arena.pb.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/message.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/unknown_field_set.h>
#include <gtest/gtest.h>
@@ -125,6 +129,29 @@ class MustBeConstructedWithOneThroughFour {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour);
};
+// A class that takes eight different types as constructor arguments.
+class MustBeConstructedWithOneThroughEight {
+ public:
+ MustBeConstructedWithOneThroughEight(
+ int one, const char* two, const string& three,
+ const PleaseDontCopyMe* four, int five, const char* six,
+ const string& seven, const string& eight)
+ : one_(one), two_(two), three_(three), four_(four), five_(five),
+ six_(six), seven_(seven), eight_(eight) {}
+
+ int one_;
+ const char* const two_;
+ string three_;
+ const PleaseDontCopyMe* four_;
+ int five_;
+ const char* const six_;
+ string seven_;
+ string eight_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight);
+};
+
} // namespace
TEST(ArenaTest, ArenaConstructable) {
@@ -156,7 +183,7 @@ TEST(ArenaTest, BasicCreate) {
EXPECT_EQ(2, notifier.GetCount());
}
-TEST(ArenaTest, CreateWithManyConstructorArguments) {
+TEST(ArenaTest, CreateWithFourConstructorArguments) {
Arena arena;
const string three("3");
const PleaseDontCopyMe four(4);
@@ -170,6 +197,26 @@ TEST(ArenaTest, CreateWithManyConstructorArguments) {
ASSERT_EQ(4, new_object->four_->value());
}
+TEST(ArenaTest, CreateWithEightConstructorArguments) {
+ Arena arena;
+ const string three("3");
+ const PleaseDontCopyMe four(4);
+ const string seven("7");
+ const string eight("8");
+ const MustBeConstructedWithOneThroughEight* new_object =
+ Arena::Create<MustBeConstructedWithOneThroughEight>(
+ &arena, 1, "2", three, &four, 5, "6", seven, eight);
+ EXPECT_TRUE(new_object != NULL);
+ ASSERT_EQ(1, new_object->one_);
+ ASSERT_STREQ("2", new_object->two_);
+ ASSERT_EQ("3", new_object->three_);
+ ASSERT_EQ(4, new_object->four_->value());
+ ASSERT_EQ(5, new_object->five_);
+ ASSERT_STREQ("6", new_object->six_);
+ ASSERT_EQ("7", new_object->seven_);
+ ASSERT_EQ("8", new_object->eight_);
+}
+
TEST(ArenaTest, InitialBlockTooSmall) {
// Construct a small (64 byte) initial block of memory to be used by the
// arena allocator; then, allocate an object which will not fit in the
@@ -1113,6 +1160,19 @@ TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
}
+TEST(ArenaTest, UnsafeSetAllocatedOnArena) {
+ ::google::protobuf::Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ EXPECT_FALSE(message->has_optional_string());
+
+ string owned_string = "test with long enough content to heap-allocate";
+ message->unsafe_arena_set_allocated_optional_string(&owned_string);
+ EXPECT_TRUE(message->has_optional_string());
+
+ message->unsafe_arena_set_allocated_optional_string(NULL);
+ EXPECT_FALSE(message->has_optional_string());
+}
+
// A helper utility class to only contain static hook functions, some
// counters to be used to verify the counters have been called and a cookie
// value to be verified.
@@ -1124,6 +1184,13 @@ class ArenaHooksTestUtil {
return static_cast<void*>(cookie);
}
+ static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size,
+ void* cookie) {
+ ++num_allocations;
+ int cookie_value = *static_cast<int*>(cookie);
+ EXPECT_EQ(kCookieValue, cookie_value);
+ }
+
static void on_reset(::google::protobuf::Arena* arena, void* cookie,
uint64 space_used) {
++num_reset;
@@ -1141,10 +1208,12 @@ class ArenaHooksTestUtil {
static const int kCookieValue = 999;
static uint32 num_init;
+ static uint32 num_allocations;
static uint32 num_reset;
static uint32 num_destruct;
};
uint32 ArenaHooksTestUtil::num_init = 0;
+uint32 ArenaHooksTestUtil::num_allocations = 0;
uint32 ArenaHooksTestUtil::num_reset = 0;
uint32 ArenaHooksTestUtil::num_destruct = 0;
const int ArenaHooksTestUtil::kCookieValue;
@@ -1153,6 +1222,7 @@ const int ArenaHooksTestUtil::kCookieValue;
TEST(ArenaTest, ArenaHooksSanity) {
::google::protobuf::ArenaOptions options;
options.on_arena_init = ArenaHooksTestUtil::on_init;
+ options.on_arena_allocation = ArenaHooksTestUtil::on_allocation;
options.on_arena_reset = ArenaHooksTestUtil::on_reset;
options.on_arena_destruction = ArenaHooksTestUtil::on_destruction;
@@ -1160,6 +1230,9 @@ TEST(ArenaTest, ArenaHooksSanity) {
{
::google::protobuf::Arena arena(options);
EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
+ EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
+ ::google::protobuf::Arena::Create<uint64>(&arena);
+ EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
arena.Reset();
arena.Reset();
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index 321a8ccd..b989f151 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -79,6 +79,37 @@ class LIBPROTOC_EXPORT CodeGenerator {
GeneratorContext* generator_context,
string* error) const = 0;
+ // Generates code for all given proto files, generating one or more files in
+ // the given output directory.
+ //
+ // This method should be called instead of |Generate()| when
+ // |HasGenerateAll()| returns |true|. It is used to emulate legacy semantics
+ // when more than one `.proto` file is specified on one compiler invocation.
+ //
+ // WARNING: Please do not use unless legacy semantics force the code generator
+ // to produce a single output file for all input files, or otherwise require
+ // an examination of all input files first. The canonical code generator
+ // design produces one output file per input .proto file, and we do not wish
+ // to encourage alternate designs.
+ //
+ // A parameter is given as passed on the command line, as in |Generate()|
+ // above.
+ //
+ // Returns true if successful. Otherwise, sets *error to a description of
+ // the problem (e.g. "invalid parameter") and returns false.
+ virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
+ const string& parameter,
+ GeneratorContext* generator_context,
+ string* error) const {
+ *error = "Unimplemented GenerateAll() method.";
+ return false;
+ }
+
+ // Returns true if the code generator expects to receive all FileDescriptors
+ // at once (via |GenerateAll()|), rather than one at a time (via
+ // |Generate()|). This is required to implement legacy semantics.
+ virtual bool HasGenerateAll() const { return false; }
+
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
};
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 567238ae..291fb054 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -898,12 +898,14 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
return PARSE_ARGUMENT_FAIL;
}
if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) {
- cerr << "Can only use --dependency_out=FILE when generating code." << endl;
+ std::cerr << "Can only use --dependency_out=FILE when generating code."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (!dependency_out_name_.empty() && input_files_.size() > 1) {
- cerr << "Can only process one input file when using --dependency_out=FILE."
- << endl;
+ std::cerr
+ << "Can only process one input file when using --dependency_out=FILE."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
@@ -1054,11 +1056,11 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--dependency_out") {
if (!dependency_out_name_.empty()) {
- cerr << name << " may only be passed once." << endl;
+ std::cerr << name << " may only be passed once." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (value.empty()) {
- cerr << name << " requires a non-empty value." << endl;
+ std::cerr << name << " requires a non-empty value." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
dependency_out_name_ = value;
@@ -1272,7 +1274,8 @@ void CommandLineInterface::PrintHelpText() {
" defined in the given proto files. Groups share\n"
" the same field number space with the parent \n"
" message. Extension ranges are counted as \n"
-" occupied fields numbers." << std::endl;
+" occupied fields numbers."
+ << std::endl;
if (!plugin_prefix_.empty()) {
std::cerr <<
" --plugin=EXECUTABLE Specifies a plugin executable to use.\n"
@@ -1327,13 +1330,23 @@ bool CommandLineInterface::GenerateOutput(
}
parameters.append(generator_parameters_[output_directive.name]);
}
- for (int i = 0; i < parsed_files.size(); i++) {
- if (!output_directive.generator->Generate(parsed_files[i], parameters,
- generator_context, &error)) {
- // Generator returned an error.
- std::cerr << output_directive.name << ": " << parsed_files[i]->name()
- << ": " << error << std::endl;
- return false;
+ if (output_directive.generator->HasGenerateAll()) {
+ if (!output_directive.generator->GenerateAll(
+ parsed_files, parameters, generator_context, &error)) {
+ // Generator returned an error.
+ std::cerr << output_directive.name << ": "
+ << ": " << error << std::endl;
+ return false;
+ }
+ } else {
+ for (int i = 0; i < parsed_files.size(); i++) {
+ if (!output_directive.generator->Generate(parsed_files[i], parameters,
+ generator_context, &error)) {
+ // Generator returned an error.
+ std::cerr << output_directive.name << ": " << parsed_files[i]->name()
+ << ": " << error << std::endl;
+ return false;
+ }
}
}
}
@@ -1403,7 +1416,8 @@ bool CommandLineInterface::GenerateDependencyManifestFile(
printer.Print(" $disk_file$", "disk_file", disk_file);
if (i < file_set.file_size() - 1) printer.Print("\\\n");
} else {
- cerr << "Unable to identify path for file " << virtual_file << endl;
+ std::cerr << "Unable to identify path for file " << virtual_file
+ << std::endl;
return false;
}
}
@@ -1673,6 +1687,10 @@ void GatherOccupiedFieldRanges(const Descriptor* descriptor,
ranges->insert(FieldRange(descriptor->extension_range(i)->start,
descriptor->extension_range(i)->end));
}
+ for (int i = 0; i < descriptor->reserved_range_count(); ++i) {
+ ranges->insert(FieldRange(descriptor->reserved_range(i)->start,
+ descriptor->reserved_range(i)->end));
+ }
// Handle the nested messages/groups in declaration order to make it
// post-order strict.
for (int i = 0; i < descriptor->nested_type_count(); ++i) {
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index e284c791..23d67e2b 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -115,10 +115,15 @@ class CommandLineInterfaceTest : public testing::Test {
// Create a subdirectory within temp_directory_.
void CreateTempDir(const string& name);
+#ifdef PROTOBUF_OPENSOURCE
// Change working directory to temp directory.
void SwitchToTempDirectory() {
File::ChangeWorkingDirectory(temp_directory_);
}
+#else // !PROTOBUF_OPENSOURCE
+ // TODO(teboring): Figure out how to change and get working directory in
+ // google3.
+#endif // !PROTOBUF_OPENSOURCE
void SetInputsAreProtoPathRelative(bool enable) {
cli_.SetInputsAreProtoPathRelative(enable);
@@ -986,6 +991,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) {
"Can only process one input file when using --dependency_out=FILE.\n");
}
+#ifdef PROTOBUF_OPENSOURCE
TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
@@ -1011,6 +1017,10 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) {
File::ChangeWorkingDirectory(current_working_directory);
}
+#else // !PROTOBUF_OPENSOURCE
+// TODO(teboring): Figure out how to change and get working directory in
+// google3.
+#endif // !PROTOBUF_OPENSOURCE
TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) {
CreateTempFile("foo.proto",
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 3eb20ab1..70d3a600 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -70,12 +70,23 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
EnumGenerator::~EnumGenerator() {}
+void EnumGenerator::GenerateForwardDeclaration(io::Printer* printer) {
+ if (!options_.proto_h) {
+ return;
+ }
+ map<string, string> vars;
+ vars["classname"] = classname_;
+ printer->Print(vars, "enum $classname$ : int;\n");
+ printer->Print(vars, "bool $classname$_IsValid(int value);\n");
+}
+
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
map<string, string> vars;
vars["classname"] = classname_;
vars["short_name"] = descriptor_->name();
+ vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
- printer->Print(vars, "enum $classname$ {\n");
+ printer->Print(vars, "enum $enumbase$ {\n");
printer->Indent();
const EnumValueDescriptor* min_value = descriptor_->value(0);
@@ -90,7 +101,6 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
vars["prefix"] = (descriptor_->containing_type() == NULL) ?
"" : classname_ + "_";
-
if (i > 0) printer->Print(",\n");
printer->Print(vars, "$prefix$$name$ = $number$");
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index 1ebd7cf7..3e930856 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -60,6 +60,12 @@ class EnumGenerator {
// Header stuff.
+ // Generate header code to forward-declare the enum. This is for use when
+ // generating other .proto.h files. This code should be placed within the
+ // enum's package namespace, but NOT within any class, even for nested
+ // enums.
+ void GenerateForwardDeclaration(io::Printer* printer);
+
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
// nested enums.
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 74989703..965327b1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -242,7 +242,7 @@ void RepeatedEnumFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField<int> $name$_;\n");
- if (descriptor_->options().packed()
+ if (descriptor_->is_packed()
&& HasGeneratedMethods(descriptor_->file())) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
@@ -352,7 +352,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
- if (!descriptor_->options().packed()) {
+ if (!descriptor_->is_packed()) {
// This path is rarely executed, so we use a non-inlined implementation.
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables_,
@@ -419,7 +419,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -432,7 +432,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n"
" this->$name$(i), output);\n");
@@ -446,7 +446,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -460,7 +460,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
" this->$name$(i), target);\n");
@@ -484,7 +484,7 @@ GenerateByteSize(io::Printer* printer) const {
" this->$name$(i));\n"
"}\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index cd2b6b75..1d7f8233 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -82,12 +82,38 @@ class FieldGenerator {
// implementation is empty.
virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {}
+ // Generate prototypes for accessors that will manipulate imported
+ // messages inline. These are for .proto.h headers.
+ //
+ // In .proto.h mode, the headers of imports are not #included. However,
+ // functions that manipulate the imported message types need access to
+ // the class definition of the imported message, meaning that the headers
+ // must be #included. To get around this, functions that manipulate
+ // imported message objects are defined as dependent functions in a base
+ // template class. By making them dependent template functions, the
+ // function templates will not be instantiated until they are called, so
+ // we can defer to those translation units to #include the necessary
+ // generated headers.
+ //
+ // See:
+ // http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation
+ //
+ // Most field types don't need this, so the default implementation is empty.
+ virtual void GenerateDependentAccessorDeclarations(
+ io::Printer* printer) const {}
+
// Generate prototypes for all of the accessor functions related to this
// field. These are placed inside the class definition.
virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0;
+ // Generate inline definitions of depenent accessor functions for this field.
+ // These are placed inside the header after all class definitions.
+ virtual void GenerateDependentInlineAccessorDefinitions(
+ io::Printer* printer) const {}
+
// Generate inline definitions of accessor functions for this field.
// These are placed inside the header after all class definitions.
+ // In non-.proto.h mode, this generates dependent accessor functions as well.
virtual void GenerateInlineAccessorDefinitions(
io::Printer* printer, bool is_inline) const = 0;
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index a98c7d92..b997a51a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -94,113 +94,10 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
FileGenerator::~FileGenerator() {}
void FileGenerator::GenerateHeader(io::Printer* printer) {
- string filename_identifier = FilenameIdentifier(file_->name());
-
- // Generate top of header.
- printer->Print(
- "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "// source: $filename$\n"
- "\n"
- "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
- "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
- "\n"
- "#include <string>\n"
- "\n",
- "filename", file_->name(),
- "filename_identifier", filename_identifier);
-
-
- printer->Print(
- "#include <google/protobuf/stubs/common.h>\n"
- "\n");
-
- // Verify the protobuf library header version is compatible with the protoc
- // version before going any further.
- printer->Print(
- "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
- "#error This file was generated by a newer version of protoc which is\n"
- "#error incompatible with your Protocol Buffer headers. Please update\n"
- "#error your headers.\n"
- "#endif\n"
- "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
- "#error This file was generated by an older version of protoc which is\n"
- "#error incompatible with your Protocol Buffer headers. Please\n"
- "#error regenerate this file with a newer version of protoc.\n"
- "#endif\n"
- "\n",
- "min_header_version",
- SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
- "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
-
- // OK, it's now safe to #include other files.
- printer->Print(
- "#include <google/protobuf/arena.h>\n"
- "#include <google/protobuf/arenastring.h>\n"
- "#include <google/protobuf/generated_message_util.h>\n");
- if (UseUnknownFieldSet(file_)) {
- printer->Print(
- "#include <google/protobuf/metadata.h>\n");
- }
- if (file_->message_type_count() > 0) {
- if (HasDescriptorMethods(file_)) {
- printer->Print(
- "#include <google/protobuf/message.h>\n");
- } else {
- printer->Print(
- "#include <google/protobuf/message_lite.h>\n");
- }
- }
- printer->Print(
- "#include <google/protobuf/repeated_field.h>\n"
- "#include <google/protobuf/extension_set.h>\n");
- if (HasMapFields(file_)) {
- printer->Print(
- "#include <google/protobuf/map.h>\n");
- if (HasDescriptorMethods(file_)) {
- printer->Print(
- "#include <google/protobuf/map_field_inl.h>\n");
- } else {
- printer->Print(
- "#include <google/protobuf/map_field_lite.h>\n");
- }
- }
-
- if (HasEnumDefinitions(file_)) {
- if (HasDescriptorMethods(file_)) {
- printer->Print(
- "#include <google/protobuf/generated_enum_reflection.h>\n");
- } else {
- printer->Print(
- "#include <google/protobuf/generated_enum_util.h>\n");
- }
- }
-
- if (HasGenericServices(file_)) {
- printer->Print(
- "#include <google/protobuf/service.h>\n");
- }
-
- if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
- printer->Print(
- "#include <google/protobuf/unknown_field_set.h>\n");
- }
-
-
- set<string> public_import_names;
- for (int i = 0; i < file_->public_dependency_count(); i++) {
- public_import_names.insert(file_->public_dependency(i)->name());
- }
-
- for (int i = 0; i < file_->dependency_count(); i++) {
- const string& name = file_->dependency(i)->name();
- bool public_import = (public_import_names.count(name) != 0);
+ GenerateTopHeaderGuard(printer);
-
- printer->Print(
- "#include \"$dependency$.pb.h\"$iwyu$\n",
- "dependency", StripProto(name),
- "iwyu", (public_import) ? " // IWYU pragma: export" : "");
- }
+ GenerateLibraryIncludes(printer);
+ GenerateDependencyIncludes(printer);
printer->Print(
"// @@protoc_insertion_point(includes)\n");
@@ -210,132 +107,44 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// Open namespace.
GenerateNamespaceOpeners(printer);
- // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
- // functions, so that we can declare them to be friends of each class.
- printer->Print(
- "\n"
- "// Internal implementation detail -- do not call these.\n"
- "void $dllexport_decl$$adddescriptorsname$();\n",
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "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
- // called by the .pb.cc file in which they are defined.
- "void $assigndescriptorsname$();\n"
- "void $shutdownfilename$();\n"
- "\n",
- "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
- "shutdownfilename", GlobalShutdownFileName(file_->name()));
-
- // Generate forward declarations of classes.
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateForwardDeclaration(printer);
- }
+ GenerateGlobalStateFunctionDeclarations(printer);
+ GenerateMessageForwardDeclarations(printer);
printer->Print("\n");
- // Generate enum definitions.
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateEnumDefinitions(printer);
- }
- for (int i = 0; i < file_->enum_type_count(); i++) {
- enum_generators_[i]->GenerateDefinition(printer);
- }
+ GenerateEnumDefinitions(printer);
printer->Print(kThickSeparator);
printer->Print("\n");
- // Generate class definitions.
- for (int i = 0; i < file_->message_type_count(); i++) {
- if (i > 0) {
- printer->Print("\n");
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- message_generators_[i]->GenerateClassDefinition(printer);
- }
+ GenerateMessageDefinitions(printer);
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
- if (HasGenericServices(file_)) {
- // Generate service definitions.
- for (int i = 0; i < file_->service_count(); i++) {
- if (i > 0) {
- printer->Print("\n");
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- service_generators_[i]->GenerateDeclarations(printer);
- }
-
- printer->Print("\n");
- printer->Print(kThickSeparator);
- printer->Print("\n");
- }
+ GenerateServiceDefinitions(printer);
- // Declare extension identifiers.
- for (int i = 0; i < file_->extension_count(); i++) {
- extension_generators_[i]->GenerateDeclaration(printer);
- }
+ GenerateExtensionIdentifiers(printer);
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
- printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
- // Generate class inline methods.
- for (int i = 0; i < file_->message_type_count(); i++) {
- if (i > 0) {
- printer->Print(kThinSeparator);
- printer->Print("\n");
- }
- message_generators_[i]->GenerateInlineMethods(printer,
- /* is_inline = */ true);
- }
- printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
-
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
+ GenerateInlineFunctionDefinitions(printer);
// Close up namespace.
GenerateNamespaceClosers(printer);
- // Emit GetEnumDescriptor specializations into google::protobuf namespace:
- if (HasEnumDefinitions(file_)) {
- // The SWIG conditional is to avoid a null-pointer dereference
- // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
- // namespace X { void Y<Z::W>(); }
- // which appears in GetEnumDescriptor() specializations.
- printer->Print(
- "\n"
- "#ifndef SWIG\n"
- "namespace google {\nnamespace protobuf {\n"
- "\n");
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
- }
- for (int i = 0; i < file_->enum_type_count(); i++) {
- enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
- }
- printer->Print(
- "\n"
- "} // namespace protobuf\n} // namespace google\n"
- "#endif // SWIG\n");
- }
+ // We need to specialize some templates in the ::google::protobuf namespace:
+ GenerateProto2NamespaceEnumSpecializations(printer);
printer->Print(
"\n"
"// @@protoc_insertion_point(global_scope)\n"
"\n");
- printer->Print(
- "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
- "filename_identifier", filename_identifier);
+ GenerateBottomHeaderGuard(printer);
}
void FileGenerator::GenerateSource(io::Printer* printer) {
@@ -707,6 +516,294 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
}
}
+void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) {
+ string filename_identifier = FilenameIdentifier(file_->name());
+ // Generate top of header.
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n"
+ "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
+ "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
+ "\n"
+ "#include <string>\n"
+ "\n",
+ "filename", file_->name(),
+ "filename_identifier", filename_identifier);
+}
+
+void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer) {
+ string filename_identifier = FilenameIdentifier(file_->name());
+ printer->Print(
+ "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
+ "filename_identifier", filename_identifier);
+}
+
+void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
+
+ printer->Print(
+ "#include <google/protobuf/stubs/common.h>\n"
+ "\n");
+
+ // Verify the protobuf library header version is compatible with the protoc
+ // version before going any further.
+ printer->Print(
+ "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
+ "#error This file was generated by a newer version of protoc which is\n"
+ "#error incompatible with your Protocol Buffer headers. Please update\n"
+ "#error your headers.\n"
+ "#endif\n"
+ "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
+ "#error This file was generated by an older version of protoc which is\n"
+ "#error incompatible with your Protocol Buffer headers. Please\n"
+ "#error regenerate this file with a newer version of protoc.\n"
+ "#endif\n"
+ "\n",
+ "min_header_version",
+ SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
+ "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
+
+ // OK, it's now safe to #include other files.
+ printer->Print(
+ "#include <google/protobuf/arena.h>\n"
+ "#include <google/protobuf/arenastring.h>\n"
+ "#include <google/protobuf/generated_message_util.h>\n");
+ if (UseUnknownFieldSet(file_)) {
+ printer->Print(
+ "#include <google/protobuf/metadata.h>\n");
+ }
+ if (file_->message_type_count() > 0) {
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/message.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/message_lite.h>\n");
+ }
+ }
+ printer->Print(
+ "#include <google/protobuf/repeated_field.h>\n"
+ "#include <google/protobuf/extension_set.h>\n");
+ if (HasMapFields(file_)) {
+ printer->Print(
+ "#include <google/protobuf/map.h>\n");
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/map_field_inl.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/map_field_lite.h>\n");
+ }
+ }
+
+ if (HasEnumDefinitions(file_)) {
+ if (HasDescriptorMethods(file_)) {
+ printer->Print(
+ "#include <google/protobuf/generated_enum_reflection.h>\n");
+ } else {
+ printer->Print(
+ "#include <google/protobuf/generated_enum_util.h>\n");
+ }
+ }
+
+ if (HasGenericServices(file_)) {
+ printer->Print(
+ "#include <google/protobuf/service.h>\n");
+ }
+
+ if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+ printer->Print(
+ "#include <google/protobuf/unknown_field_set.h>\n");
+ }
+
+
+ if (IsAnyMessage(file_)) {
+ printer->Print(
+ "#include \"google/protobuf/any.h\"\n");
+ }
+}
+
+void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
+ set<string> public_import_names;
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ public_import_names.insert(file_->public_dependency(i)->name());
+ }
+
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ const string& name = file_->dependency(i)->name();
+ bool public_import = (public_import_names.count(name) != 0);
+
+
+ printer->Print(
+ "#include \"$dependency$.pb.h\"$iwyu$\n",
+ "dependency", StripProto(name),
+ "iwyu", (public_import) ? " // IWYU pragma: export" : "");
+ }
+}
+
+void FileGenerator::GenerateGlobalStateFunctionDeclarations(
+ io::Printer* printer) {
+ // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
+ // functions, so that we can declare them to be friends of each class.
+ printer->Print(
+ "\n"
+ "// Internal implementation detail -- do not call these.\n"
+ "void $dllexport_decl$$adddescriptorsname$();\n",
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
+ "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
+ // called by the .pb.cc file in which they are defined.
+ "void $assigndescriptorsname$();\n"
+ "void $shutdownfilename$();\n"
+ "\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
+ "shutdownfilename", GlobalShutdownFileName(file_->name()));
+}
+
+void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
+ // Generate forward declarations of classes.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ }
+}
+
+void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
+ // Generate class definitions.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (i > 0) {
+ printer->Print("\n");
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ message_generators_[i]->GenerateClassDefinition(printer);
+ }
+}
+
+void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
+ // Generate enum definitions.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateEnumDefinitions(printer);
+ }
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ enum_generators_[i]->GenerateDefinition(printer);
+ }
+}
+
+void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
+ if (HasGenericServices(file_)) {
+ // Generate service definitions.
+ for (int i = 0; i < file_->service_count(); i++) {
+ if (i > 0) {
+ printer->Print("\n");
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ service_generators_[i]->GenerateDeclarations(printer);
+ }
+
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+ }
+}
+
+void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
+ // Declare extension identifiers.
+ for (int i = 0; i < file_->extension_count(); i++) {
+ extension_generators_[i]->GenerateDeclaration(printer);
+ }
+}
+
+void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
+ // An aside about inline functions in .proto.h mode:
+ //
+ // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
+ // moving much of the inline functions to the .pb.cc file, which can be a
+ // significant performance benefit for compilation time, at the expense
+ // of non-inline function calls.
+ //
+ // However, in .proto.h mode, the definition of the internal dependent
+ // base class must remain in the header, and can never be out-lined. The
+ // dependent base class also needs access to has-bit manipuation
+ // functions, so the has-bit functions must be unconditionally inlined in
+ // proto_h mode.
+ //
+ // This gives us three flavors of functions:
+ //
+ // 1. Functions on the message not used by the internal dependent base
+ // class: in .proto.h mode, only some functions are defined on the
+ // message class; others are defined on the dependent base class.
+ // These are guarded and can be out-lined. These are generated by
+ // GenerateInlineMethods, and include has_* bit functions in
+ // non-proto_h mode.
+ //
+ // 2. Functions on the internal dependent base class: these functions
+ // are dependent on a template parameter, so they always need to
+ // remain in the header.
+ //
+ // 3. Functions on the message that are used by the dependent base: the
+ // dependent base class down casts itself to the message
+ // implementation class to access these functions (the has_* bit
+ // manipulation functions). Unlike #1, these functions must
+ // unconditionally remain in the header. These are emitted by
+ // GenerateDependentInlineMethods, even though they are not actually
+ // dependent.
+
+ printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+ // Generate class inline methods.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (i > 0) {
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ message_generators_[i]->GenerateInlineMethods(printer,
+ /* is_inline = */ true);
+ }
+ printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ if (i > 0) {
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+ // Methods of the dependent base class must always be inline in the header.
+ message_generators_[i]->GenerateDependentInlineMethods(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+}
+
+void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
+ io::Printer* printer) {
+ // Emit GetEnumDescriptor specializations into google::protobuf namespace:
+ if (HasEnumDefinitions(file_)) {
+ // The SWIG conditional is to avoid a null-pointer dereference
+ // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
+ // namespace X { void Y<Z::W>(); }
+ // which appears in GetEnumDescriptor() specializations.
+ printer->Print(
+ "\n"
+ "#ifndef SWIG\n"
+ "namespace google {\nnamespace protobuf {\n"
+ "\n");
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+ }
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
+ }
+ printer->Print(
+ "\n"
+ "} // namespace protobuf\n} // namespace google\n"
+ "#endif // SWIG\n");
+ }
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 0e06547d..e68f67bb 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -80,6 +80,35 @@ class FileGenerator {
void GenerateNamespaceOpeners(io::Printer* printer);
void GenerateNamespaceClosers(io::Printer* printer);
+ // Generates top or bottom of a header file.
+ void GenerateTopHeaderGuard(io::Printer* printer);
+ void GenerateBottomHeaderGuard(io::Printer* printer);
+
+ // Generates #include directives.
+ void GenerateLibraryIncludes(io::Printer* printer);
+ void GenerateDependencyIncludes(io::Printer* printer);
+
+ // Generates a couple of different pieces before definitions:
+ void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
+
+ // Generates types for classes.
+ void GenerateMessageForwardDeclarations(io::Printer* printer);
+ void GenerateMessageDefinitions(io::Printer* printer);
+
+ // Generates enum definitions.
+ void GenerateEnumDefinitions(io::Printer* printer);
+
+ // Generates generic service definitions.
+ void GenerateServiceDefinitions(io::Printer* printer);
+
+ // Generates extension identifiers.
+ void GenerateExtensionIdentifiers(io::Printer* printer);
+
+ // Generates inline function defintions.
+ void GenerateInlineFunctionDefinitions(io::Printer* printer);
+
+ void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
+
const FileDescriptor* file_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > message_generators_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index c999b93f..99416372 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -82,6 +82,7 @@ bool CppGenerator::Generate(const FileDescriptor* file,
// }
// FOO_EXPORT is a macro which should expand to __declspec(dllexport) or
// __declspec(dllimport) depending on what is being compiled.
+ //
Options file_options;
for (int i = 0; i < options.size(); i++) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 4e7155c3..0f3688d0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -51,6 +51,9 @@ namespace cpp {
namespace {
+static const char kAnyMessageName[] = "Any";
+static const char kAnyProtoFile[] = "google/protobuf/any.proto";
+
string DotsToUnderscores(const string& name) {
return StringReplace(name, ".", "_", true);
}
@@ -162,6 +165,10 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) {
}
+string DependentBaseClassTemplateName(const Descriptor* descriptor) {
+ return ClassName(descriptor, false) + "_InternalBase";
+}
+
string SuperClassName(const Descriptor* descriptor) {
return HasDescriptorMethods(descriptor->file()) ?
"::google::protobuf::Message" : "::google::protobuf::MessageLite";
@@ -200,6 +207,47 @@ string FieldConstantName(const FieldDescriptor *field) {
return result;
}
+bool IsFieldDependent(const FieldDescriptor* field) {
+ if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ return false;
+ }
+ if (field->containing_oneof() != NULL) {
+ // Oneof fields will always be dependent.
+ //
+ // This is a unique case for field codegen. Field generators are
+ // responsible for generating all the field-specific accessor
+ // functions, except for the clear_*() function; instead, field
+ // generators produce inline clearing code.
+ //
+ // For non-oneof fields, the Message class uses the inline clearing
+ // code to define the field's clear_*() function, as well as in the
+ // destructor. For oneof fields, the Message class generates a much
+ // more complicated clear_*() function, which clears only the oneof
+ // member that is set, in addition to clearing methods for each of the
+ // oneof members individually.
+ //
+ // Since oneofs do not have their own generator class, the Message code
+ // generation logic would be significantly complicated in order to
+ // split dependent and non-dependent manipulation logic based on
+ // whether the oneof truly needs to be dependent; so, for oneof fields,
+ // we just assume it (and its constituents) should be manipulated by a
+ // dependent base class function.
+ //
+ // This is less precise than how dependent message-typed fields are
+ // handled, but the cost is limited to only the generated code for the
+ // oneof field, which seems like an acceptable tradeoff.
+ return true;
+ }
+ if (field->file() == field->message_type()->file()) {
+ return false;
+ }
+ return true;
+}
+
+string DependentTypeName(const FieldDescriptor* field) {
+ return "InternalBase_" + field->name() + "_T";
+}
+
string FieldMessageTypeName(const FieldDescriptor* field) {
// Note: The Google-internal version of Protocol Buffers uses this function
// as a hook point for hacks to support legacy code.
@@ -360,7 +408,7 @@ string FilenameIdentifier(const string& filename) {
} else {
// Not alphanumeric. To avoid any possibility of name conflicts we
// use the hex code for the character.
- StrAppend(&result, "_", ToHex(static_cast<uint8>(filename[i])));
+ StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
}
}
return result;
@@ -521,6 +569,15 @@ FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
}
+bool IsAnyMessage(const FileDescriptor* descriptor) {
+ return descriptor->name() == kAnyProtoFile;
+}
+
+bool IsAnyMessage(const Descriptor* descriptor) {
+ return descriptor->name() == kAnyMessageName &&
+ descriptor->file()->name() == kAnyProtoFile;
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 284fa2c1..4bbf8303 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -66,6 +66,10 @@ extern const char kThinSeparator[];
string ClassName(const Descriptor* descriptor, bool qualified);
string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
+// Name of the CRTP class template (for use with proto_h).
+// This is a class name, like "ProtoName_InternalBase".
+string DependentBaseClassTemplateName(const Descriptor* descriptor);
+
string SuperClassName(const Descriptor* descriptor);
// Get the (unqualified) name that should be used for this field in C++ code.
@@ -88,6 +92,20 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) {
field->extension_scope() : field->containing_type();
}
+// Returns true if the given 'field_descriptor' has a message type that is
+// a dependency of the file where the field is defined (i.e., the field
+// type is defined in a different file than the message holding the field).
+//
+// This only applies to Message-typed fields. Enum-typed fields may refer
+// to an enum in a dependency; however, enums are specified and
+// forward-declared with an enum-base, so the definition is not required to
+// manipulate the field value.
+bool IsFieldDependent(const FieldDescriptor* field_descriptor);
+
+// Returns the name that should be used for forcing dependent lookup from a
+// dependent base class.
+string DependentTypeName(const FieldDescriptor* field);
+
// Returns the fully-qualified type name field->message_type(). Usually this
// is just ClassName(field->message_type(), true);
string FieldMessageTypeName(const FieldDescriptor* field);
@@ -242,6 +260,9 @@ inline bool SupportsArenas(const FieldDescriptor* field) {
return SupportsArenas(field->file());
}
+bool IsAnyMessage(const FileDescriptor* descriptor);
+bool IsAnyMessage(const Descriptor* descriptor);
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 8c38db2b..0ff0d27c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -244,7 +244,8 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = $name$().begin(); it != $name$().end(); ++it) {\n");
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it) {\n");
// If entry is allocated by arena, its desctructor should be avoided.
if (SupportsArenas(descriptor_)) {
@@ -277,7 +278,8 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = $name$().begin(); it != $name$().end(); ++it) {\n");
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it) {\n");
// If entry is allocated by arena, its desctructor should be avoided.
if (SupportsArenas(descriptor_)) {
@@ -312,7 +314,8 @@ GenerateByteSize(io::Printer* printer) const {
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
- " it = $name$().begin(); it != $name$().end(); ++it) {\n");
+ " it = this->$name$().begin();\n"
+ " it != this->$name$().end(); ++it) {\n");
// If entry is allocated by arena, its desctructor should be avoided.
if (SupportsArenas(descriptor_)) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 98929b1e..212fe2e1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -64,10 +64,15 @@ using internal::WireFormatLite;
namespace {
-void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
- // Print the field's proto-syntax definition as a comment. We don't want to
- // print group bodies so we cut off after the first line.
- string def = field->DebugString();
+template <class T>
+void PrintFieldComment(io::Printer* printer, const T* field) {
+ // Print the field's (or oneof's) proto-syntax definition as a comment.
+ // We don't want to print group bodies so we cut off after the first
+ // line.
+ DebugStringOptions options;
+ options.elide_group_body = true;
+ options.elide_oneof_body = true;
+ string def = field->DebugStringWithOptions(options);
printer->Print("// $def$\n",
"def", def.substr(0, def.find_first_of('\n')));
}
@@ -280,6 +285,10 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
}
}
+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
@@ -379,7 +388,8 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
enum_generators_(
new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]),
extension_generators_(new google::protobuf::scoped_ptr<
- ExtensionGenerator>[descriptor->extension_count()]) {
+ ExtensionGenerator>[descriptor->extension_count()]),
+ use_dependent_base_(false) {
for (int i = 0; i < descriptor->nested_type_count(); i++) {
nested_generators_[i].reset(
@@ -401,13 +411,16 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
if (descriptor->field(i)->is_required()) {
++num_required_fields_;
}
+ if (options.proto_h && IsFieldDependent(descriptor->field(i))) {
+ use_dependent_base_ = true;
+ }
}
}
MessageGenerator::~MessageGenerator() {}
void MessageGenerator::
-GenerateForwardDeclaration(io::Printer* printer) {
+GenerateMessageForwardDeclaration(io::Printer* printer) {
printer->Print("class $classname$;\n",
"classname", classname_);
@@ -416,7 +429,17 @@ GenerateForwardDeclaration(io::Printer* printer) {
// message cannot be a top level class, we just need to avoid calling
// GenerateForwardDeclaration here.
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
- nested_generators_[i]->GenerateForwardDeclaration(printer);
+ nested_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ }
+}
+
+void MessageGenerator::
+GenerateEnumForwardDeclaration(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ nested_generators_[i]->GenerateEnumForwardDeclaration(printer);
+ }
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ enum_generators_[i]->GenerateForwardDeclaration(printer);
}
}
@@ -442,6 +465,35 @@ GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
}
void MessageGenerator::
+GenerateDependentFieldAccessorDeclarations(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+
+ PrintFieldComment(printer, field);
+
+ map<string, string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ // If the message is dependent, the inline clear_*() method will need
+ // to delete the message type, so it must be in the dependent base
+ // class. (See also GenerateFieldAccessorDeclarations.)
+ printer->Print(vars, "void clear_$name$()$deprecation$;\n");
+ }
+ // Generate type-specific accessor declarations.
+ field_generators_.get(field).GenerateDependentAccessorDeclarations(printer);
+ printer->Print("\n");
+ }
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
+ PrintFieldComment(printer, oneof);
+ printer->Print(
+ "void clear_$oneof_name$();\n",
+ "oneof_name", oneof->name());
+ }
+}
+
+void MessageGenerator::
GenerateFieldAccessorDeclarations(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
@@ -452,6 +504,19 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
SetCommonFieldVariables(field, &vars, options_);
vars["constant_name"] = FieldConstantName(field);
+ bool dependent_field = use_dependent_base_ && IsFieldDependent(field);
+ if (dependent_field) {
+ // If this field is dependent, the dependent base class determines
+ // the message type from the derived class (which is a template
+ // parameter). This typedef is for that:
+ printer->Print(
+ "private:\n"
+ "typedef $field_type$ $dependent_type$;\n"
+ "public:\n",
+ "field_type", FieldMessageTypeName(field),
+ "dependent_type", DependentTypeName(field));
+ }
+
if (field->is_repeated()) {
printer->Print(vars, "int $name$_size() const$deprecation$;\n");
} else if (HasHasMethod(field)) {
@@ -463,7 +528,11 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
"public:\n");
}
- printer->Print(vars, "void clear_$name$()$deprecation$;\n");
+ if (!dependent_field) {
+ // If this field is dependent, then its clear_() method is in the
+ // depenent base class. (See also GenerateDependentAccessorDeclarations.)
+ printer->Print(vars, "void clear_$name$()$deprecation$;\n");
+ }
printer->Print(vars, "static const int $constant_name$ = $number$;\n");
// Generate type-specific accessor declarations.
@@ -490,6 +559,188 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
}
void MessageGenerator::
+GenerateDependentFieldAccessorDefinitions(io::Printer* printer) {
+ if (!use_dependent_base_) return;
+
+ printer->Print("// $classname$\n\n", "classname",
+ DependentBaseClassTemplateName(descriptor_));
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+
+ PrintFieldComment(printer, field);
+
+ // These functions are not really dependent: they are part of the
+ // (non-dependent) derived class. However, they need to live outside
+ // any #ifdef guards, so we treat them as if they were dependent.
+ //
+ // See the comment in FileGenerator::GenerateInlineFunctionDefinitions
+ // for a more complete explanation.
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ map<string, string> vars;
+ SetCommonFieldVariables(field, &vars, options_);
+ vars["inline"] = "inline ";
+ if (field->containing_oneof()) {
+ vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
+ vars["oneof_name"] = field->containing_oneof()->name();
+ vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
+ GenerateOneofMemberHasBits(field, vars, printer);
+ } else if (!field->is_repeated()) {
+ // There will be no header guard, so this always has to be inline.
+ GenerateSingularFieldHasBits(field, vars, printer);
+ }
+ // vars needed for clear_(), which is in the dependent base:
+ // (See also GenerateDependentFieldAccessorDeclarations.)
+ vars["tmpl"] = "template<class T>\n";
+ vars["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_) + "<T>";
+ vars["this_message"] = "reinterpret_cast<T*>(this)->";
+ vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ GenerateFieldClear(field, vars, printer);
+ }
+
+ // Generate type-specific accessors.
+ field_generators_.get(field)
+ .GenerateDependentInlineAccessorDefinitions(printer);
+
+ printer->Print("\n");
+ }
+
+ // Generate has_$name$() and clear_has_$name$() functions for oneofs
+ // Similar to other has-bits, these must always be in the header if we
+ // are using a dependent base class.
+ GenerateOneofHasBits(printer, true /* is_inline */);
+}
+
+void MessageGenerator::
+GenerateSingularFieldHasBits(const FieldDescriptor* field,
+ map<string, string> vars,
+ io::Printer* printer) {
+ if (HasFieldPresence(descriptor_->file())) {
+ // N.B.: without field presence, we do not use has-bits or generate
+ // has_$name$() methods.
+ vars["has_array_index"] = SimpleItoa(field->index() / 32);
+ vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32),
+ strings::Hex::ZERO_PAD_8));
+ 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 !_is_default_instance_ && $name$_ != NULL;\n"
+ "}\n");
+ }
+ }
+ }
+}
+
+void MessageGenerator::
+GenerateOneofHasBits(io::Printer* printer, bool is_inline) {
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ map<string, string> vars;
+ vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ vars["cap_oneof_name"] =
+ ToUpper(descriptor_->oneof_decl(i)->name());
+ vars["classname"] = classname_;
+ vars["inline"] = (is_inline ? "inline " : "");
+ printer->Print(
+ vars,
+ "$inline$"
+ "bool $classname$::has_$oneof_name$() const {\n"
+ " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
+ "}\n"
+ "$inline$"
+ "void $classname$::clear_has_$oneof_name$() {\n"
+ " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
+ "}\n");
+ }
+}
+
+void MessageGenerator::
+GenerateOneofMemberHasBits(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer) {
+ // 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).
+ printer->Print(vars,
+ "$inline$"
+ "bool $classname$::has_$name$() const {\n"
+ " return $oneof_name$_case() == k$field_name$;\n"
+ "}\n");
+ printer->Print(vars,
+ "$inline$"
+ "void $classname$::set_has_$name$() {\n"
+ " _oneof_case_[$oneof_index$] = k$field_name$;\n"
+ "}\n");
+}
+
+void MessageGenerator::
+GenerateFieldClear(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer) {
+ // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and
+ // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is
+ // set by the Generate*Definitions functions.)
+ printer->Print(vars,
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::clear_$name$() {\n");
+
+ printer->Indent();
+
+ if (field->containing_oneof()) {
+ // Clear this field only if it is the active field in this oneof,
+ // otherwise ignore
+ printer->Print(vars,
+ "if ($this_message$has_$name$()) {\n");
+ printer->Indent();
+ field_generators_.get(field).GenerateClearingCode(printer);
+ printer->Print(vars,
+ "$this_message$clear_has_$oneof_name$();\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ } else {
+ field_generators_.get(field).GenerateClearingCode(printer);
+ if (HasFieldPresence(descriptor_->file())) {
+ if (!field->is_repeated()) {
+ printer->Print(vars,
+ "$this_message$clear_has_$name$();\n");
+ }
+ }
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void MessageGenerator::
GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
printer->Print("// $classname$\n\n", "classname", classname_);
@@ -500,101 +751,37 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
map<string, string> vars;
SetCommonFieldVariables(field, &vars, options_);
- vars["inline"] = is_inline ? "inline" : "";
+ vars["inline"] = is_inline ? "inline " : "";
// Generate has_$name$() or $name$_size().
if (field->is_repeated()) {
printer->Print(vars,
- "$inline$ int $classname$::$name$_size() const {\n"
+ "$inline$"
+ "int $classname$::$name$_size() const {\n"
" return $name$_.size();\n"
"}\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");
- printer->Print(vars,
- "$inline$ void $classname$::set_has_$name$() {\n"
- " _oneof_case_[$oneof_index$] = k$field_name$;\n"
- "}\n");
+ if (!use_dependent_base_ || !IsFieldDependent(field)) {
+ GenerateOneofMemberHasBits(field, vars, printer);
+ }
} else {
// Singular field.
- 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 !_is_default_instance_ && $name$_ != NULL;\n"
- "}\n");
- }
- }
+ if (!use_dependent_base_ || !IsFieldDependent(field)) {
+ GenerateSingularFieldHasBits(field, vars, printer);
}
}
- // Generate clear_$name$()
- printer->Print(vars,
- "$inline$ void $classname$::clear_$name$() {\n");
-
- printer->Indent();
-
- if (field->containing_oneof()) {
- // Clear this field only if it is the active field in this oneof,
- // otherwise ignore
- printer->Print(vars,
- "if (has_$name$()) {\n");
- printer->Indent();
- field_generators_.get(field).GenerateClearingCode(printer);
- printer->Print(vars,
- "clear_has_$oneof_name$();\n");
- printer->Outdent();
- printer->Print("}\n");
- } else {
- field_generators_.get(field).GenerateClearingCode(printer);
- if (HasFieldPresence(descriptor_->file())) {
- if (!field->is_repeated()) {
- printer->Print(vars,
- "clear_has_$name$();\n");
- }
- }
+ if (!use_dependent_base_ || !IsFieldDependent(field)) {
+ vars["tmpl"] = "";
+ vars["dependent_classname"] = vars["classname"];
+ vars["this_message"] = "";
+ vars["this_const_message"] = "";
+ GenerateFieldClear(field, vars, printer);
}
- printer->Outdent();
- printer->Print("}\n");
-
// Generate type-specific accessors.
field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
is_inline);
@@ -602,23 +789,11 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
printer->Print("\n");
}
- // Generate has_$name$() and clear_has_$name$() functions for oneofs
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- map<string, string> vars;
- vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
- vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
- vars["cap_oneof_name"] =
- ToUpper(descriptor_->oneof_decl(i)->name());
- vars["classname"] = classname_;
- vars["inline"] = is_inline ? "inline" : "";
- printer->Print(
- vars,
- "$inline$ bool $classname$::has_$oneof_name$() const {\n"
- " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
- "}\n"
- "$inline$ void $classname$::clear_has_$oneof_name$() {\n"
- " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
- "}\n");
+ if (!use_dependent_base_) {
+ // Generate has_$name$() and clear_has_$name$() functions for oneofs
+ // If we aren't using a dependent base, they can be with the other functions
+ // that are #ifdef-guarded.
+ GenerateOneofHasBits(printer, is_inline);
}
}
@@ -648,6 +823,34 @@ static bool CanClearByZeroing(const FieldDescriptor* field) {
}
void MessageGenerator::
+GenerateDependentBaseClassDefinition(io::Printer* printer) {
+ if (!use_dependent_base_) {
+ return;
+ }
+
+ map<string, string> vars;
+ vars["classname"] = DependentBaseClassTemplateName(descriptor_);
+ vars["superclass"] = SuperClassName(descriptor_);
+
+ printer->Print(vars,
+ "template <class T>\n"
+ "class $classname$ : public $superclass$ {\n"
+ " public:\n");
+ printer->Indent();
+
+ printer->Print(vars,
+ "$classname$() {}\n"
+ "virtual ~$classname$() {}\n"
+ "\n");
+
+ // Generate dependent accessor methods for all fields.
+ GenerateDependentFieldAccessorDeclarations(printer);
+
+ printer->Outdent();
+ printer->Print("};\n");
+}
+
+void MessageGenerator::
GenerateClassDefinition(io::Printer* printer) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// map entry message doesn't need class definition. Since map entry message
@@ -660,6 +863,11 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print("\n");
}
+ if (use_dependent_base_) {
+ GenerateDependentBaseClassDefinition(printer);
+ printer->Print("\n");
+ }
+
map<string, string> vars;
vars["classname"] = classname_;
vars["field_count"] = SimpleItoa(descriptor_->field_count());
@@ -669,11 +877,18 @@ GenerateClassDefinition(io::Printer* printer) {
} else {
vars["dllexport"] = options_.dllexport_decl + " ";
}
- vars["superclass"] = SuperClassName(descriptor_);
-
+ if (use_dependent_base_) {
+ vars["superclass"] =
+ DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
+ } else {
+ vars["superclass"] = SuperClassName(descriptor_);
+ }
printer->Print(vars,
- "class $dllexport$$classname$ : public $superclass$ {\n"
- " public:\n");
+ "class $dllexport$$classname$ : public $superclass$ {\n");
+ if (use_dependent_base_) {
+ printer->Print(vars, " friend class $superclass$;\n");
+ }
+ printer->Print(" public:\n");
printer->Indent();
printer->Print(vars,
@@ -782,6 +997,19 @@ GenerateClassDefinition(io::Printer* printer) {
printer->Print(vars,
"void UnsafeArenaSwap($classname$* other);\n");
}
+
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(vars,
+ "// implements Any -----------------------------------------------\n"
+ "\n"
+ "void PackFrom(const ::google::protobuf::Message& message);\n"
+ "bool UnpackTo(::google::protobuf::Message* message) const;\n"
+ "template<typename T> bool Is() const {\n"
+ " return _any_metadata_.Is<T>();\n"
+ "}\n"
+ "\n");
+ }
+
printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
@@ -973,11 +1201,18 @@ GenerateClassDefinition(io::Printer* printer) {
// Generate oneof function declarations
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print(
- "inline bool has_$oneof_name$() const;\n"
- "void clear_$oneof_name$();\n"
- "inline void clear_has_$oneof_name$();\n\n",
- "oneof_name", descriptor_->oneof_decl(i)->name());
+ if (use_dependent_base_) {
+ printer->Print(
+ "inline bool has_$oneof_name$() const;\n"
+ "inline void clear_has_$oneof_name$();\n\n",
+ "oneof_name", descriptor_->oneof_decl(i)->name());
+ } else {
+ printer->Print(
+ "inline bool has_$oneof_name$() const;\n"
+ "void clear_$oneof_name$();\n"
+ "inline void clear_has_$oneof_name$();\n\n",
+ "oneof_name", descriptor_->oneof_decl(i)->name());
+ }
}
if (HasGeneratedMethods(descriptor_->file()) &&
@@ -1139,6 +1374,12 @@ GenerateClassDefinition(io::Printer* printer) {
"\n");
}
+ // Generate _any_metadata_ for the Any type.
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(vars,
+ "::google::protobuf::internal::AnyMetadata _any_metadata_;\n");
+ }
+
// Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
// friends so that they can access private static variables like
// default_instance_ and reflection_.
@@ -1172,6 +1413,21 @@ GenerateClassDefinition(io::Printer* printer) {
}
void MessageGenerator::
+GenerateDependentInlineMethods(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // map entry message doesn't need inline methods. Since map entry message
+ // cannot be a top level class, we just need to avoid calling
+ // GenerateInlineMethods here.
+ if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
+ nested_generators_[i]->GenerateDependentInlineMethods(printer);
+ printer->Print(kThinSeparator);
+ printer->Print("\n");
+ }
+
+ GenerateDependentFieldAccessorDefinitions(printer);
+}
+
+void MessageGenerator::
GenerateInlineMethods(io::Printer* printer, bool is_inline) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// map entry message doesn't need inline methods. Since map entry message
@@ -1196,7 +1452,8 @@ GenerateInlineMethods(io::Printer* printer, bool is_inline) {
vars["inline"] = is_inline ? "inline " : "";
printer->Print(
vars,
- "$inline$$class_name$::$camel_oneof_name$Case $class_name$::"
+ "$inline$"
+ "$class_name$::$camel_oneof_name$Case $class_name$::"
"$oneof_name$_case() const {\n"
" return $class_name$::$camel_oneof_name$Case("
"_oneof_case_[$oneof_index$]);\n"
@@ -1494,6 +1751,19 @@ GenerateShutdownCode(io::Printer* printer) {
void MessageGenerator::
GenerateClassMethods(io::Printer* printer) {
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(
+ "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n"
+ " _any_metadata_.PackFrom(message);\n"
+ "}\n"
+ "\n"
+ "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n"
+ " return _any_metadata_.UnpackTo(message);\n"
+ "}\n"
+ "\n",
+ "classname", classname_);
+ }
+
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
enum_generators_[i]->GenerateMethods(printer);
}
@@ -1767,7 +2037,7 @@ GenerateArenaDestructorCode(io::Printer* printer) {
if (need_registration) {
printer->Print(
"inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
- " if (arena != NULL) {"
+ " if (arena != NULL) {\n"
" arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
" }\n"
"}\n",
@@ -1782,18 +2052,23 @@ GenerateArenaDestructorCode(io::Printer* printer) {
void MessageGenerator::
GenerateStructors(io::Printer* printer) {
- string superclass = SuperClassName(descriptor_);
- string initializer_with_arena;
- if (UseUnknownFieldSet(descriptor_->file())) {
- initializer_with_arena = "_internal_metadata_(arena)";
+ string superclass;
+ if (use_dependent_base_) {
+ superclass =
+ DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">";
} else {
- initializer_with_arena = "_arena_ptr_(arena)";
+ superclass = SuperClassName(descriptor_);
}
+ string initializer_with_arena = superclass + "()";
+
if (descriptor_->extension_range_count() > 0) {
- initializer_with_arena = string("\n _extensions_(arena)") +
- (!initializer_with_arena.empty() ? ", " : "") + initializer_with_arena;
+ initializer_with_arena += ",\n _extensions_(arena)";
+ }
+
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ initializer_with_arena += ",\n _internal_metadata_(arena)";
} else {
- initializer_with_arena = "\n " + initializer_with_arena;
+ initializer_with_arena += ",\n _arena_ptr_(arena)";
}
// Initialize member variables with arena constructor.
@@ -1804,16 +2079,21 @@ GenerateStructors(io::Printer* printer) {
FieldName(descriptor_->field(i)) + string("_(arena)");
}
}
- initializer_with_arena = superclass + "()" +
- (!initializer_with_arena.empty() ? "," : " ") + initializer_with_arena;
+
+ if (IsAnyMessage(descriptor_)) {
+ initializer_with_arena += ",\n _any_metadata_(&type_url, &value_)";
+ }
string initializer_null;
initializer_null = (UseUnknownFieldSet(descriptor_->file()) ?
- ", _internal_metadata_(NULL) " : ", _arena_ptr_(NULL)");
+ ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)");
+ if (IsAnyMessage(descriptor_)) {
+ initializer_null += ", _any_metadata_(&type_url_, &value_)";
+ }
printer->Print(
"$classname$::$classname$()\n"
- " : $superclass$() $initializer$ {\n"
+ " : $superclass$()$initializer$ {\n"
" SharedCtor();\n"
" // @@protoc_insertion_point(constructor:$full_name$)\n"
"}\n",
@@ -1894,10 +2174,14 @@ GenerateStructors(io::Printer* printer) {
"full_name", descriptor_->full_name());
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(
- ",\n _internal_metadata_(NULL) {\n");
+ ",\n _internal_metadata_(NULL)");
} else if (!UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(",\n _arena_ptr_(NULL) {\n");
+ printer->Print(",\n _arena_ptr_(NULL)");
}
+ if (IsAnyMessage(descriptor_)) {
+ printer->Print(",\n _any_metadata_(&type_url_, &value_)");
+ }
+ printer->Print(" {\n");
printer->Print(
" SharedCtor();\n"
" MergeFrom(from);\n"
@@ -2124,7 +2408,11 @@ GenerateClear(io::Printer* printer) {
have_enclosing_if = true;
}
- field_generators_.get(field).GenerateClearingCode(printer);
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ printer->Print("clear_$name$();\n", "name", fieldname);
+ } else {
+ field_generators_.get(field).GenerateClearingCode(printer);
+ }
if (have_enclosing_if) {
printer->Outdent();
@@ -2147,7 +2435,11 @@ GenerateClear(io::Printer* printer) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
- field_generators_.get(field).GenerateClearingCode(printer);
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ printer->Print("clear_$name$();\n", "name", FieldName(field));
+ } else {
+ field_generators_.get(field).GenerateClearingCode(printer);
+ }
}
}
@@ -2184,19 +2476,38 @@ void MessageGenerator::
GenerateOneofClear(io::Printer* printer) {
// Generated function clears the active field and union case (e.g. foo_case_).
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print(
- "void $classname$::clear_$oneofname$() {\n",
- "classname", classname_,
- "oneofname", descriptor_->oneof_decl(i)->name());
+ map<string, string> oneof_vars;
+ oneof_vars["classname"] = classname_;
+ oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name();
+ string message_class;
+
+ if (use_dependent_base_) {
+ oneof_vars["tmpl"] = "template<class T>\n";
+ oneof_vars["inline"] = "inline ";
+ oneof_vars["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_) + "<T>";
+ oneof_vars["this_message"] = "reinterpret_cast<T*>(this)->";
+ message_class = "T::";
+ } else {
+ oneof_vars["tmpl"] = "";
+ oneof_vars["inline"] = "";
+ oneof_vars["dependent_classname"] = classname_;
+ oneof_vars["this_message"] = "";
+ }
+
+ printer->Print(oneof_vars,
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::clear_$oneofname$() {\n");
printer->Indent();
- printer->Print(
- "switch($oneofname$_case()) {\n",
- "oneofname", descriptor_->oneof_decl(i)->name());
+ printer->Print(oneof_vars,
+ "switch($this_message$$oneofname$_case()) {\n");
printer->Indent();
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(
- "case k$field_name$: {\n",
+ "case $message_class$k$field_name$: {\n",
+ "message_class", message_class,
"field_name", UnderscoresToCamelCase(field->name(), true));
printer->Indent();
// We clear only allocated objects in oneofs
@@ -2213,16 +2524,20 @@ GenerateOneofClear(io::Printer* printer) {
"}\n");
}
printer->Print(
- "case $cap_oneof_name$_NOT_SET: {\n"
+ "case $message_class$$cap_oneof_name$_NOT_SET: {\n"
" break;\n"
"}\n",
+ "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
printer->Print(
"}\n"
- "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n",
+ "$this_message$_oneof_case_[$oneof_index$] = "
+ "$message_class$$cap_oneof_name$_NOT_SET;\n",
+ "this_message", oneof_vars["this_message"],
"oneof_index", SimpleItoa(i),
+ "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
@@ -2333,9 +2648,9 @@ GenerateMergeFrom(io::Printer* printer) {
// system, as the GOOGLE_CHECK above ensured that we have the same descriptor
// for each message.
printer->Print(
- "const $classname$* source =\n"
- " ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
- " &from);\n"
+ "const $classname$* source = \n"
+ " ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n"
+ " &from);\n"
"if (source == NULL) {\n"
" ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
"} else {\n"
@@ -2585,8 +2900,24 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Indent();
+ // Find repeated messages and groups now, to simplify what follows.
+ hash_set<int> fields_with_parse_loop;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = ordered_fields[i];
+ if (field->is_repeated() &&
+ (field->type() == FieldDescriptor::TYPE_MESSAGE ||
+ field->type() == FieldDescriptor::TYPE_GROUP)) {
+ fields_with_parse_loop.insert(i);
+ }
+ }
+
+ // need_label is true if we generated "goto parse_$name$" while handling the
+ // previous field.
+ bool need_label = false;
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = ordered_fields[i];
+ const bool loops = fields_with_parse_loop.count(i) > 0;
+ const bool next_field_loops = fields_with_parse_loop.count(i + 1) > 0;
PrintFieldComment(printer, field);
@@ -2600,9 +2931,16 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Print("if (tag == $commontag$) {\n",
"commontag", SimpleItoa(WireFormat::MakeTag(field)));
- if (i > 0 || (field->is_repeated() && !field->options().packed())) {
+ if (need_label ||
+ (field->is_repeated() && !field->options().packed() && !loops)) {
+ printer->Print(
+ " parse_$name$:\n",
+ "name", field->name());
+ }
+ if (loops) {
printer->Print(
- " parse_$name$:\n",
+ " DO_(input->IncrementRecursionDepth());\n"
+ " parse_loop_$name$:\n",
"name", field->name());
}
@@ -2644,26 +2982,53 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// switch() is slow since it can't be predicted well. Insert some if()s
// here that attempt to predict the next tag.
- if (field->is_repeated() && !field->options().packed()) {
- // Expect repeats of this field.
+ // For non-packed repeated fields, expect the same tag again.
+ if (loops) {
+ printer->Print(
+ "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n",
+ "tag", SimpleItoa(WireFormat::MakeTag(field)),
+ "name", field->name());
+ } else if (field->is_repeated() && !field->options().packed()) {
printer->Print(
"if (input->ExpectTag($tag$)) goto parse_$name$;\n",
"tag", SimpleItoa(WireFormat::MakeTag(field)),
"name", field->name());
}
- if (i + 1 < descriptor_->field_count()) {
- // Expect the next field in order.
- const FieldDescriptor* next_field = ordered_fields[i + 1];
- printer->Print(
- "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
- "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
- "next_name", next_field->name());
- } else {
- // Expect EOF.
- // TODO(kenton): Expect group end-tag?
+ // Have we emitted "if (input->ExpectTag($next_tag$)) ..." yet?
+ bool emitted_goto_next_tag = false;
+
+ // For repeated messages/groups, we need to decrement recursion depth,
+ // unless the next tag is also for a repeated message/group.
+ if (loops) {
+ if (next_field_loops) {
+ const FieldDescriptor* next_field = ordered_fields[i + 1];
+ printer->Print(
+ "if (input->ExpectTag($next_tag$)) goto parse_loop_$next_name$;\n",
+ "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
+ "next_name", next_field->name());
+ emitted_goto_next_tag = true;
+ }
printer->Print(
- "if (input->ExpectAtEnd()) goto success;\n");
+ "input->UnsafeDecrementRecursionDepth();\n");
+ }
+
+ // If there are more fields, expect the next one.
+ need_label = false;
+ if (!emitted_goto_next_tag) {
+ if (i + 1 == descriptor_->field_count()) {
+ // Expect EOF.
+ // TODO(kenton): Expect group end-tag?
+ printer->Print(
+ "if (input->ExpectAtEnd()) goto success;\n");
+ } else {
+ const FieldDescriptor* next_field = ordered_fields[i + 1];
+ printer->Print(
+ "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
+ "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
+ "next_name", next_field->name());
+ need_label = true;
+ }
}
printer->Print(
@@ -2999,9 +3364,7 @@ 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);
+ string m = StrCat("0x", strings::Hex(masks[i], strings::Hex::ZERO_PAD_8));
// Each xor evaluates to 0 if the expected bits are present.
parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")"));
}
@@ -3293,11 +3656,10 @@ GenerateIsInitialized(io::Printer* printer) {
}
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));
+ "mask", StrCat(strings::Hex(mask, strings::Hex::ZERO_PAD_8)));
}
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index ea96581d..23dad10c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -67,7 +67,8 @@ class MessageGenerator {
// Header stuff.
// Generate foward declarations for this class and all its nested types.
- void GenerateForwardDeclaration(io::Printer* printer);
+ void GenerateMessageForwardDeclaration(io::Printer* printer);
+ void GenerateEnumForwardDeclaration(io::Printer* printer);
// Generate definitions of all nested enums (must come before class
// definitions because those classes use the enums definitions).
@@ -84,6 +85,9 @@ class MessageGenerator {
// file).
void GenerateInlineMethods(io::Printer* printer, bool is_inline);
+ // Dependent methods are always inline.
+ void GenerateDependentInlineMethods(io::Printer* printer);
+
// Source file stuff.
// Generate code which declares all the global descriptor pointers which
@@ -115,7 +119,10 @@ class MessageGenerator {
private:
// Generate declarations and definitions of accessors for fields.
+ void GenerateDependentBaseClassDefinition(io::Printer* printer);
+ void GenerateDependentFieldAccessorDeclarations(io::Printer* printer);
void GenerateFieldAccessorDeclarations(io::Printer* printer);
+ void GenerateDependentFieldAccessorDefinitions(io::Printer* printer);
void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline);
// Generate the field offsets array.
@@ -158,6 +165,21 @@ class MessageGenerator {
bool unbounded);
+ // Generates has_foo() functions and variables for singular field has-bits.
+ void GenerateSingularFieldHasBits(const FieldDescriptor* field,
+ map<string, string> vars,
+ io::Printer* printer);
+ // Generates has_foo() functions and variables for oneof field has-bits.
+ void GenerateOneofHasBits(io::Printer* printer, bool is_inline);
+ // Generates has_foo_bar() functions for oneof members.
+ void GenerateOneofMemberHasBits(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer);
+ // Generates the clear_foo() method for a field.
+ void GenerateFieldClear(const FieldDescriptor* field,
+ const map<string, string>& vars,
+ io::Printer* printer);
+
const Descriptor* descriptor_;
string classname_;
Options options_;
@@ -168,6 +190,7 @@ class MessageGenerator {
google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_;
int num_required_fields_;
bool uses_string_;
+ bool use_dependent_base_;
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 467b6bf6..ba318d10 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -72,7 +72,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : descriptor_(descriptor) {
+ : descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -84,6 +85,10 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+}
+
+void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
@@ -144,6 +149,8 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
" return temp;\n"
"}\n");
if (SupportsArenas(descriptor_->message_type())) {
+ // NOTE: the same logic is mirrored in weak_message_field.cc. Any
+ // arena-related semantics changes should be made in both places.
printer->Print(variables_,
"void $classname$::_slow_set_allocated_$name$(\n"
" ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
@@ -181,6 +188,10 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
}
void MessageFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+}
+
+void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
@@ -294,7 +305,7 @@ GenerateClearingCode(io::Printer* printer) const {
// 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"
+ "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) delete $name$_;\n"
"$name$_ = NULL;\n");
} else {
printer->Print(variables_,
@@ -366,6 +377,10 @@ MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
void MessageOneofFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+}
+
+void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
@@ -560,6 +575,10 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+}
+
+void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"const $type$& $name$(int index) const$deprecation$;\n"
@@ -573,6 +592,10 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+}
+
+void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
@@ -627,11 +650,13 @@ void RepeatedMessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
+ "DO_(::google::protobuf::internal::WireFormatLite::"
+ "ReadMessageNoVirtualNoRecursionDepth(\n"
" input, add_$name$()));\n");
} else {
printer->Print(variables_,
- "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
+ "DO_(::google::protobuf::internal::WireFormatLite::"
+ "ReadGroupNoVirtualNoRecursionDepth(\n"
" $number$, input, add_$name$()));\n");
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index c1704fc1..9ddf9643 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -52,7 +52,9 @@ class MessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
+ void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
+ void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const;
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
@@ -67,6 +69,7 @@ class MessageFieldGenerator : public FieldGenerator {
protected:
const FieldDescriptor* descriptor_;
+ const bool dependent_field_;
map<string, string> variables_;
private:
@@ -80,6 +83,7 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
~MessageOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
+ void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const;
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {}
@@ -99,7 +103,9 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
+ void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
+ void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index 0c99cff1..4463f200 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -41,12 +41,13 @@ namespace protobuf {
namespace compiler {
namespace cpp {
-// Generator options:
+// Generator options (see generator.cc for a description of each):
struct Options {
- Options() : safe_boundary_check(false) {
+ Options() : safe_boundary_check(false), proto_h(false) {
}
string dllexport_decl;
bool safe_boundary_check;
+ bool proto_h;
};
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 329eae32..9f929d37 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -262,7 +262,7 @@ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
: descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, &variables_, options);
- if (descriptor->options().packed()) {
+ if (descriptor->is_packed()) {
variables_["packed_reader"] = "ReadPackedPrimitive";
variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
} else {
@@ -277,7 +277,7 @@ void RepeatedPrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
- if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
+ if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) {
printer->Print(variables_,
"mutable int _$name$_cached_byte_size_;\n");
}
@@ -364,7 +364,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -377,7 +377,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
" this->$name$(i), output);\n");
@@ -391,7 +391,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// Write the tag and the size.
printer->Print(variables_,
"if (this->$name$_size() > 0) {\n"
@@ -405,7 +405,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
}
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
@@ -435,7 +435,7 @@ GenerateByteSize(io::Printer* printer) const {
"data_size = $fixed_size$ * this->$name$_size();\n");
}
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (data_size > 0) {\n"
" total_size += $tag_size$ +\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 1a1bcd3d..1a3896a1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -226,7 +226,6 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" } 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"
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 9f63155b..4e25b2ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -131,23 +131,23 @@ message TestConflictingSymbolNamesExtension { // NO_PROTO3
} // NO_PROTO3
} // NO_PROTO3
-message TestConflictingEnumNames {
- enum NestedConflictingEnum {
- and = 1;
- class = 2;
- int = 3;
- typedef = 4;
- XOR = 5;
- }
-
- optional NestedConflictingEnum conflicting_enum = 1;
-}
-
-enum ConflictingEnum {
- NOT_EQ = 1;
- volatile = 2;
- return = 3;
-}
+message TestConflictingEnumNames { // NO_PROTO3
+ enum NestedConflictingEnum { // NO_PROTO3
+ and = 1; // NO_PROTO3
+ class = 2; // NO_PROTO3
+ int = 3; // NO_PROTO3
+ typedef = 4; // NO_PROTO3
+ XOR = 5; // NO_PROTO3
+ } // NO_PROTO3
+
+ optional NestedConflictingEnum conflicting_enum = 1; // NO_PROTO3
+} // NO_PROTO3
+
+enum ConflictingEnum { // NO_PROTO3
+ NOT_EQ = 1; // NO_PROTO3
+ volatile = 2; // NO_PROTO3
+ return = 3; // NO_PROTO3
+} // NO_PROTO3
message DummyMessage {}
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 9d14a924..b11fb21a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -941,6 +941,22 @@ TEST(GeneratedMessageTest, ExtensionConstantValues) {
EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51);
}
+TEST(GeneratedMessageTest, ParseFromTruncated) {
+ const string long_string = string(128, 'q');
+ FileDescriptorProto p;
+ p.add_extension()->set_name(long_string);
+ const string msg = p.SerializeAsString();
+ int successful_count = 0;
+ for (int i = 0; i <= msg.size(); i++) {
+ if (p.ParseFromArray(msg.c_str(), i)) {
+ ++successful_count;
+ }
+ }
+ // We don't really care about how often we succeeded.
+ // As long as we didn't crash, we're happy.
+ EXPECT_GE(successful_count, 1);
+}
+
// ===================================================================
TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) {
diff --git a/src/google/protobuf/compiler/cpp/test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto
new file mode 100644
index 00000000..cb6ca1b1
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto
@@ -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.
+
+// Test that proto2 compiler can generate valid code when the enum value
+// is INT_MAX. Note that this is a compile-only test and this proto is not
+// referenced in any C++ code.
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message TestLargeEnumValue {
+ enum EnumWithLargeValue {
+ VALUE_1 = 1;
+ VALUE_MAX = 0x7fffffff;
+ }
+}
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 71a2ba4b..39318a19 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -67,7 +67,13 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
(*variables)["default_number"] = SimpleItoa(
descriptor->default_value_enum()->number());
- (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+ if (descriptor->is_packed()) {
+ (*variables)["tag"] = SimpleItoa(internal::WireFormatLite::MakeTag(
+ descriptor->number(),
+ internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+ } else {
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+ }
(*variables)["tag_size"] = SimpleItoa(
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
@@ -641,7 +647,7 @@ GenerateMembers(io::Printer* printer) const {
"}\n");
}
- if (descriptor_->options().packed() &&
+ if (descriptor_->is_packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize;\n");
@@ -884,7 +890,7 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void RepeatedImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (get$capitalized_name$List().size() > 0) {\n"
" output.writeRawVarint32($tag$);\n"
@@ -915,7 +921,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"}\n");
printer->Print(
"size += dataSize;\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (!get$capitalized_name$List().isEmpty()) {"
" size += $tag_size$;\n"
@@ -928,7 +934,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
// cache the data size for packed fields.
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"$name$MemoizedSerializedSize = dataSize;\n");
}
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
new file mode 100644
index 00000000..697a07a7
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -0,0 +1,967 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum_field_lite.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+void SetEnumVariables(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->enum_type());
+ (*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)));
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ if (SupportFieldPresence(descriptor->file())) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " +
+ (*variables)["default"] + ".getNumber()";
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ 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
+
+// ===================================================================
+
+ImmutableEnumFieldLiteGenerator::
+ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
+
+int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ 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");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private int $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ }
+ 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"
+ " $type$ result = $type$.valueOf($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ "}\n");
+
+ // Generate private setters for the builder to proxy into.
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(int value) {\n"
+ " $set_has_field_bit_message$"
+ " $name$_ = value;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value.getNumber();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n"
+ " $name$_ = $default_number$;\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return instance.get$capitalized_name$Value();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(int value);\n"
+ " return this;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default_number$;\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+ } else if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "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.";
+ }
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = rawValue;\n");
+ } else {
+ printer->Print(variables_,
+ "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");
+ }
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.writeEnum($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSize($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && $name$_ == other.$name$_;\n");
+}
+
+void ImmutableEnumFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + $name$_;\n");
+}
+
+string ImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+// ===================================================================
+
+ImmutableEnumOneofFieldLiteGenerator::
+ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableEnumFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableEnumOneofFieldLiteGenerator::
+~ImmutableEnumOneofFieldLiteGenerator() {}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+ 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"
+ " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+
+ // Generate private setters for the builder to proxy into.
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(int value) {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value.getNumber();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return instance.get$capitalized_name$Value();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(value);\n"
+ " return this;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ 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 ImmutableEnumOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = rawValue;\n");
+ } else {
+ printer->Print(variables_,
+ "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");
+ }
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutableEnumOneofFieldLiteGenerator::
+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 ImmutableEnumOneofFieldLiteGenerator::
+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");
+ }
+}
+
+// ===================================================================
+
+RepeatedImmutableEnumFieldLiteGenerator::
+RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetEnumVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableEnumFieldLiteGenerator::
+~RepeatedImmutableEnumFieldLiteGenerator() {}
+
+int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ 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 RepeatedImmutableEnumFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ // TODO(dweis): Switch to IntList?
+ "private com.google.protobuf.Internal.ProtobufList<\n"
+ " 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 new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return $name$_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())) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize;\n");
+ }
+
+ // Generate private setters for the builder to proxy into.
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList($name$_);\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value.getNumber());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value.getNumber());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for ($type$ value : values) {\n"
+ " $name$_.add(value.getNumber());\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyProtobufList();\n"
+ "}\n");
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Value(\n"
+ " int index, int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$Value(int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void 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"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return instance.get$capitalized_name$List();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\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(\n"
+ " instance.get$capitalized_name$ValueList());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+ " return instance.get$capitalized_name$Value(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(\n"
+ " int index, int value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Value(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+ " instance.add$capitalized_name$Value(value);\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"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$Value(values);\n"
+ " return this;\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for enums
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // The code below does two optimizations:
+ // 1. If the other list is empty, there's nothing to do. This ensures we
+ // don't allocate a new array if we already have an immutable one.
+ // 2. If the other list is non-empty and our current list is empty, we can
+ // reuse the other list which is guaranteed to be immutable.
+ printer->Print(variables_,
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = other.$name$_;\n"
+ " } else {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.addAll(other.$name$_);\n"
+ " }\n"
+ " $on_changed$\n"
+ "}\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ // Read and store the enum
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "int rawValue = input.readEnum();\n"
+ "if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ "}\n"
+ "$name$_.add(rawValue);\n");
+ } else {
+ printer->Print(variables_,
+ "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 (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ " }\n"
+ " $name$_.add(rawValue);\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Wrap GenerateParsingCode's contents with a while loop.
+
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int oldLimit = input.pushLimit(length);\n"
+ "while(input.getBytesUntilLimit() > 0) {\n");
+ printer->Indent();
+
+ GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(oldLimit);\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $name$_.makeImmutable();\n"
+ "}\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.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));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .computeEnumSizeNoTag($name$_.get(i));\n"
+ "}\n");
+ printer->Print(
+ "size += dataSize;\n");
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeRawVarint32Size(dataSize);\n"
+ "}");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * $name$_.size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && $name$_.equals(other.$name$_);\n");
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + $name$_.hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->enum_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h
new file mode 100644
index 00000000..2c41c3e4
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h
@@ -0,0 +1,159 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableEnumFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableEnumFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateMergingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator);
+};
+
+class ImmutableEnumOneofFieldLiteGenerator
+ : public ImmutableEnumFieldLiteGenerator {
+ public:
+ ImmutableEnumOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableEnumOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableEnumFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableEnumFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableEnumFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateMergingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index af9978e2..3f0fa11f 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -42,12 +42,18 @@
#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_enum_field_lite.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_lazy_message_field_lite.h>
#include <google/protobuf/compiler/java/java_map_field.h>
+#include <google/protobuf/compiler/java/java_map_field_lite.h>
#include <google/protobuf/compiler/java/java_message_field.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
#include <google/protobuf/compiler/java/java_primitive_field.h>
+#include <google/protobuf/compiler/java/java_primitive_field_lite.h>
#include <google/protobuf/compiler/java/java_string_field.h>
+#include <google/protobuf/compiler/java/java_string_field_lite.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -133,6 +139,79 @@ ImmutableFieldGenerator* MakeImmutableGenerator(
}
}
+ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator(
+ const FieldDescriptor* field, int messageBitIndex, int builderBitIndex,
+ Context* context) {
+ if (field->is_repeated()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsMapEntry(field->message_type())) {
+ return new ImmutableMapFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ if (IsLazy(field)) {
+ return new RepeatedImmutableLazyMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new RepeatedImmutableMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ }
+ case JAVATYPE_ENUM:
+ return new RepeatedImmutableEnumFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new RepeatedImmutableStringFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new RepeatedImmutablePrimitiveFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ } else {
+ if (field->containing_oneof()) {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsLazy(field)) {
+ return new ImmutableLazyMessageOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new ImmutableMessageOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new ImmutablePrimitiveOneofFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ } else {
+ switch (GetJavaType(field)) {
+ case JAVATYPE_MESSAGE:
+ if (IsLazy(field)) {
+ return new ImmutableLazyMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new ImmutableMessageFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ case JAVATYPE_ENUM:
+ return new ImmutableEnumFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ case JAVATYPE_STRING:
+ return new ImmutableStringFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ default:
+ return new ImmutablePrimitiveFieldLiteGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
+ }
+ }
+}
+
static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) {
// Reaching here indicates a bug. Cases are:
@@ -153,6 +232,13 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
ReportUnexpectedPackedFieldsCall(printer);
}
+ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {}
+
+void ImmutableFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ ReportUnexpectedPackedFieldsCall(printer);
+}
+
// ===================================================================
template <>
@@ -178,6 +264,28 @@ FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap(
template<>
FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {}
+template <>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor),
+ field_generators_(new google::protobuf::scoped_ptr<
+ ImmutableFieldLiteGenerator>[descriptor->field_count()]) {
+ // Construct all the FieldGenerators and assign them bit indices for their
+ // bit fields.
+ int messageBitIndex = 0;
+ int builderBitIndex = 0;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator(
+ descriptor->field(i), messageBitIndex, builderBitIndex, context);
+ field_generators_[i].reset(generator);
+ messageBitIndex += generator->GetNumBitsForMessage();
+ builderBitIndex += generator->GetNumBitsForBuilder();
+ }
+}
+
+template<>
+FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {}
+
void SetCommonFieldVariables(const FieldDescriptor* descriptor,
const FieldGeneratorInfo* info,
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index 1cf360c1..00f3c601 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -83,7 +83,6 @@ class ImmutableFieldGenerator {
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
const = 0;
- virtual void GenerateStaticInitializationCode(io::Printer* printer) const {}
virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
virtual void GenerateHashCode(io::Printer* printer) const = 0;
@@ -94,6 +93,37 @@ class ImmutableFieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator);
};
+class ImmutableFieldLiteGenerator {
+ public:
+ ImmutableFieldLiteGenerator() {}
+ virtual ~ImmutableFieldLiteGenerator();
+
+ virtual int GetNumBitsForMessage() const = 0;
+ virtual int GetNumBitsForBuilder() const = 0;
+ virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0;
+ virtual void GenerateMembers(io::Printer* printer) const = 0;
+ virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+ virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+ virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer)
+ const = 0;
+ virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
+ virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
+ virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer)
+ const = 0;
+
+ virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
+ virtual void GenerateHashCode(io::Printer* printer) const = 0;
+
+ virtual string GetBoxedType() const = 0;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator);
+};
+
// Convenience class which constructs FieldGenerators for a Descriptor.
template<typename FieldGeneratorType>
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 4a1f4529..68b47ee1 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -35,10 +35,10 @@
#include <google/protobuf/compiler/java/java_file.h>
#include <memory>
-#include <set>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <set>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum.h>
@@ -153,6 +153,12 @@ void CollectExtensions(const FileDescriptorProto& file_proto,
}
}
+// Compare two field descriptors, returning true if the first should come
+// before the second.
+bool CompareFieldsByName(const FieldDescriptor *a, const FieldDescriptor *b) {
+ return a->full_name() < b->full_name();
+}
+
// Our static initialization methods can become very, very large.
// So large that if we aren't careful we end up blowing the JVM's
// 64K bytes of bytecode/method. Fortunately, since these static
@@ -166,7 +172,6 @@ void MaybeRestartJavaMethod(io::Printer* printer,
int *method_num,
const char *chain_statement,
const char *method_decl) {
-
// The goal here is to stay under 64K bytes of jvm bytecode/method,
// since otherwise we hit a hardcoded limit in the jvm and javac will
// then fail with the error "code too large". This limit lets our
@@ -184,6 +189,7 @@ void MaybeRestartJavaMethod(io::Printer* printer,
}
}
+
} // namespace
FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api)
diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc
index 2d1437f0..92ef851b 100644
--- a/src/google/protobuf/compiler/java/java_generator_factory.cc
+++ b/src/google/protobuf/compiler/java/java_generator_factory.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/compiler/java/java_field.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_message.h>
+#include <google/protobuf/compiler/java/java_message_lite.h>
#include <google/protobuf/compiler/java/java_service.h>
namespace google {
@@ -57,7 +58,12 @@ ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {}
MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator(
const Descriptor* descriptor) const {
- return new ImmutableMessageGenerator(descriptor, context_);
+ if (descriptor->file()->options().optimize_for() ==
+ FileOptions::LITE_RUNTIME) {
+ return new ImmutableMessageLiteGenerator(descriptor, context_);
+ } else {
+ return new ImmutableMessageGenerator(descriptor, context_);
+ }
}
ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 62efbefa..96d2545f 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -196,12 +196,6 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
FileOptions::LITE_RUNTIME;
}
-inline bool HasNestedBuilders(const Descriptor* descriptor) {
- // The proto-lite version doesn't support nested builders.
- return descriptor->file()->options().optimize_for() !=
- FileOptions::LITE_RUNTIME;
-}
-
// Should we generate generic services for this file?
inline bool HasGenericServices(const FileDescriptor *file) {
return file->service_count() > 0 &&
@@ -330,6 +324,10 @@ inline bool IsMapEntry(const Descriptor* descriptor) {
return descriptor->options().map_entry();
}
+inline bool IsMapField(const FieldDescriptor* descriptor) {
+ return descriptor->is_map();
+}
+
inline bool PreserveUnknownFields(const Descriptor* descriptor) {
return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
index 6e29a40b..0de8cbe5 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
@@ -72,14 +72,12 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
- "}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " return $name$_;\n"
- "}\n");
- }
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " return $name$_;\n"
+ "}\n");
}
void ImmutableLazyMessageFieldGenerator::
@@ -92,14 +90,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
"private com.google.protobuf.LazyFieldLite $name$_ =\n"
" new com.google.protobuf.LazyFieldLite();\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+ "\n");
// The comments above the methods below are based on a hypothetical
// field of type "Field" called "Field".
@@ -179,39 +175,37 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$clear_has_field_bit_builder$;\n"
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
- " $set_has_field_bit_builder$;\n"
- " $on_changed$\n"
- " return get$capitalized_name$FieldBuilder().getBuilder();\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n"
- " return $name$_;\n"
- " }\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " $name$_,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+ " $set_has_field_bit_builder$;\n"
+ " $on_changed$\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " return $name$_;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " $name$_,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
@@ -538,14 +532,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n"
"\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+ "\n");
// The comments above the methods below are based on a hypothetical
// repeated field of type "Field" called "RepeatedField".
@@ -723,70 +715,68 @@ GenerateBuilderMembers(io::Printer* printer) const {
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
- " int index) {\n"
- " if ($name$Builder_ == null) {\n"
- " return $name$_.get(index);"
- " } else {\n"
- " return $name$Builder_.getMessageOrBuilder(index);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " if ($name$Builder_ == null) {\n"
+ " return $name$_.get(index);"
+ " } else {\n"
+ " return $name$Builder_.getMessageOrBuilder(index);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
- " get$capitalized_name$OrBuilderList() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilderList();\n"
- " } else {\n"
- " return java.util.Collections.unmodifiableList($name$_);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilderList();\n"
+ " } else {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " index, $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<$type$.Builder> \n"
- " get$capitalized_name$BuilderList() {\n"
- " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
- "}\n"
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " $name$_,\n"
- " $get_mutable_bit_builder$,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " index, $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$.Builder> \n"
+ " get$capitalized_name$BuilderList() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+ "}\n"
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " $name$_,\n"
+ " $get_mutable_bit_builder$,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void RepeatedImmutableLazyMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
new file mode 100644
index 00000000..283ba1d3
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
@@ -0,0 +1,708 @@
+// 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: niwasaki@google.com (Naoki Iwasaki)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+ImmutableLazyMessageFieldLiteGenerator::
+ImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+ImmutableLazyMessageFieldLiteGenerator::
+~ImmutableLazyMessageFieldLiteGenerator() {}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.LazyFieldLite $name$_ =\n"
+ " new com.google.protobuf.LazyFieldLite();\n");
+
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $name$_.setValue(value);\n"
+ " $set_has_field_bit_message$;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " $name$_.setValue(builderForValue.build());\n"
+ " $set_has_field_bit_message$;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($get_has_field_bit_message$ &&\n"
+ " !$name$_.containsDefaultInstance()) {\n"
+ " $name$_.setValue(\n"
+ " $type$.newBuilder(\n"
+ " get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+ " } else {\n"
+ " $name$_.setValue(value);\n"
+ " }\n"
+ " $set_has_field_bit_message$;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_.clear();\n"
+ " $clear_has_field_bit_message$;\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_.clear();\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " $name$_.merge(other.$name$_);\n"
+ " $set_has_field_bit_message$;\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.setByteString(input.readBytes(), extensionRegistry);\n");
+ printer->Print(variables_,
+ "$set_has_field_bit_message$;\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ // Do not de-serialize lazy fields.
+ printer->Print(variables_,
+ "if ($get_has_field_bit_message$) {\n"
+ " output.writeBytes($number$, $name$_.toByteString());\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($get_has_field_bit_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeLazyFieldSize($number$, $name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+ImmutableLazyMessageOneofFieldLiteGenerator::
+ImmutableLazyMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableLazyMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+ variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite";
+}
+
+ImmutableLazyMessageOneofFieldLiteGenerator::
+~ImmutableLazyMessageOneofFieldLiteGenerator() {}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n"
+ " $type$.getDefaultInstance());\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ " $set_oneof_case_message$;\n"
+ " }\n"
+ " (($lazy_type$) $oneof_name$_).setValue(value);\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ " $set_oneof_case_message$;\n"
+ " }\n"
+ " (($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($has_oneof_case_message$ &&\n"
+ " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n"
+ " (($lazy_type$) $oneof_name$_).setValue(\n"
+ " $type$.newBuilder(\n"
+ " get$capitalized_name$()).mergeFrom(value).buildPartial());\n"
+ " } else {\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ " $set_oneof_case_message$;\n"
+ " }\n"
+ " (($lazy_type$) $oneof_name$_).setValue(value);\n"
+ " }\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ "}\n"
+ "(($lazy_type$) $oneof_name$_).merge(\n"
+ " ($lazy_type$) other.$oneof_name$_);\n"
+ "$set_oneof_case_message$;\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = new $lazy_type$();\n"
+ "}\n"
+ "(($lazy_type$) $oneof_name$_).setByteString(\n"
+ " input.readBytes(), extensionRegistry);\n"
+ "$set_oneof_case_message$;\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ // Do not de-serialize lazy fields.
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeBytes(\n"
+ " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n"
+ "}\n");
+}
+
+void ImmutableLazyMessageOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableLazyMessageFieldLiteGenerator::
+RepeatedImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : RepeatedImmutableMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+}
+
+
+RepeatedImmutableLazyMessageFieldLiteGenerator::
+~RepeatedImmutableLazyMessageFieldLiteGenerator() {}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.Internal.ProtobufList<\n"
+ " com.google.protobuf.LazyFieldLite> $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$>\n"
+ " get$capitalized_name$List() {\n"
+ " java.util.List<$type$> list =\n"
+ " new java.util.ArrayList<$type$>($name$_.size());\n"
+ " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n"
+ " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n"
+ " }\n"
+ // TODO(dweis): Make this list immutable?
+ " return list;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder>\n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " return get$capitalized_name$List();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return ($type$)\n"
+ " $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " return ($type$OrBuilder)\n"
+ " $name$_.get(index).getValue($type$.getDefaultInstance());\n"
+ "}\n");
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList($name$_);\n"
+ " }\n"
+ "}\n"
+ "\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(\n"
+ " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+ " builderForValue.build()));\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(\n"
+ " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n"
+ " builderForValue.build()));\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n"
+ " builderForValue.build()));\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for (com.google.protobuf.MessageLite v : values) {\n"
+ " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n"
+ " }\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyProtobufList();\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void remove$capitalized_name$(int index) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.remove(index);\n"
+ "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // List<Field> getRepeatedFieldList()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+
+ // int getRepeatedFieldCount()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+
+ // Field getRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+ " copyOnWrite();\n"
+ " instance.remove$capitalized_name$(index);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ "}\n"
+ "$name$_.add(new com.google.protobuf.LazyFieldLite(\n"
+ " extensionRegistry, input.readBytes()));\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeBytes($number$, $name$_.get(i).toByteString());\n"
+ "}\n");
+}
+
+void RepeatedImmutableLazyMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeLazyFieldSize($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
new file mode 100644
index 00000000..e85ec0f3
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
@@ -0,0 +1,118 @@
+// 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: niwasaki@google.com (Naoki Iwasaki)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableLazyMessageFieldLiteGenerator
+ : public ImmutableMessageFieldLiteGenerator {
+ public:
+ explicit ImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableLazyMessageFieldLiteGenerator();
+
+ // overroads ImmutableMessageFieldLiteGenerator ------------------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldLiteGenerator);
+};
+
+class ImmutableLazyMessageOneofFieldLiteGenerator
+ : public ImmutableLazyMessageFieldLiteGenerator {
+ public:
+ ImmutableLazyMessageOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableLazyMessageOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableLazyMessageFieldLiteGenerator
+ : public RepeatedImmutableMessageFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableLazyMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableLazyMessageFieldLiteGenerator();
+
+ // overroads RepeatedImmutableMessageFieldLiteGenerator ----------------------
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index cf1ef589..f25970e5 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -133,9 +133,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["set_mutable_bit_parser"] =
GenerateSetBitMutableLocal(builderBitIndex);
+ (*variables)["default_entry"] = (*variables)["capitalized_name"] +
+ "DefaultEntryHolder.defaultEntry";
if (HasDescriptorMethods(descriptor->file())) {
(*variables)["lite"] = "";
- (*variables)["map_field_parameter"] = (*variables)["name"] + "DefaultEntry";
+ (*variables)["map_field_parameter"] = (*variables)["default_entry"];
(*variables)["descriptor"] =
name_resolver->GetImmutableClassName(descriptor->file()) +
".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
@@ -198,26 +200,20 @@ GenerateInterfaceMembers(io::Printer* printer) const {
}
void ImmutableMapFieldGenerator::
-GenerateStaticInitializationCode(io::Printer* printer) const {
- printer->Print(
- variables_,
- "$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"
- "\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");
+ "private static final class $capitalized_name$DefaultEntryHolder {\n"
+ " static final com.google.protobuf.MapEntry$lite$<\n"
+ " $type_parameters$> 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"
+ "}\n");
printer->Print(
variables_,
"private com.google.protobuf.MapField$lite$<\n"
@@ -291,7 +287,10 @@ GenerateBuilderMembers(io::Printer* printer) const {
" if ($name$_ == null) {\n"
" $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
" $map_field_parameter$);\n"
- " }\n"
+ " }\n"
+ " if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.copy();\n"
+ " }\n"
" return $name$_;\n"
"}\n");
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
@@ -381,10 +380,8 @@ 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$_ = internalGet$capitalized_name$().copy();\n");
+ "result.$name$_ = internalGet$capitalized_name$();\n"
+ "result.$name$_.makeImmutable();\n");
}
void ImmutableMapFieldGenerator::
@@ -402,7 +399,7 @@ GenerateParsingCode(io::Printer* printer) const {
variables_,
"com.google.protobuf.ByteString bytes = input.readBytes();\n"
"com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
- "$name$ = $name$DefaultEntry.getParserForType().parseFrom(bytes);\n");
+ "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
printer->Print(
variables_,
"if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
@@ -415,7 +412,7 @@ GenerateParsingCode(io::Printer* printer) const {
variables_,
"com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
"$name$ = input.readMessage(\n"
- " $name$DefaultEntry.getParserForType(), extensionRegistry);\n"
+ " $default_entry$.getParserForType(), extensionRegistry);\n"
"$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
}
}
@@ -432,7 +429,7 @@ GenerateSerializationCode(io::Printer* printer) const {
"for (java.util.Map.Entry<$type_parameters$> entry\n"
" : internalGet$capitalized_name$().getMap().entrySet()) {\n"
" com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
- " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
" .setKey(entry.getKey())\n"
" .setValue(entry.getValue())\n"
" .build();\n"
@@ -447,7 +444,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"for (java.util.Map.Entry<$type_parameters$> entry\n"
" : internalGet$capitalized_name$().getMap().entrySet()) {\n"
" com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
- " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
" .setKey(entry.getKey())\n"
" .setValue(entry.getValue())\n"
" .build();\n"
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
index 3e6dd973..80a94f45 100644
--- a/src/google/protobuf/compiler/java/java_map_field.h
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -60,7 +60,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
- void GenerateStaticInitializationCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
new file mode 100644
index 00000000..ccc1b32e
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -0,0 +1,461 @@
+// 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_lite.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();" : "";
+
+ (*variables)["default_entry"] = (*variables)["capitalized_name"] +
+ "DefaultEntryHolder.defaultEntry";
+ (*variables)["lite"] = "Lite";
+ (*variables)["descriptor"] = "";
+}
+
+} // namespace
+
+ImmutableMapFieldLiteGenerator::
+ImmutableMapFieldLiteGenerator(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_);
+}
+
+ImmutableMapFieldLiteGenerator::
+~ImmutableMapFieldLiteGenerator() {}
+
+int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutableMapFieldLiteGenerator::
+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 ImmutableMapFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private static final class $capitalized_name$DefaultEntryHolder {\n"
+ " static final com.google.protobuf.MapEntry$lite$<\n"
+ " $type_parameters$> 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"
+ "}\n");
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.MapField$lite$<\n"
+ " $type_parameters$> $name$_ =\n"
+ " com.google.protobuf.MapField$lite$.emptyMapField();\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " return $name$_;\n"
+ "}\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGetMutable$capitalized_name$() {\n"
+ " if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.copy();\n"
+ " }\n"
+ " return $name$_;\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 internalGet$capitalized_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"
+ " internalGet$capitalized_name$().getMap(),\n"
+ " $name$ValueConverter);\n"
+ "}\n");
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return internalGet$capitalized_name$().getMap();\n"
+ "}\n");
+ }
+
+ // Generate private setters for the builder to proxy into.
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " internalGetMutable$capitalized_name$().getMutableMap(),\n"
+ " $name$ValueConverter);\n"
+ "}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "getMutable$capitalized_name$Value() {\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
+ "}\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "private java.util.Map<$type_parameters$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ 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 instance.get$capitalized_name$();\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"
+ " copyOnWrite();\n"
+ " return instance.getMutable$capitalized_name$();\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 instance.get$capitalized_name$Value();\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"
+ " copyOnWrite();\n"
+ " return instance.getMutable$capitalized_name$Value();\n"
+ "}\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " return instance.getMutable$capitalized_name$();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "internalGetMutable$capitalized_name$().mergeFrom(\n"
+ " other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!$name$_.isMutable()) {\n"
+ " $name$_ = $name$_.copy();\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$ = $default_entry$.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"
+ " $default_entry$.getParserForType(), extensionRegistry);\n"
+ "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+ }
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // Nothing to do here.
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " output.writeMessage($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $default_entry$.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeMessageSize($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "result = result && internalGet$capitalized_name$().equals(\n"
+ " other.internalGet$capitalized_name$());\n");
+}
+
+void ImmutableMapFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
+ "}\n");
+}
+
+string ImmutableMapFieldLiteGenerator::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_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h
new file mode 100644
index 00000000..82472602
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.h
@@ -0,0 +1,81 @@
+// 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_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableMapFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMapFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateMergingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(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_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 63df10b4..09b0fd94 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -49,6 +49,8 @@
#include <google/protobuf/compiler/java/java_extension.h>
#include <google/protobuf/compiler/java/java_generator_factory.h>
#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_message_builder.h>
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/printer.h>
@@ -93,43 +95,46 @@ ImmutableMessageGenerator::ImmutableMessageGenerator(
: MessageGenerator(descriptor), context_(context),
name_resolver_(context->GetNameResolver()),
field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_NE(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
}
ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
- // used in the construction of descriptors, we have a tricky bootstrapping
- // problem. To help control static initialization order, we make sure all
- // descriptors and other static data that depends on them are members of
- // the outermost class in the file. This way, they will be initialized in
- // a deterministic order.
-
- map<string, string> vars;
- vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
- vars["index"] = SimpleItoa(descriptor_->index());
- vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
- if (descriptor_->containing_type() != NULL) {
- vars["parent"] = UniqueFileScopeIdentifier(
- descriptor_->containing_type());
- }
- if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
- // We can only make these package-private since the classes that use them
- // are in separate files.
- vars["private"] = "";
- } else {
- vars["private"] = "private ";
- }
-
- // The descriptor for this type.
- printer->Print(vars,
- "$private$static com.google.protobuf.Descriptors.Descriptor\n"
- " internal_$identifier$_descriptor;\n");
+ // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is
+ // used in the construction of descriptors, we have a tricky bootstrapping
+ // problem. To help control static initialization order, we make sure all
+ // descriptors and other static data that depends on them are members of
+ // the outermost class in the file. This way, they will be initialized in
+ // a deterministic order.
- // And the FieldAccessorTable.
- GenerateFieldAccessorTable(printer);
+ map<string, string> vars;
+ vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+ vars["index"] = SimpleItoa(descriptor_->index());
+ vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+ if (descriptor_->containing_type() != NULL) {
+ vars["parent"] = UniqueFileScopeIdentifier(
+ descriptor_->containing_type());
}
+ if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
+ // We can only make these package-private since the classes that use them
+ // are in separate files.
+ vars["private"] = "";
+ } else {
+ vars["private"] = "private ";
+ }
+
+ // The descriptor for this type.
+ printer->Print(vars,
+ // TODO(teboring): final needs to be added back. The way to fix it is to
+ // generate methods that can construct the types, and then still declare the
+ // types, and then init them in clinit with the new method calls.
+ "$private$static com.google.protobuf.Descriptors.Descriptor\n"
+ " internal_$identifier$_descriptor;\n");
+
+ // And the FieldAccessorTable.
+ GenerateFieldAccessorTable(printer);
// Generate static members for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -142,38 +147,37 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
io::Printer* printer) {
int bytecode_estimate = 0;
- if (HasDescriptorMethods(descriptor_)) {
- map<string, string> vars;
- vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
- vars["index"] = SimpleItoa(descriptor_->index());
- vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
- if (descriptor_->containing_type() != NULL) {
- vars["parent"] = UniqueFileScopeIdentifier(
- descriptor_->containing_type());
- }
-
- // The descriptor for this type.
- if (descriptor_->containing_type() == NULL) {
- printer->Print(vars,
- "internal_$identifier$_descriptor =\n"
- " getDescriptor().getMessageTypes().get($index$);\n");
- bytecode_estimate += 30;
- } else {
- printer->Print(vars,
- "internal_$identifier$_descriptor =\n"
- " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
- bytecode_estimate += 30;
- }
+ map<string, string> vars;
+ vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
+ vars["index"] = SimpleItoa(descriptor_->index());
+ vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
+ if (descriptor_->containing_type() != NULL) {
+ vars["parent"] = UniqueFileScopeIdentifier(
+ descriptor_->containing_type());
+ }
- // And the FieldAccessorTable.
- bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
+ // The descriptor for this type.
+ if (descriptor_->containing_type() == NULL) {
+ printer->Print(vars,
+ "internal_$identifier$_descriptor =\n"
+ " getDescriptor().getMessageTypes().get($index$);\n");
+ bytecode_estimate += 30;
+ } else {
+ printer->Print(vars,
+ "internal_$identifier$_descriptor =\n"
+ " internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
+ bytecode_estimate += 30;
}
+ // And the FieldAccessorTable.
+ bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
+
// Generate static member initializers for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
- bytecode_estimate += ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
- .GenerateStaticVariableInitializers(printer);
+ bytecode_estimate +=
+ ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariableInitializers(printer);
}
return bytecode_estimate;
}
@@ -229,40 +233,20 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) {
void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public interface $classname$OrBuilder extends\n"
- " $extra_interfaces$\n"
- " com.google.protobuf.GeneratedMessage.\n"
- " ExtendableMessageOrBuilder<$classname$> {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- } else {
- printer->Print(
- "public interface $classname$OrBuilder extends \n"
- " $extra_interfaces$\n"
- " com.google.protobuf.GeneratedMessageLite.\n"
- " ExtendableMessageOrBuilder<\n"
- " $classname$, $classname$.Builder> {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- }
+ printer->Print(
+ "public interface $classname$OrBuilder extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.GeneratedMessage.\n"
+ " ExtendableMessageOrBuilder<$classname$> {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
} else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public interface $classname$OrBuilder extends\n"
- " $extra_interfaces$\n"
- " com.google.protobuf.MessageOrBuilder {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- } else {
- printer->Print(
- "public interface $classname$OrBuilder extends\n"
- " $extra_interfaces$\n"
- " com.google.protobuf.MessageLiteOrBuilder {\n",
- "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
- "classname", descriptor_->name());
- }
+ printer->Print(
+ "public interface $classname$OrBuilder extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.MessageOrBuilder {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
}
printer->Indent();
@@ -287,98 +271,71 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
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(variables,
- "public $static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
- " $classname$> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n");
- } else {
- printer->Print(variables,
- "public $static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
- " $classname$, $classname$.Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n");
- }
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessage.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"]);
+ "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_));
} else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(variables,
- "public $static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n");
- } else {
- printer->Print(variables,
- "public $static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessageLite<\n"
- " $classname$, $classname$.Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n");
- }
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessage implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
- builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessage$0.Builder",
- variables["lite"]);
+ builder_type = "com.google.protobuf.GeneratedMessage.Builder";
}
printer->Indent();
- if (HasDescriptorMethods(descriptor_)) {
- // Using builder_type, instead of Builder, prevents the Builder class from
- // being loaded into PermGen space when the default instance is created.
- // This optimizes the PermGen space usage for clients that do not modify
- // messages.
- printer->Print(
- "// Use $classname$.newBuilder() to construct.\n"
- "private $classname$($buildertype$ builder) {\n"
- " super(builder);\n"
- "}\n",
- "classname", descriptor_->name(),
- "buildertype", builder_type);
- printer->Print(
- "private $classname$() {\n",
- "classname", descriptor_->name());
- printer->Indent();
- GenerateInitializers(printer);
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n");
- }
+ // Using builder_type, instead of Builder, prevents the Builder class from
+ // being loaded into PermGen space when the default instance is created.
+ // This optimizes the PermGen space usage for clients that do not modify
+ // messages.
+ printer->Print(
+ "// Use $classname$.newBuilder() to construct.\n"
+ "private $classname$($buildertype$ builder) {\n"
+ " super(builder);\n"
+ "}\n",
+ "classname", descriptor_->name(),
+ "buildertype", builder_type);
+ printer->Print(
+ "private $classname$() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ GenerateInitializers(printer);
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
- if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public final com.google.protobuf.UnknownFieldSet\n"
+ "getUnknownFields() {\n");
+ if (PreserveUnknownFields(descriptor_)) {
printer->Print(
- "@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");
- }
+ " return this.unknownFields;\n");
+ } else {
printer->Print(
- "}\n");
+ " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
}
+ printer->Print(
+ "}\n");
if (HasGeneratedMethods(descriptor_)) {
GenerateParsingConstructor(printer);
}
- GenerateDescriptorMethods(printer, false);
- GenerateParser(printer);
+ GenerateDescriptorMethods(printer);
// Nested types
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
@@ -488,7 +445,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
}
if (HasGeneratedMethods(descriptor_)) {
- GenerateIsInitialized(printer, MEMOIZE);
+ GenerateIsInitialized(printer);
GenerateMessageSerializationMethods(printer);
}
@@ -509,78 +466,39 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
// Carefully initialize the default instance in such a way that it doesn't
// conflict with other initialization.
printer->Print(
- "private static final $classname$ defaultInstance;\n",
+ "private static final $classname$ DEFAULT_INSTANCE;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "static {\n"
- " defaultInstance = new $classname$();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- // LITE_RUNTIME only has one constructor.
- printer->Print(
- "static {\n"
- " defaultInstance = new $classname$(\n"
- " com.google.protobuf.Internal\n"
- " .EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
- "}\n"
- "\n",
- "classname", descriptor_->name());
- }
+ printer->Print(
+ "static {\n"
+ " DEFAULT_INSTANCE = new $classname$();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
printer->Print(
"public static $classname$ getDefaultInstance() {\n"
- " return defaultInstance;\n"
+ " return DEFAULT_INSTANCE;\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
- if (HasDescriptorMethods(descriptor_)) {
- // LITE_RUNTIME implements this at the GeneratedMessageLite level.
- printer->Print(
- "public $classname$ getDefaultInstanceForType() {\n"
- " return defaultInstance;\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- // LITE_RUNTIME uses this to implement the *ForType methods at the
- // GeneratedMessageLite level.
- printer->Print(
- "static {"
- " com.google.protobuf.GeneratedMessageLite.onLoad(\n"
- " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n"
- " .PrototypeHolder<$classname$, Builder>(\n"
- " defaultInstance, PARSER));"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
+ GenerateParser(printer);
- // Extensions must be declared after the defaultInstance is initialized
- // because the defaultInstance is used by the extension to lazily retrieve
+ printer->Print(
+ "public $classname$ getDefaultInstanceForType() {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+ // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
// the outer class's FileDescriptor.
for (int i = 0; i < descriptor_->extension_count(); i++) {
ImmutableExtensionGenerator(descriptor_->extension(i), context_)
.Generate(printer);
}
- // Some fields also have static members that must be initialized after we
- // have the default instance available.
- printer->Print(
- "static {\n");
- printer->Indent();
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i))
- .GenerateStaticInitializationCode(printer);
- }
- printer->Outdent();
- printer->Print(
- "}\n");
-
printer->Outdent();
printer->Print("}\n\n");
}
@@ -617,35 +535,17 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
if (descriptor_->options().message_set_wire_format()) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "com.google.protobuf.GeneratedMessage\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter\n"
- " extensionWriter = newMessageSetExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- printer->Print(
- "com.google.protobuf.GeneratedMessageLite\n"
- " .ExtendableMessage<$classname$, $classname$.Builder>\n"
- " .ExtensionWriter extensionWriter =\n"
- " newMessageSetExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
+ printer->Print(
+ "com.google.protobuf.GeneratedMessage\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newMessageSetExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
} else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "com.google.protobuf.GeneratedMessage\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter\n"
- " extensionWriter = newExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- printer->Print(
- "com.google.protobuf.GeneratedMessageLite\n"
- " .ExtendableMessage<$classname$, $classname$.Builder>\n"
- " .ExtensionWriter extensionWriter =\n"
- " newExtensionWriter();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
+ printer->Print(
+ "com.google.protobuf.GeneratedMessage\n"
+ " .ExtendableMessage<$classname$>.ExtensionWriter\n"
+ " extensionWriter = newExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
}
}
@@ -665,8 +565,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()
- && HasDescriptorMethods(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()) {
printer->Print(
"unknownFields.writeAsMessageSetTo(output);\n");
} else {
@@ -702,8 +601,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
if (PreserveUnknownFields(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()
- && HasDescriptorMethods(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()) {
printer->Print(
"size += unknownFields.getSerializedSizeAsMessageSet();\n");
} else {
@@ -800,609 +698,115 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
// ===================================================================
void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- // LITE_RUNTIME implements this at the GeneratedMessageLite level.
- printer->Print(
- "public Builder newBuilderForType() { return newBuilder(); }\n");
- }
+ // LITE_RUNTIME implements this at the GeneratedMessageLite level.
+ printer->Print(
+ "public Builder newBuilderForType() { return newBuilder(); }\n");
printer->Print(
"public static Builder newBuilder() {\n"
- " return defaultInstance.toBuilder();\n"
+ " return DEFAULT_INSTANCE.toBuilder();\n"
"}\n"
"public static Builder newBuilder($classname$ prototype) {\n"
- " return defaultInstance.toBuilder().mergeFrom(prototype);\n"
+ " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
"}\n"
"public Builder toBuilder() {\n"
- " return this == defaultInstance\n"
+ " return this == DEFAULT_INSTANCE\n"
" ? new Builder() : new Builder().mergeFrom(this);\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
- if (HasNestedBuilders(descriptor_)) {
- printer->Print(
- "@java.lang.Override\n"
- "protected Builder newBuilderForType(\n"
- " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
- " Builder builder = new Builder(parent);\n"
- " return builder;\n"
- "}\n");
- }
-
- WriteMessageDocComment(printer, descriptor_);
-
- if (descriptor_->extension_range_count() > 0) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
- " $classname$, Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- } else {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n"
- " $classname$, Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- }
- } else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- } else {
- printer->Print(
- "public static final class Builder extends\n"
- " com.google.protobuf.GeneratedMessageLite.Builder<\n"
- " $classname$, Builder>\n"
- " implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
- "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
- }
- }
- printer->Indent();
-
- GenerateDescriptorMethods(printer, true);
- GenerateCommonBuilderMethods(printer);
-
- if (HasGeneratedMethods(descriptor_)) {
- GenerateIsInitialized(printer, DONT_MEMOIZE);
- GenerateBuilderParsingMethods(printer);
- }
-
- // oneof
- map<string, string> vars;
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- vars["oneof_name"] = context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name;
- vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->capitalized_name;
- vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
- // oneofCase_ and oneof_
- printer->Print(vars,
- "private int $oneof_name$Case_ = 0;\n"
- "private java.lang.Object $oneof_name$_;\n");
- // oneofCase() and clearOneof()
- printer->Print(vars,
- "public $oneof_capitalized_name$Case\n"
- " get$oneof_capitalized_name$Case() {\n"
- " return $oneof_capitalized_name$Case.valueOf(\n"
- " $oneof_name$Case_);\n"
- "}\n"
- "\n"
- "public Builder clear$oneof_capitalized_name$() {\n"
- " $oneof_name$Case_ = 0;\n"
- " $oneof_name$_ = null;\n");
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(" onChanged();\n");
- }
- printer->Print(
- " return this;\n"
- "}\n"
- "\n");
- }
-
- if (GenerateHasBits(descriptor_)) {
- // Integers for bit fields.
- int totalBits = 0;
- for (int i = 0; i < descriptor_->field_count(); i++) {
- totalBits += field_generators_.get(descriptor_->field(i))
- .GetNumBitsForBuilder();
- }
- int totalInts = (totalBits + 31) / 32;
- for (int i = 0; i < totalInts; i++) {
- printer->Print("private int $bit_field_name$;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- }
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- printer->Print("\n");
- field_generators_.get(descriptor_->field(i))
- .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",
- "full_name", descriptor_->full_name());
-
- printer->Outdent();
- printer->Print("}\n");
+ "@java.lang.Override\n"
+ "protected Builder newBuilderForType(\n"
+ " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+ " Builder builder = new Builder(parent);\n"
+ " return builder;\n"
+ "}\n");
+
+ MessageBuilderGenerator builderGenerator(descriptor_, context_);
+ builderGenerator.Generate(printer);
}
void ImmutableMessageGenerator::
-GenerateDescriptorMethods(io::Printer* printer, bool is_builder) {
- if (HasDescriptorMethods(descriptor_)) {
- if (!descriptor_->options().no_standard_descriptor_accessor()) {
- printer->Print(
- "public static final com.google.protobuf.Descriptors.Descriptor\n"
- " getDescriptor() {\n"
- " return $fileclass$.internal_$identifier$_descriptor;\n"
- "}\n"
- "\n",
- "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
- "identifier", UniqueFileScopeIdentifier(descriptor_));
- }
- 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 internalGet$capitalized_name$();\n",
- "number", SimpleItoa(field->number()),
- "capitalized_name", info->capitalized_name);
- }
- printer->Print(
- "default:\n"
- " throw new RuntimeException(\n"
- " \"Invalid map field number: \" + number);\n");
- printer->Outdent();
- printer->Outdent();
- printer->Print(
- " }\n"
- "}\n");
- if (is_builder) {
- printer->Print(
- "@SuppressWarnings({\"rawtypes\"})\n"
- "protected com.google.protobuf.MapField internalGetMutableMapField(\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 internalGetMutable$capitalized_name$();\n",
- "number", SimpleItoa(field->number()),
- "capitalized_name", info->capitalized_name);
- }
- printer->Print(
- "default:\n"
- " throw new RuntimeException(\n"
- " \"Invalid map field number: \" + number);\n");
- printer->Outdent();
- printer->Outdent();
- printer->Print(
- " }\n"
- "}\n");
- }
- }
+GenerateDescriptorMethods(io::Printer* printer) {
+ if (!descriptor_->options().no_standard_descriptor_accessor()) {
printer->Print(
- "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
- " internalGetFieldAccessorTable() {\n"
- " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
- " .ensureFieldAccessorsInitialized(\n"
- " $classname$.class, $classname$.Builder.class);\n"
+ "public static final com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptor() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
"}\n"
"\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_),
"fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
}
-}
-
-// ===================================================================
-
-void ImmutableMessageGenerator::
-GenerateCommonBuilderMethods(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "// Construct using $classname$.newBuilder()\n"
- "private Builder() {\n"
- " maybeForceBuilderInitialization();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
- printer->Print(
- "private Builder(\n"
- " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
- " super(parent);\n"
- " maybeForceBuilderInitialization();\n"
- "}\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- // LITE runtime passes along the default instance to implement
- // getDefaultInstanceForType() at the GeneratedMessageLite level.
- printer->Print(
- "// Construct using $classname$.newBuilder()\n"
- "private Builder() {\n"
- " super(defaultInstance);\n"
- " maybeForceBuilderInitialization();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(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 (HasNestedBuilders(descriptor_)) {
+ if (!map_fields.empty()) {
printer->Print(
- "private void maybeForceBuilderInitialization() {\n"
- " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
-
+ "@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 < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(descriptor_->field(i))
- .GenerateFieldBuilderInitializationCode(printer);
- }
+ 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 internalGet$capitalized_name$();\n",
+ "number", SimpleItoa(field->number()),
+ "capitalized_name", info->capitalized_name);
}
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
printer->Outdent();
printer->Outdent();
-
- printer->Print(
- " }\n"
- "}\n");
- } else {
- printer->Print(
- "private void maybeForceBuilderInitialization() {\n"
- "}\n");
- }
-
- printer->Print(
- "public Builder clear() {\n"
- " super.clear();\n");
-
- printer->Indent();
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(descriptor_->field(i))
- .GenerateBuilderClearCode(printer);
- }
- }
-
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print(
- "$oneof_name$Case_ = 0;\n"
- "$oneof_name$_ = null;\n",
- "oneof_name", context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name);
- }
-
- printer->Outdent();
-
- printer->Print(
- " return this;\n"
- "}\n"
- "\n");
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public com.google.protobuf.Descriptors.Descriptor\n"
- " getDescriptorForType() {\n"
- " return $fileclass$.internal_$identifier$_descriptor;\n"
- "}\n"
- "\n",
- "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
- "identifier", UniqueFileScopeIdentifier(descriptor_));
-
- // LITE runtime implements this in GeneratedMessageLite.
- printer->Print(
- "public $classname$ getDefaultInstanceForType() {\n"
- " return $classname$.getDefaultInstance();\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
-
- // -----------------------------------------------------------------
-
- if (HasDescriptorMethods(descriptor_)) {
- // LITE implements build in GeneratedMessageLite to save methods.
printer->Print(
- "public $classname$ build() {\n"
- " $classname$ result = buildPartial();\n"
- " if (!result.isInitialized()) {\n"
- " throw newUninitializedMessageException(result);\n"
- " }\n"
- " return result;\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public $classname$ buildPartial() {\n"
- " $classname$ result = new $classname$(this);\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- // LITE_RUNTIME only provides a single message constructor.
- printer->Print(
- "public $classname$ buildPartial() {\n"
- " $classname$ result = new $classname$(\n"
- " com.google.protobuf.Internal\n"
- " .EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
- " result.unknownFields = this.unknownFields;\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- " result.extensions = this.buildExtensions();\n");
- }
- }
-
- printer->Indent();
-
- int totalBuilderBits = 0;
- int totalMessageBits = 0;
- for (int i = 0; i < descriptor_->field_count(); i++) {
- const ImmutableFieldGenerator& field =
- field_generators_.get(descriptor_->field(i));
- totalBuilderBits += field.GetNumBitsForBuilder();
- totalMessageBits += field.GetNumBitsForMessage();
- }
- int totalBuilderInts = (totalBuilderBits + 31) / 32;
- int totalMessageInts = (totalMessageBits + 31) / 32;
-
- if (GenerateHasBits(descriptor_)) {
- // Local vars for from and to bit fields to avoid accessing the builder and
- // message over and over for these fields. Seems to provide a slight
- // perforamance improvement in micro benchmark and this is also what proto1
- // code does.
- for (int i = 0; i < totalBuilderInts; i++) {
- printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- for (int i = 0; i < totalMessageInts; i++) {
- printer->Print("int to_$bit_field_name$ = 0;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- }
-
- // Output generation code for each field.
- for (int i = 0; i < descriptor_->field_count(); i++) {
- field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
- }
-
- if (GenerateHasBits(descriptor_)) {
- // Copy the bit field results to the generated message
- for (int i = 0; i < totalMessageInts; i++) {
- printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
- "bit_field_name", GetBitFieldName(i));
- }
- }
-
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
- "oneof_name", context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name);
- }
-
- printer->Outdent();
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- " onBuilt();\n");
+ " }\n"
+ "}\n");
}
-
printer->Print(
- " return result;\n"
+ "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+ " internalGetFieldAccessorTable() {\n"
+ " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+ " .ensureFieldAccessorsInitialized(\n"
+ " $classname$.class, $classname$.Builder.class);\n"
"}\n"
"\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
- // -----------------------------------------------------------------
-
- if (HasGeneratedMethods(descriptor_)) {
- // MergeFrom(Message other) requires the ability to distinguish the other
- // messages type by its descriptor.
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
- " if (other instanceof $classname$) {\n"
- " return mergeFrom(($classname$)other);\n"
- " } else {\n"
- " super.mergeFrom(other);\n"
- " return this;\n"
- " }\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
-
- printer->Print(
- "public Builder mergeFrom($classname$ other) {\n"
- // Optimization: If other is the default instance, we know none of its
- // fields are set so we can skip the merge.
- " if (other == $classname$.getDefaultInstance()) return this;\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- printer->Indent();
-
- for (int i = 0; i < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(
- descriptor_->field(i)).GenerateMergingCode(printer);
- }
- }
-
- // Merge oneof fields.
- for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
- printer->Print(
- "switch (other.get$oneof_capitalized_name$Case()) {\n",
- "oneof_capitalized_name",
- context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->capitalized_name);
- printer->Indent();
- for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
- const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
- printer->Print(
- "case $field_name$: {\n",
- "field_name",
- ToUpper(field->name()));
- printer->Indent();
- field_generators_.get(field).GenerateMergingCode(printer);
- printer->Print(
- "break;\n");
- printer->Outdent();
- printer->Print(
- "}\n");
- }
- printer->Print(
- "case $cap_oneof_name$_NOT_SET: {\n"
- " break;\n"
- "}\n",
- "cap_oneof_name",
- ToUpper(context_->GetOneofGeneratorInfo(
- descriptor_->oneof_decl(i))->name));
- printer->Outdent();
- printer->Print(
- "}\n");
- }
-
- printer->Outdent();
-
- // if message type has extensions
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- " this.mergeExtensionFields(other);\n");
- }
-
- if (PreserveUnknownFields(descriptor_)) {
- printer->Print(
- " this.mergeUnknownFields(other.unknownFields);\n");
- }
-
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(" onChanged();\n");
- }
-
- printer->Print(
- " return this;\n"
- "}\n"
- "\n");
- }
-}
-
-// ===================================================================
-
-void ImmutableMessageGenerator::
-GenerateBuilderParsingMethods(io::Printer* printer) {
- if (HasDescriptorMethods(descriptor_)) {
- // LITE_RUNTIME implements this at the GeneratedMessageLite level.
- 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_));
- }
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
}
// ===================================================================
void ImmutableMessageGenerator::GenerateIsInitialized(
- io::Printer* printer, UseMemoization useMemoization) {
- // LITE_RUNTIME avoids generating isInitialized if it's not needed.
- if (!HasDescriptorMethods(descriptor_)
- && !HasRequiredFields(descriptor_)) {
- return;
- }
-
- bool memoization = useMemoization == MEMOIZE;
- if (memoization) {
- // Memoizes whether the protocol buffer is fully initialized (has all
- // required fields). -1 means not yet computed. 0 means false and 1 means
- // true.
- printer->Print(
- "private byte memoizedIsInitialized = -1;\n");
- }
+ io::Printer* printer) {
+ // Memoizes whether the protocol buffer is fully initialized (has all
+ // required fields). -1 means not yet computed. 0 means false and 1 means
+ // true.
+ printer->Print(
+ "private byte memoizedIsInitialized = -1;\n");
printer->Print(
"public final boolean isInitialized() {\n");
printer->Indent();
- if (memoization) {
- // Don't directly compare to -1 to avoid an Android x86 JIT bug.
- printer->Print(
- "byte isInitialized = memoizedIsInitialized;\n"
- "if (isInitialized == 1) return true;\n"
- "if (isInitialized == 0) return false;\n"
- "\n");
- }
+ // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+ printer->Print(
+ "byte isInitialized = memoizedIsInitialized;\n"
+ "if (isInitialized == 1) return true;\n"
+ "if (isInitialized == 0) return false;\n"
+ "\n");
// Check that all required fields in this message are set.
// TODO(kenton): We can optimize this when we switch to putting all the
@@ -1414,11 +818,10 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
if (field->is_required()) {
printer->Print(
"if (!has$name$()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
"}\n",
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
}
}
@@ -1432,13 +835,12 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
case FieldDescriptor::LABEL_REQUIRED:
printer->Print(
"if (!get$name$().isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
"}\n",
"type", name_resolver_->GetImmutableClassName(
field->message_type()),
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
break;
case FieldDescriptor::LABEL_OPTIONAL:
if (!SupportFieldPresence(descriptor_->file()) &&
@@ -1457,38 +859,35 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
}
printer->Print(
" if (!get$name$().isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
" }\n"
"}\n",
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
break;
case FieldDescriptor::LABEL_REPEATED:
if (IsMapEntry(field->message_type())) {
printer->Print(
"for ($type$ item : get$name$().values()) {\n"
" if (!item.isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
" }\n"
"}\n",
"type", MapValueImmutableClassdName(field->message_type(),
name_resolver_),
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
} else {
printer->Print(
"for (int i = 0; i < get$name$Count(); i++) {\n"
" if (!get$name$(i).isInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
" }\n"
"}\n",
"type", name_resolver_->GetImmutableClassName(
field->message_type()),
- "name", info->capitalized_name,
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "name", info->capitalized_name);
}
break;
}
@@ -1498,18 +897,15 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"if (!extensionsAreInitialized()) {\n"
- " $memoize$\n"
+ " memoizedIsInitialized = 0;\n"
" return false;\n"
- "}\n",
- "memoize", memoization ? "memoizedIsInitialized = 0;" : "");
+ "}\n");
}
printer->Outdent();
- if (memoization) {
- printer->Print(
- " memoizedIsInitialized = 1;\n");
- }
+ printer->Print(
+ " memoizedIsInitialized = 1;\n");
printer->Print(
" return true;\n"
@@ -1575,12 +971,10 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Print(
"result = result && unknownFields.equals(other.unknownFields);\n");
}
- if (HasDescriptorMethods(descriptor_)) {
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- "result = result &&\n"
- " getExtensionFields().equals(other.getExtensionFields());\n");
- }
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "result = result &&\n"
+ " getExtensionFields().equals(other.getExtensionFields());\n");
}
printer->Print(
"return result;\n");
@@ -1603,14 +997,7 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
"}\n"
"int hash = 41;\n");
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
- } else {
- // Include the hash of the class so that two objects with different types
- // but the same field values will probably have different hashes.
- printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
- }
+ printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
@@ -1628,11 +1015,9 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Print("}\n");
}
}
- if (HasDescriptorMethods(descriptor_)) {
- if (descriptor_->extension_range_count() > 0) {
- printer->Print(
- "hash = hashFields(hash, getExtensionFields());\n");
- }
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "hash = hashFields(hash, getExtensionFields());\n");
}
printer->Print(
@@ -1675,13 +1060,8 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Indent();
// Initialize all fields to default.
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "this();\n");
- } else {
- // LITE_RUNTIME only has one constructor.
- GenerateInitializers(printer);
- }
+ printer->Print(
+ "this();\n");
// Use builder bits to track mutable repeated fields.
int totalBuilderBits = 0;
@@ -1697,15 +1077,9 @@ GenerateParsingConstructor(io::Printer* printer) {
}
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(
+ "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
}
printer->Print(
@@ -1728,29 +1102,14 @@ GenerateParsingConstructor(io::Printer* printer) {
" 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");
- }
+ 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"
@@ -1825,18 +1184,9 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Print("this.unknownFields = unknownFields.build();\n");
}
- if (!HasDescriptorMethods(descriptor_)) {
- // LITE runtime uses a static method to reduce method count.
- if (descriptor_->extension_range_count() > 0) {
- // Make extensions immutable.
- printer->Print(
- "makeExtensionsImmutable(extensions);\n");
- }
- } else {
- // Make extensions immutable.
- printer->Print(
- "makeExtensionsImmutable();\n");
- }
+ // Make extensions immutable.
+ printer->Print(
+ "makeExtensionsImmutable();\n");
printer->Outdent();
printer->Outdent();
@@ -1874,9 +1224,9 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
" }\n",
"classname", descriptor_->name());
} else {
- // When parsing constructor isn't generated, use builder to parse messages.
- // Note, will fallback to use reflection based mergeFieldFrom() in
- // AbstractMessage.Builder.
+ // When parsing constructor isn't generated, use builder to parse
+ // messages. Note, will fallback to use reflection based mergeFieldFrom()
+ // in AbstractMessage.Builder.
printer->Indent();
printer->Print(
"Builder builder = newBuilder();\n"
@@ -1886,7 +1236,8 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
" throw e.setUnfinishedMessage(builder.buildPartial());\n"
"} catch (java.io.IOException e) {\n"
" throw new com.google.protobuf.InvalidProtocolBufferException(\n"
- " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n"
+ " e.getMessage()).setUnfinishedMessage(\n"
+ " builder.buildPartial());\n"
"}\n"
"return builder.buildPartial();\n");
printer->Outdent();
@@ -1898,16 +1249,13 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
"};\n"
"\n");
- if (HasDescriptorMethods(descriptor_)) {
- // LITE_RUNTIME implements this at the GeneratedMessageLite level.
- printer->Print(
- "@java.lang.Override\n"
- "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
- " return PARSER;\n"
- "}\n"
- "\n",
- "classname", descriptor_->name());
- }
+ printer->Print(
+ "@java.lang.Override\n"
+ "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
+ " return PARSER;\n"
+ "}\n"
+ "\n",
+ "classname", descriptor_->name());
}
// ===================================================================
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 58dd5f99..c3c37765 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -102,10 +102,6 @@ class ImmutableMessageGenerator : public MessageGenerator {
virtual int GenerateStaticVariableInitializers(io::Printer* printer);
private:
- enum UseMemoization {
- MEMOIZE,
- DONT_MEMOIZE
- };
void GenerateFieldAccessorTable(io::Printer* printer);
@@ -120,11 +116,8 @@ class ImmutableMessageGenerator : public MessageGenerator {
io::Printer* printer, const Descriptor::ExtensionRange* range);
void GenerateBuilder(io::Printer* printer);
- void GenerateCommonBuilderMethods(io::Printer* printer);
- void GenerateDescriptorMethods(io::Printer* printer, bool is_builder);
- void GenerateBuilderParsingMethods(io::Printer* printer);
- void GenerateIsInitialized(io::Printer* printer,
- UseMemoization useMemoization);
+ void GenerateIsInitialized(io::Printer* printer);
+ void GenerateDescriptorMethods(io::Printer* printer);
void GenerateInitializers(io::Printer* printer);
void GenerateEqualsAndHashCode(io::Printer* printer);
void GenerateParser(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
new file mode 100644
index 00000000..72694119
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -0,0 +1,661 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_builder.h>
+
+#include <algorithm>
+#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>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+ return SupportFieldPresence(descriptor->file()) ||
+ HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+MessageBuilderGenerator::MessageBuilderGenerator(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor), context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_NE(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+MessageBuilderGenerator::~MessageBuilderGenerator() {}
+
+void MessageBuilderGenerator::
+Generate(io::Printer* printer) {
+ WriteMessageDocComment(printer, descriptor_);
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n"
+ " $classname$, Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+ } else {
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_));
+ }
+ printer->Indent();
+
+ GenerateDescriptorMethods(printer);
+ GenerateCommonBuilderMethods(printer);
+
+ if (HasGeneratedMethods(descriptor_)) {
+ GenerateIsInitialized(printer);
+ GenerateBuilderParsingMethods(printer);
+ }
+
+ // oneof
+ map<string, string> vars;
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name;
+ vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name;
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ // oneofCase() and clearOneof()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ " get$oneof_capitalized_name$Case() {\n"
+ " return $oneof_capitalized_name$Case.valueOf(\n"
+ " $oneof_name$Case_);\n"
+ "}\n"
+ "\n"
+ "public Builder clear$oneof_capitalized_name$() {\n"
+ " $oneof_name$Case_ = 0;\n"
+ " $oneof_name$_ = null;\n");
+ printer->Print(" onChanged();\n");
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
+ if (GenerateHasBits(descriptor_)) {
+ // Integers for bit fields.
+ int totalBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ totalBits += field_generators_.get(descriptor_->field(i))
+ .GetNumBitsForBuilder();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .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",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateDescriptorMethods(io::Printer* printer) {
+ if (!descriptor_->options().no_standard_descriptor_accessor()) {
+ printer->Print(
+ "public static final com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptor() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+ }
+ 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 internalGet$capitalized_name$();\n",
+ "number", SimpleItoa(field->number()),
+ "capitalized_name", info->capitalized_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(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMutableMapField(\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 internalGetMutable$capitalized_name$();\n",
+ "number", SimpleItoa(field->number()),
+ "capitalized_name", info->capitalized_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"
+ " return $fileclass$.internal_$identifier$_fieldAccessorTable\n"
+ " .ensureFieldAccessorsInitialized(\n"
+ " $classname$.class, $classname$.Builder.class);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+GenerateCommonBuilderMethods(io::Printer* printer) {
+ printer->Print(
+ "// Construct using $classname$.newBuilder()\n"
+ "private Builder() {\n"
+ " maybeForceBuilderInitialization();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "private Builder(\n"
+ " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n"
+ " super(parent);\n"
+ " maybeForceBuilderInitialization();\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "private void maybeForceBuilderInitialization() {\n"
+ " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n");
+
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateFieldBuilderInitializationCode(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ "}\n");
+
+ printer->Print(
+ "public Builder clear() {\n"
+ " super.clear();\n");
+
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateBuilderClearCode(printer);
+ }
+ }
+
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "$oneof_name$Case_ = 0;\n"
+ "$oneof_name$_ = null;\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name);
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "public com.google.protobuf.Descriptors.Descriptor\n"
+ " getDescriptorForType() {\n"
+ " return $fileclass$.internal_$identifier$_descriptor;\n"
+ "}\n"
+ "\n",
+ "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
+ "identifier", UniqueFileScopeIdentifier(descriptor_));
+
+ // LITE runtime implements this in GeneratedMessageLite.
+ printer->Print(
+ "public $classname$ getDefaultInstanceForType() {\n"
+ " return $classname$.getDefaultInstance();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public $classname$ build() {\n"
+ " $classname$ result = buildPartial();\n"
+ " if (!result.isInitialized()) {\n"
+ " throw newUninitializedMessageException(result);\n"
+ " }\n"
+ " return result;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public $classname$ buildPartial() {\n"
+ " $classname$ result = new $classname$(this);\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Indent();
+
+ int totalBuilderBits = 0;
+ int totalMessageBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const ImmutableFieldGenerator& field =
+ field_generators_.get(descriptor_->field(i));
+ totalBuilderBits += field.GetNumBitsForBuilder();
+ totalMessageBits += field.GetNumBitsForMessage();
+ }
+ int totalBuilderInts = (totalBuilderBits + 31) / 32;
+ int totalMessageInts = (totalMessageBits + 31) / 32;
+
+ if (GenerateHasBits(descriptor_)) {
+ // Local vars for from and to bit fields to avoid accessing the builder and
+ // message over and over for these fields. Seems to provide a slight
+ // perforamance improvement in micro benchmark and this is also what proto1
+ // code does.
+ for (int i = 0; i < totalBuilderInts; i++) {
+ printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ for (int i = 0; i < totalMessageInts; i++) {
+ printer->Print("int to_$bit_field_name$ = 0;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ // Output generation code for each field.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer);
+ }
+
+ if (GenerateHasBits(descriptor_)) {
+ // Copy the bit field results to the generated message
+ for (int i = 0; i < totalMessageInts; i++) {
+ printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n",
+ "oneof_name", context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name);
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " onBuilt();\n");
+
+ printer->Print(
+ " return result;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // -----------------------------------------------------------------
+
+ if (HasGeneratedMethods(descriptor_)) {
+ printer->Print(
+ "public Builder mergeFrom(com.google.protobuf.Message other) {\n"
+ " if (other instanceof $classname$) {\n"
+ " return mergeFrom(($classname$)other);\n"
+ " } else {\n"
+ " super.mergeFrom(other);\n"
+ " return this;\n"
+ " }\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "public Builder mergeFrom($classname$ other) {\n"
+ // Optimization: If other is the default instance, we know none of its
+ // fields are set so we can skip the merge.
+ " if (other == $classname$.getDefaultInstance()) return this;\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(
+ descriptor_->field(i)).GenerateMergingCode(printer);
+ }
+ }
+
+ // Merge oneof fields.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+ printer->Print(
+ "switch (other.get$oneof_capitalized_name$Case()) {\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name);
+ printer->Indent();
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+ printer->Print(
+ "case $field_name$: {\n",
+ "field_name",
+ ToUpper(field->name()));
+ printer->Indent();
+ field_generators_.get(field).GenerateMergingCode(printer);
+ printer->Print(
+ "break;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+ printer->Print(
+ "case $cap_oneof_name$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ "cap_oneof_name",
+ ToUpper(context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name));
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+
+ printer->Outdent();
+
+ // if message type has extensions
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ " this.mergeExtensionFields(other);\n");
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ " this.mergeUnknownFields(other.unknownFields);\n");
+ }
+
+ printer->Print(
+ " onChanged();\n");
+
+ printer->Print(
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+}
+
+// ===================================================================
+
+void MessageBuilderGenerator::
+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 MessageBuilderGenerator::GenerateIsInitialized(
+ io::Printer* printer) {
+ printer->Print(
+ "public final boolean isInitialized() {\n");
+ printer->Indent();
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+ if (field->is_required()) {
+ printer->Print(
+ "if (!has$name$()) {\n"
+ " return false;\n"
+ "}\n",
+ "name", info->capitalized_name);
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(field->message_type())) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_REQUIRED:
+ printer->Print(
+ "if (!get$name$().isInitialized()) {\n"
+ " return false;\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ 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 (!get$name$().isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ if (IsMapEntry(field->message_type())) {
+ printer->Print(
+ "for ($type$ item : get$name$().values()) {\n"
+ " if (!item.isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type", MapValueImmutableClassdName(field->message_type(),
+ name_resolver_),
+ "name", info->capitalized_name);
+ } else {
+ printer->Print(
+ "for (int i = 0; i < get$name$Count(); i++) {\n"
+ " if (!get$name$(i).isInitialized()) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ }
+ break;
+ }
+ }
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!extensionsAreInitialized()) {\n"
+ " return false;\n"
+ "}\n");
+ }
+
+ printer->Outdent();
+
+ printer->Print(
+ " return true;\n"
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_message_builder.h b/src/google/protobuf/compiler/java/java_message_builder.h
new file mode 100644
index 00000000..015ea062
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder.h
@@ -0,0 +1,86 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderGenerator {
+ public:
+ explicit MessageBuilderGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~MessageBuilderGenerator();
+
+ virtual void Generate(io::Printer* printer);
+
+ private:
+ void GenerateCommonBuilderMethods(io::Printer* printer);
+ void GenerateDescriptorMethods(io::Printer* printer);
+ void GenerateBuilderParsingMethods(io::Printer* printer);
+ void GenerateIsInitialized(io::Printer* printer);
+
+ const Descriptor* descriptor_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
new file mode 100644
index 00000000..8719d00d
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
@@ -0,0 +1,192 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
+
+#include <algorithm>
+#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>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+ return SupportFieldPresence(descriptor->file()) ||
+ HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+MessageBuilderLiteGenerator::MessageBuilderLiteGenerator(
+ const Descriptor* descriptor, Context* context)
+ : descriptor_(descriptor), context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_EQ(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {}
+
+void MessageBuilderLiteGenerator::
+Generate(io::Printer* printer) {
+ WriteMessageDocComment(printer, descriptor_);
+ printer->Print(
+ "public static final class Builder extends\n"
+ " com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n"
+ " $classname$, Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_),
+ "extra_interfaces", ExtraBuilderInterfaces(descriptor_),
+ "extendible",
+ descriptor_->extension_range_count() > 0 ? "Extendable" : "");
+ printer->Indent();
+
+ GenerateCommonBuilderMethods(printer);
+
+ // oneof
+ map<string, string> vars;
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name;
+ vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name;
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+
+ // oneofCase() and clearOneof()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ " get$oneof_capitalized_name$Case() {\n"
+ " return instance.get$oneof_capitalized_name$Case();\n"
+ "}\n"
+ "\n"
+ "public Builder clear$oneof_capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$oneof_capitalized_name$();\n"
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
+ if (GenerateHasBits(descriptor_)) {
+ // Integers for bit fields.
+ int totalBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ totalBits += field_generators_.get(descriptor_->field(i))
+ .GetNumBitsForBuilder();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .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",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void MessageBuilderLiteGenerator::
+GenerateCommonBuilderMethods(io::Printer* printer) {
+ printer->Print(
+ "// Construct using $classname$.newBuilder()\n"
+ "private Builder() {\n"
+ " super(DEFAULT_INSTANCE);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+// ===================================================================
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.h b/src/google/protobuf/compiler/java/java_message_builder_lite.h
new file mode 100644
index 00000000..8597b2e6
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.h
@@ -0,0 +1,83 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class MessageBuilderLiteGenerator {
+ public:
+ explicit MessageBuilderLiteGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~MessageBuilderLiteGenerator();
+
+ virtual void Generate(io::Printer* printer);
+
+ private:
+ void GenerateCommonBuilderMethods(io::Printer* printer);
+
+ const Descriptor* descriptor_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index a2d12a38..b180b4a7 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -157,11 +157,9 @@ GenerateInterfaceMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$();\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n");
}
void ImmutableMessageFieldGenerator::
@@ -182,14 +180,12 @@ GenerateMembers(io::Printer* printer) const {
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder "
- "get$capitalized_name$OrBuilder() {\n"
- " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder "
+ "get$capitalized_name$OrBuilder() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
} else {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -202,14 +198,12 @@ GenerateMembers(io::Printer* printer) const {
" return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder "
- "get$capitalized_name$OrBuilder() {\n"
- " return get$capitalized_name$();\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder "
+ "get$capitalized_name$OrBuilder() {\n"
+ " return get$capitalized_name$();\n"
+ "}\n");
}
}
@@ -217,19 +211,15 @@ void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
io::Printer* printer,
const char* regular_case,
const char* nested_builder_case) const {
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_, "if ($name$Builder_ == null) {\n");
- printer->Indent();
- printer->Print(variables_, regular_case);
- printer->Outdent();
- printer->Print("} else {\n");
- printer->Indent();
- printer->Print(variables_, nested_builder_case);
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(variables_, regular_case);
- }
+ printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+ printer->Indent();
+ printer->Print(variables_, regular_case);
+ printer->Outdent();
+ printer->Print("} else {\n");
+ printer->Indent();
+ printer->Print(variables_, nested_builder_case);
+ printer->Outdent();
+ printer->Print("}\n");
}
void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
@@ -260,14 +250,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"private $type$ $name$_ = null;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
+ printer->Print(variables_,
// If this builder is non-null, it is used and the other fields are
// ignored.
"private com.google.protobuf.SingleFieldBuilder<\n"
" $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
"\n");
- }
// The comments above the methods below are based on a hypothetical
// field of type "Field" called "Field".
@@ -368,40 +356,38 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$clear_has_field_bit_builder$\n"
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
- " $set_has_field_bit_builder$\n"
- " $on_changed$\n"
- " return get$capitalized_name$FieldBuilder().getBuilder();\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n"
- " return $name$_ == null ?\n"
- " $type$.getDefaultInstance() : $name$_;\n"
- " }\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " get$capitalized_name$(),\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+ " $set_has_field_bit_builder$\n"
+ " $on_changed$\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " return $name$_ == null ?\n"
+ " $type$.getDefaultInstance() : $name$_;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " get$capitalized_name$(),\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void ImmutableMessageFieldGenerator::
@@ -557,16 +543,14 @@ GenerateMembers(io::Printer* printer) const {
" return $type$.getDefaultInstance();\n"
"}\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if ($has_oneof_case_message$) {\n"
- " return ($type$) $oneof_name$_;\n"
- " }\n"
- " return $type$.getDefaultInstance();\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
}
void ImmutableMessageOneofFieldGenerator::
@@ -574,14 +558,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
// When using nested-builders, the code initially works just like the
// non-nested builder case. It only creates a nested builder lazily on
// demand and then forever delegates to it after creation.
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;"
+ "\n");
// The comments above the methods below are based on a hypothetical
// field of type "Field" called "Field".
@@ -683,45 +665,43 @@ GenerateBuilderMembers(io::Printer* printer) const {
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
- " return get$capitalized_name$FieldBuilder().getBuilder();\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
- " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
- " return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n"
- " if ($has_oneof_case_message$) {\n"
- " return ($type$) $oneof_name$_;\n"
- " }\n"
- " return $type$.getDefaultInstance();\n"
- " }\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "private com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " if (!($has_oneof_case_message$)) {\n"
- " $oneof_name$_ = $type$.getDefaultInstance();\n"
- " }\n"
- " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " ($type$) $oneof_name$_,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $oneof_name$_ = null;\n"
- " }\n"
- " $set_oneof_case_message$;\n"
- " $on_changed$;\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+ " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
+ " return $name$Builder_.getMessageOrBuilder();\n"
+ " } else {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " if (!($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = $type$.getDefaultInstance();\n"
+ " }\n"
+ " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " ($type$) $oneof_name$_,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ " $on_changed$;\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void ImmutableMessageOneofFieldGenerator::
@@ -831,16 +811,15 @@ GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$int get$capitalized_name$Count();\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
- " get$capitalized_name$OrBuilderList();\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
- " int index);\n");
- }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index);\n");
}
void RepeatedImmutableMessageFieldGenerator::
@@ -882,19 +861,15 @@ void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition(
io::Printer* printer,
const char* regular_case,
const char* nested_builder_case) const {
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_, "if ($name$Builder_ == null) {\n");
- printer->Indent();
- printer->Print(variables_, regular_case);
- printer->Outdent();
- printer->Print("} else {\n");
- printer->Indent();
- printer->Print(variables_, nested_builder_case);
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(variables_, regular_case);
- }
+ printer->Print(variables_, "if ($name$Builder_ == null) {\n");
+ printer->Indent();
+ printer->Print(variables_, regular_case);
+ printer->Outdent();
+ printer->Print("} else {\n");
+ printer->Indent();
+ printer->Print(variables_, nested_builder_case);
+ printer->Outdent();
+ printer->Print("}\n");
}
void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction(
@@ -942,14 +917,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n"
"\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- printer->Print(variables_,
- // If this builder is non-null, it is used and the other fields are
- // ignored.
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
- "\n");
- }
+ printer->Print(variables_,
+ // If this builder is non-null, it is used and the other fields are
+ // ignored.
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n"
+ "\n");
// The comments above the methods below are based on a hypothetical
// repeated field of type "Field" called "RepeatedField".
@@ -1116,70 +1089,68 @@ GenerateBuilderMembers(io::Printer* printer) const {
"return this;\n");
- if (HasNestedBuilders(descriptor_->containing_type())) {
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
- " int index) {\n"
- " if ($name$Builder_ == null) {\n"
- " return $name$_.get(index);"
- " } else {\n"
- " return $name$Builder_.getMessageOrBuilder(index);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " if ($name$Builder_ == null) {\n"
+ " return $name$_.get(index);"
+ " } else {\n"
+ " return $name$Builder_.getMessageOrBuilder(index);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
- " get$capitalized_name$OrBuilderList() {\n"
- " if ($name$Builder_ != null) {\n"
- " return $name$Builder_.getMessageOrBuilderList();\n"
- " } else {\n"
- " return java.util.Collections.unmodifiableList($name$_);\n"
- " }\n"
- "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " if ($name$Builder_ != null) {\n"
+ " return $name$Builder_.getMessageOrBuilderList();\n"
+ " } else {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ " }\n"
+ "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
- " int index) {\n"
- " return get$capitalized_name$FieldBuilder().addBuilder(\n"
- " index, $type$.getDefaultInstance());\n"
- "}\n");
- WriteFieldDocComment(printer, descriptor_);
- printer->Print(variables_,
- "$deprecation$public java.util.List<$type$.Builder> \n"
- " get$capitalized_name$BuilderList() {\n"
- " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
- "}\n"
- "private com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder> \n"
- " get$capitalized_name$FieldBuilder() {\n"
- " if ($name$Builder_ == null) {\n"
- " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
- " $type$, $type$.Builder, $type$OrBuilder>(\n"
- " $name$_,\n"
- " $get_mutable_bit_builder$,\n"
- " getParentForChildren(),\n"
- " isClean());\n"
- " $name$_ = null;\n"
- " }\n"
- " return $name$Builder_;\n"
- "}\n");
- }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+ " int index) {\n"
+ " return get$capitalized_name$FieldBuilder().addBuilder(\n"
+ " index, $type$.getDefaultInstance());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$.Builder> \n"
+ " get$capitalized_name$BuilderList() {\n"
+ " return get$capitalized_name$FieldBuilder().getBuilderList();\n"
+ "}\n"
+ "private com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder> \n"
+ " get$capitalized_name$FieldBuilder() {\n"
+ " if ($name$Builder_ == null) {\n"
+ " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n"
+ " $type$, $type$.Builder, $type$OrBuilder>(\n"
+ " $name$_,\n"
+ " $get_mutable_bit_builder$,\n"
+ " getParentForChildren(),\n"
+ " isClean());\n"
+ " $name$_ = null;\n"
+ " }\n"
+ " return $name$Builder_;\n"
+ "}\n");
}
void RepeatedImmutableMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
new file mode 100644
index 00000000..8332202c
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -0,0 +1,944 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+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());
+ (*variables)["mutable_type"] =
+ name_resolver->GetMutableClassName(descriptor->message_type());
+ (*variables)["group_or_message"] =
+ (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
+ "Group" : "Message";
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ if (SupportFieldPresence(descriptor->file())) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != null";
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableMessageFieldLiteGenerator::
+ImmutableMessageFieldLiteGenerator(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_);
+}
+
+ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {}
+
+int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ // TODO(jonp): In the future, consider having a method specific to the
+ // interface so that builders can choose dynamically to either return a
+ // message or a nested builder, so that asking for the interface doesn't
+ // cause a message to ever be built.
+ if (SupportFieldPresence(descriptor_->file()) ||
+ descriptor_->containing_oneof() == NULL) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private $type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $name$_ != null;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
+ "}\n");
+ }
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $name$_ = value;\n"
+ " $set_has_field_bit_message$\n"
+ " }\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " $name$_ = builderForValue.build();\n"
+ " $set_has_field_bit_message$\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($name$_ != null &&\n"
+ " $name$_ != $type$.getDefaultInstance()) {\n"
+ " $name$_ =\n"
+ " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
+ " } else {\n"
+ " $name$_ = value;\n"
+ " }\n"
+ " $set_has_field_bit_message$\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {"
+ " $name$_ = null;\n"
+ " $clear_has_field_bit_message$\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+
+ // Field getField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ " }\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ printer->Print(variables_,
+ "get$capitalized_name$FieldBuilder();\n");
+ }
+}
+
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " merge$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$type$.Builder subBuilder = null;\n"
+ "if ($is_field_present_message$) {\n"
+ " subBuilder = $name$_.toBuilder();\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ }
+
+ printer->Print(variables_,
+ "if (subBuilder != null) {\n"
+ " subBuilder.mergeFrom($name$_);\n"
+ " $name$_ = subBuilder.buildPartial();\n"
+ "}\n"
+ "$set_has_field_bit_message$\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for messages.
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.write$group_or_message$($number$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+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$, get$capitalized_name$());\n"
+ "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableMessageFieldLiteGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+// ===================================================================
+
+ImmutableMessageOneofFieldLiteGenerator::
+ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableMessageFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableMessageOneofFieldLiteGenerator::
+~ImmutableMessageOneofFieldLiteGenerator() {}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($type$) $oneof_name$_;\n"
+ " }\n"
+ " return $type$.getDefaultInstance();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " $oneof_name$_ = value;\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " $oneof_name$_ = builderForValue.build();\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void merge$capitalized_name$($type$ value) {\n"
+ " if ($has_oneof_case_message$ &&\n"
+ " $oneof_name$_ != $type$.getDefaultInstance()) {\n"
+ " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n"
+ " .mergeFrom(value).buildPartial();\n"
+ " } else {\n"
+ " $oneof_name$_ = value;\n"
+ " }\n"
+ " $set_oneof_case_message$;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // field of type "Field" called "Field".
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ // boolean hasField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ // Field getField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ // Field.Builder setField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder setField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder mergeField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.merge$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Field.Builder clearField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "merge$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$type$.Builder subBuilder = null;\n"
+ "if ($has_oneof_case_message$) {\n"
+ " subBuilder = (($type$) $oneof_name$_).toBuilder();\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry);\n");
+ } else {
+ printer->Print(variables_,
+ "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ }
+
+ printer->Print(variables_,
+ "if (subBuilder != null) {\n"
+ " subBuilder.mergeFrom(($type$) $oneof_name$_);\n"
+ " $oneof_name$_ = subBuilder.buildPartial();\n"
+ "}\n");
+ printer->Print(variables_,
+ "$set_oneof_case_message$;\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+void ImmutableMessageOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableMessageFieldLiteGenerator::
+RepeatedImmutableMessageFieldLiteGenerator(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_);
+}
+
+RepeatedImmutableMessageFieldLiteGenerator::
+~RepeatedImmutableMessageFieldLiteGenerator() {}
+
+int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ // TODO(jonp): In the future, consider having methods specific to the
+ // interface so that builders can choose dynamically to either return a
+ // message or a nested builder, so that asking for the interface doesn't
+ // cause a message to ever be built.
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$type$> \n"
+ " get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
+ " get$capitalized_name$OrBuilderList() {\n"
+ " return $name$_;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+ " int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList($name$_);\n"
+ " }\n"
+ "}\n"
+ "\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, builderForValue.build());\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(index, value);\n"
+ "}\n");
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(builderForValue.build());\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(index, builderForValue.build());\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = emptyProtobufList();\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void remove$capitalized_name$(int index) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.remove(index);\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ // The comments above the methods below are based on a hypothetical
+ // repeated field of type "Field" called "RepeatedField".
+
+ // List<Field> getRepeatedFieldList()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+
+ // int getRepeatedFieldCount()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}");
+
+ // Field getRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder setRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field value)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ // Builder addRepeatedField(Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addRepeatedField(int index, Field.Builder builderForValue)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " int index, $type$.Builder builderForValue) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(index, builderForValue);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder addAllRepeatedField(Iterable<Field> values)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder clearAllRepeatedField()
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ // Builder removeRepeatedField(int index)
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+ " copyOnWrite();\n"
+ " instance.remove$capitalized_name$(index);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "get$capitalized_name$FieldBuilder();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = emptyProtobufList();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // The code below does two optimizations (non-nested builder case):
+ // 1. If the other list is empty, there's nothing to do. This ensures we
+ // don't allocate a new array if we already have an immutable one.
+ // 2. If the other list is non-empty and our current list is empty, we can
+ // reuse the other list which is guaranteed to be immutable.
+ printer->Print(variables_,
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = other.$name$_;\n"
+ " } else {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.addAll(other.$name$_);\n"
+ " }\n"
+ " $on_changed$\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = newProtobufList();\n"
+ "}\n");
+
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
+ printer->Print(variables_,
+ "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+ " extensionRegistry));\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
+ }
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $name$_.makeImmutable();\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$group_or_message$($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$group_or_message$Size($number$, $name$_.get(i));\n"
+ "}\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableMessageFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutableMessageFieldLiteGenerator::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_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h
new file mode 100644
index 00000000..ae26c06a
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.h
@@ -0,0 +1,157 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMessageFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateMergingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldLiteGenerator);
+};
+
+class ImmutableMessageOneofFieldLiteGenerator
+ : public ImmutableMessageFieldLiteGenerator {
+ public:
+ ImmutableMessageOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMessageOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableMessageFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableMessageFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableMessageFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateMergingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
new file mode 100644
index 00000000..3accee92
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -0,0 +1,1174 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <google/protobuf/compiler/java/java_message_lite.h>
+
+#include <algorithm>
+#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>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_extension.h>
+#include <google/protobuf/compiler/java/java_generator_factory.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_message_builder.h>
+#include <google/protobuf/compiler/java/java_message_builder_lite.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+bool GenerateHasBits(const Descriptor* descriptor) {
+ return SupportFieldPresence(descriptor->file()) ||
+ HasRepeatedFields(descriptor);
+}
+
+string MapValueImmutableClassdName(const Descriptor* descriptor,
+ ClassNameResolver* name_resolver) {
+ const FieldDescriptor* value_field = descriptor->FindFieldByName("value");
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type());
+ return name_resolver->GetImmutableClassName(value_field->message_type());
+}
+} // namespace
+
+// ===================================================================
+ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator(
+ const Descriptor* descriptor, Context* context)
+ : MessageGenerator(descriptor), context_(context),
+ name_resolver_(context->GetNameResolver()),
+ field_generators_(descriptor, context_) {
+ GOOGLE_CHECK_EQ(
+ FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
+
+void ImmutableMessageLiteGenerator::GenerateStaticVariables(
+ io::Printer* printer) {
+ // Generate static members for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariables(printer);
+ }
+}
+
+int ImmutableMessageLiteGenerator::GenerateStaticVariableInitializers(
+ io::Printer* printer) {
+ int bytecode_estimate = 0;
+ // Generate static member initializers for all nested types.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // TODO(kenton): Reuse MessageGenerator objects?
+ bytecode_estimate +=
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateStaticVariableInitializers(printer);
+ }
+ return bytecode_estimate;
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "public interface $classname$OrBuilder extends \n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.GeneratedMessageLite.\n"
+ " ExtendableMessageOrBuilder<\n"
+ " $classname$, $classname$.Builder> {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
+ } else {
+ printer->Print(
+ "public interface $classname$OrBuilder extends\n"
+ " $extra_interfaces$\n"
+ " com.google.protobuf.MessageLiteOrBuilder {\n",
+ "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
+ "classname", descriptor_->name());
+ }
+
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("\n");
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInterfaceMembers(printer);
+ }
+ printer->Outdent();
+
+ printer->Print("}\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
+ bool is_own_file =
+ 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_);
+
+ 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) {
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
+ " $classname$, $classname$.Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_));
+ } else {
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessageLite<\n"
+ " $classname$, $classname$.Builder> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+
+ builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
+ }
+ printer->Indent();
+
+ GenerateParsingConstructor(printer);
+
+ // Nested types
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator(descriptor_->enum_type(i), true, context_)
+ .Generate(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;
+ ImmutableMessageLiteGenerator messageGenerator(
+ descriptor_->nested_type(i), context_);
+ messageGenerator.GenerateInterface(printer);
+ messageGenerator.Generate(printer);
+ }
+
+ if (GenerateHasBits(descriptor_)) {
+ // Integers for bit fields.
+ int totalBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ totalBits += field_generators_.get(descriptor_->field(i))
+ .GetNumBitsForMessage();
+ }
+ int totalInts = (totalBits + 31) / 32;
+ for (int i = 0; i < totalInts; i++) {
+ printer->Print("private int $bit_field_name$;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+ }
+
+ // oneof
+ map<string, string> vars;
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ vars["oneof_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name;
+ vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name;
+ vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ // OneofCase enum
+ printer->Print(vars,
+ "public enum $oneof_capitalized_name$Case\n"
+ " implements com.google.protobuf.Internal.EnumLite {\n");
+ printer->Indent();
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+ printer->Print(
+ "$field_name$($field_number$),\n",
+ "field_name",
+ ToUpper(field->name()),
+ "field_number",
+ SimpleItoa(field->number()));
+ }
+ printer->Print(
+ "$cap_oneof_name$_NOT_SET(0);\n",
+ "cap_oneof_name",
+ ToUpper(vars["oneof_name"]));
+ printer->Print(vars,
+ "private int value = 0;\n"
+ "private $oneof_capitalized_name$Case(int value) {\n"
+ " this.value = value;\n"
+ "}\n");
+ printer->Print(vars,
+ "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+ " switch (value) {\n");
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+ printer->Print(
+ " case $field_number$: return $field_name$;\n",
+ "field_number",
+ SimpleItoa(field->number()),
+ "field_name",
+ ToUpper(field->name()));
+ }
+ printer->Print(
+ " case 0: return $cap_oneof_name$_NOT_SET;\n"
+ " default: throw new java.lang.IllegalArgumentException(\n"
+ " \"Value is undefined for this oneof enum.\");\n"
+ " }\n"
+ "}\n"
+ "public int getNumber() {\n"
+ " return this.value;\n"
+ "}\n",
+ "cap_oneof_name", ToUpper(vars["oneof_name"]));
+ printer->Outdent();
+ printer->Print("};\n\n");
+ // oneofCase()
+ printer->Print(vars,
+ "public $oneof_capitalized_name$Case\n"
+ "get$oneof_capitalized_name$Case() {\n"
+ " return $oneof_capitalized_name$Case.valueOf(\n"
+ " $oneof_name$Case_);\n"
+ "}\n"
+ "\n"
+ "private void clear$oneof_capitalized_name$() {\n"
+ " $oneof_name$Case_ = 0;\n"
+ " $oneof_name$_ = null;\n"
+ "}\n"
+ "\n");
+ }
+
+ // Fields
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ printer->Print("public static final int $constant_name$ = $number$;\n",
+ "constant_name", FieldConstantName(descriptor_->field(i)),
+ "number", SimpleItoa(descriptor_->field(i)->number()));
+ field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
+ printer->Print("\n");
+ }
+
+ GenerateMessageSerializationMethods(printer);
+
+ if (HasEqualsAndHashCode(descriptor_)) {
+ GenerateEqualsAndHashCode(printer);
+ }
+
+
+ GenerateParseFromMethods(printer);
+ GenerateBuilder(printer);
+
+ if (HasRequiredFields(descriptor_)) {
+ // Memoizes whether the protocol buffer is fully initialized (has all
+ // required fields). -1 means not yet computed. 0 means false and 1 means
+ // true.
+ printer->Print(
+ "private byte memoizedIsInitialized = -1;\n");
+ }
+
+ printer->Print(
+ "protected final Object dynamicMethod(\n"
+ " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
+ " Object... args) {\n"
+ " switch (method) {\n"
+ " case PARSE_PARTIAL_FROM: {\n"
+ " return new $classname$("
+ " (com.google.protobuf.CodedInputStream) args[0],\n"
+ " (com.google.protobuf.ExtensionRegistryLite) args[1]);\n"
+ " }\n"
+ " case NEW_INSTANCE: {\n"
+ " return new $classname$(\n"
+ " com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n"
+ " com.google.protobuf.ExtensionRegistryLite\n"
+ " .getEmptyRegistry());\n"
+ " }\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Indent();
+ printer->Indent();
+
+ printer->Print(
+ "case IS_INITIALIZED: {\n");
+ printer->Indent();
+ GenerateDynamicMethodIsInitialized(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case MAKE_IMMUTABLE: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodMakeImmutable(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case NEW_BUILDER: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodNewBuilder(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n"
+ "case MERGE_FROM: {\n");
+
+ printer->Indent();
+ GenerateDynamicMethodMergeFrom(printer);
+ printer->Outdent();
+
+ printer->Print(
+ "}\n");
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ " throw new UnsupportedOperationException();\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+
+ // Carefully initialize the default instance in such a way that it doesn't
+ // conflict with other initialization.
+ printer->Print(
+ "private static final $classname$ DEFAULT_INSTANCE;\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print(
+ "static {\n"
+ " DEFAULT_INSTANCE = new $classname$(\n"
+ " com.google.protobuf.Internal\n"
+ " .EMPTY_CODED_INPUT_STREAM,\n"
+ " com.google.protobuf.ExtensionRegistryLite\n"
+ " .getEmptyRegistry());\n"
+ "}\n"
+ "\n",
+ "classname", descriptor_->name());
+ printer->Print(
+ "public static $classname$ getDefaultInstance() {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ GenerateParser(printer);
+
+ // LITE_RUNTIME uses this to implement the *ForType methods at the
+ // GeneratedMessageLite level.
+ printer->Print(
+ "static {\n"
+ " com.google.protobuf.GeneratedMessageLite.onLoad(\n"
+ " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n"
+ " .PrototypeHolder<$classname$, Builder>(\n"
+ " DEFAULT_INSTANCE, PARSER));"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ // Extensions must be declared after the DEFAULT_INSTANCE is initialized
+ // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
+ // the outer class's FileDescriptor.
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+ .Generate(printer);
+ }
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::
+GenerateMessageSerializationMethods(io::Printer* printer) {
+ google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
+
+ printer->Print(
+ "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
+ " throws java.io.IOException {\n");
+ printer->Indent();
+ if (HasPackedFields(descriptor_)) {
+ // writeTo(CodedOutputStream output) might be invoked without
+ // getSerializedSize() ever being called, but we need the memoized
+ // sizes in case this message has packed fields. Rather than emit checks for
+ // each packed field, just call getSerializedSize() up front.
+ // In most cases, getSerializedSize() will have already been called anyway
+ // by one of the wrapper writeTo() methods, making this call cheap.
+ printer->Print(
+ "getSerializedSize();\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessageLite\n"
+ " .ExtendableMessage<$classname$, $classname$.Builder>\n"
+ " .ExtensionWriter extensionWriter =\n"
+ " newMessageSetExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ } else {
+ printer->Print(
+ "com.google.protobuf.GeneratedMessageLite\n"
+ " .ExtendableMessage<$classname$, $classname$.Builder>\n"
+ " .ExtensionWriter extensionWriter =\n"
+ " newExtensionWriter();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ }
+ }
+
+ // Merge the fields and the extension ranges, both sorted by field number.
+ for (int i = 0, j = 0;
+ i < descriptor_->field_count() || j < sorted_extensions.size();
+ ) {
+ if (i == descriptor_->field_count()) {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ } else if (j == sorted_extensions.size()) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
+ GenerateSerializeOneField(printer, sorted_fields[i++]);
+ } else {
+ GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+ }
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "unknownFields.writeTo(output);\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n"
+ "public int getSerializedSize() {\n"
+ " int size = memoizedSerializedSize;\n"
+ " if (size != -1) return size;\n"
+ "\n"
+ " size = 0;\n");
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer);
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ if (descriptor_->options().message_set_wire_format()) {
+ printer->Print(
+ "size += extensionsSerializedSizeAsMessageSet();\n");
+ } else {
+ printer->Print(
+ "size += extensionsSerializedSize();\n");
+ }
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "size += unknownFields.getSerializedSize();\n");
+ }
+
+ printer->Outdent();
+ printer->Print(
+ " memoizedSerializedSize = size;\n"
+ " return size;\n"
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "private static final long serialVersionUID = 0L;\n");
+}
+
+void ImmutableMessageLiteGenerator::
+GenerateParseFromMethods(io::Printer* printer) {
+ // Note: These are separate from GenerateMessageSerializationMethods()
+ // because they need to be generated even for messages that are optimized
+ // for code size.
+ printer->Print(
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.ByteString data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(byte[] data)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " byte[] data,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " return PARSER.parseFrom(data, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(java.io.InputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseFrom(input);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " java.io.InputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseFrom(input, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseDelimitedFrom(input);\n"
+ "}\n"
+ "public static $classname$ parseDelimitedFrom(\n"
+ " java.io.InputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.CodedInputStream input)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseFrom(input);\n"
+ "}\n"
+ "public static $classname$ parseFrom(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
+ " throws java.io.IOException {\n"
+ " return PARSER.parseFrom(input, extensionRegistry);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+}
+
+void ImmutableMessageLiteGenerator::GenerateSerializeOneField(
+ io::Printer* printer, const FieldDescriptor* field) {
+ field_generators_.get(field).GenerateSerializationCode(printer);
+}
+
+void ImmutableMessageLiteGenerator::GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range) {
+ printer->Print(
+ "extensionWriter.writeUntil($end$, output);\n",
+ "end", SimpleItoa(range->end));
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) {
+ printer->Print(
+ "public static Builder newBuilder() {\n"
+ " return DEFAULT_INSTANCE.toBuilder();\n"
+ "}\n"
+ "public static Builder newBuilder($classname$ prototype) {\n"
+ " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n"
+ "}\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ MessageBuilderLiteGenerator builderGenerator(descriptor_, context_);
+ builderGenerator.Generate(printer);
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
+ io::Printer* printer) {
+ // Returns null for false, DEFAULT_INSTANCE for true.
+ if (!HasRequiredFields(descriptor_)) {
+ printer->Print("return DEFAULT_INSTANCE;\n");
+ return;
+ }
+
+ // Don't directly compare to -1 to avoid an Android x86 JIT bug.
+ printer->Print(
+ "byte isInitialized = memoizedIsInitialized;\n"
+ "if (isInitialized == 1) return DEFAULT_INSTANCE;\n"
+ "if (isInitialized == 0) return null;\n"
+ "\n"
+ "boolean shouldMemoize = ((Boolean) args[0]).booleanValue();\n");
+
+ // Check that all required fields in this message are set.
+ // TODO(kenton): We can optimize this when we switch to putting all the
+ // "has" fields into a single bitfield.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+
+ if (field->is_required()) {
+ printer->Print(
+ "if (!has$name$()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ "}\n",
+ "name", info->capitalized_name);
+ }
+ }
+
+ // Now check that all embedded messages are initialized.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ HasRequiredFields(field->message_type())) {
+ switch (field->label()) {
+ case FieldDescriptor::LABEL_REQUIRED:
+ printer->Print(
+ "if (!get$name$().isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ 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 (!get$name$().isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ " }\n"
+ "}\n",
+ "name", info->capitalized_name);
+ break;
+ case FieldDescriptor::LABEL_REPEATED:
+ if (IsMapEntry(field->message_type())) {
+ printer->Print(
+ "for ($type$ item : get$name$().values()) {\n"
+ " if (!item.isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ " }\n"
+ "}\n",
+ "type", MapValueImmutableClassdName(field->message_type(),
+ name_resolver_),
+ "name", info->capitalized_name);
+ } else {
+ printer->Print(
+ "for (int i = 0; i < get$name$Count(); i++) {\n"
+ " if (!get$name$(i).isInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ " }\n"
+ "}\n",
+ "type", name_resolver_->GetImmutableClassName(
+ field->message_type()),
+ "name", info->capitalized_name);
+ }
+ break;
+ }
+ }
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "if (!extensionsAreInitialized()) {\n"
+ " if (shouldMemoize) {\n"
+ " memoizedIsInitialized = 0;\n"
+ " }\n"
+ " return null;\n"
+ "}\n");
+ }
+
+ printer->Print(
+ "if (shouldMemoize) memoizedIsInitialized = 1;\n");
+
+ printer->Print(
+ "return DEFAULT_INSTANCE;\n"
+ "\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
+ io::Printer* printer) {
+ // Output generation code for each field.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateDynamicMethodMakeImmutableCode(printer);
+ }
+ printer->Print(
+ "return null;");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder(
+ io::Printer* printer) {
+ printer->Print(
+ "return new Builder();");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
+ io::Printer* printer) {
+ printer->Print(
+ // Optimization: If other is the default instance, we know none of its
+ // fields are set so we can skip the merge.
+ "Object arg = args[0];\n"
+ "if (arg == $classname$.getDefaultInstance()) return this;\n"
+ "$classname$ other = ($classname$) arg;\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(
+ descriptor_->field(i)).GenerateMergingCode(printer);
+ }
+ }
+
+ // Merge oneof fields.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+ printer->Print(
+ "switch (other.get$oneof_capitalized_name$Case()) {\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name);
+ printer->Indent();
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+ printer->Print(
+ "case $field_name$: {\n",
+ "field_name",
+ ToUpper(field->name()));
+ printer->Indent();
+ field_generators_.get(field).GenerateMergingCode(printer);
+ printer->Print(
+ "break;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+ printer->Print(
+ "case $cap_oneof_name$_NOT_SET: {\n"
+ " break;\n"
+ "}\n",
+ "cap_oneof_name",
+ ToUpper(context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name));
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+
+ // if message type has extensions
+ if (descriptor_->extension_range_count() > 0) {
+ printer->Print(
+ "this.mergeExtensionFields(other);\n");
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "this.mergeUnknownFields(other.unknownFields);\n");
+ }
+
+ printer->Print(
+ "return this;\n");
+}
+
+// ===================================================================
+
+namespace {
+bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) {
+ if (field->is_repeated()) {
+ return false;
+ }
+ if (SupportFieldPresence(field->file())) {
+ return true;
+ }
+ return GetJavaType(field) == JAVATYPE_MESSAGE &&
+ field->containing_oneof() == NULL;
+}
+} // namespace
+
+void ImmutableMessageLiteGenerator::
+GenerateEqualsAndHashCode(io::Printer* printer) {
+ printer->Print(
+ "@java.lang.Override\n"
+ "public boolean equals(final java.lang.Object obj) {\n");
+ printer->Indent();
+ printer->Print(
+ "if (obj == this) {\n"
+ " return true;\n"
+ "}\n"
+ "if (!(obj instanceof $classname$)) {\n"
+ " return super.equals(obj);\n"
+ "}\n"
+ "$classname$ other = ($classname$) obj;\n"
+ "\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ printer->Print("boolean result = true;\n");
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+ if (check_has_bits) {
+ printer->Print(
+ "result = result && (has$name$() == other.has$name$());\n"
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ printer->Indent();
+ }
+ field_generators_.get(field).GenerateEqualsCode(printer);
+ if (check_has_bits) {
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+ }
+ if (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 && unknownFields.equals(other.unknownFields);\n");
+ }
+ printer->Print(
+ "return result;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+
+ printer->Print(
+ "@java.lang.Override\n"
+ "public int hashCode() {\n");
+ printer->Indent();
+ printer->Print(
+ "if (memoizedHashCode != 0) {\n");
+ printer->Indent();
+ printer->Print(
+ "return memoizedHashCode;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "int hash = 41;\n");
+
+ // Include the hash of the class so that two objects with different types
+ // but the same field values will probably have different hashes.
+ printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+ if (check_has_bits) {
+ printer->Print(
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ printer->Indent();
+ }
+ field_generators_.get(field).GenerateHashCode(printer);
+ if (check_has_bits) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+
+ printer->Print(
+ "hash = (29 * hash) + unknownFields.hashCode();\n");
+ printer->Print(
+ "memoizedHashCode = hash;\n"
+ "return hash;\n");
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::
+GenerateExtensionRegistrationCode(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ ImmutableExtensionGenerator(descriptor_->extension(i), context_)
+ .GenerateRegistrationCode(printer);
+ }
+
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+ .GenerateExtensionRegistrationCode(printer);
+ }
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::
+GenerateParsingConstructor(io::Printer* printer) {
+ google::protobuf::scoped_array<const FieldDescriptor * > sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ printer->Print(
+ "private $classname$(\n"
+ " com.google.protobuf.CodedInputStream input,\n"
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ // Initialize all fields to default.
+ GenerateInitializers(printer);
+
+ // Use builder bits to track mutable repeated fields.
+ int totalBuilderBits = 0;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const ImmutableFieldLiteGenerator& field =
+ field_generators_.get(descriptor_->field(i));
+ totalBuilderBits += field.GetNumBitsForBuilder();
+ }
+ int totalBuilderInts = (totalBuilderBits + 31) / 32;
+ for (int i = 0; i < totalBuilderInts; i++) {
+ printer->Print("int mutable_$bit_field_name$ = 0;\n",
+ "bit_field_name", GetBitFieldName(i));
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
+ }
+
+ printer->Print(
+ "try {\n");
+ printer->Indent();
+
+ printer->Print(
+ "boolean done = false;\n"
+ "while (!done) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "int tag = input.readTag();\n"
+ "switch (tag) {\n");
+ printer->Indent();
+
+ printer->Print(
+ "case 0:\n" // zero signals EOF / limit reached
+ " done = true;\n"
+ " break;\n");
+
+ if (PreserveUnknownFields(descriptor_)) {
+ if (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];
+ uint32 tag = WireFormatLite::MakeTag(field->number(),
+ WireFormat::WireTypeForFieldType(field->type()));
+
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from a
+ // packed version of this field regardless of field->options().packed().
+ uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(packed_tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // switch (tag)
+ "}\n"); // while (!done)
+
+ printer->Outdent();
+ printer->Print(
+ "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
+ " throw new RuntimeException(e.setUnfinishedMessage(this));\n"
+ "} catch (java.io.IOException e) {\n"
+ " throw new RuntimeException(\n"
+ " new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e.getMessage()).setUnfinishedMessage(this));\n"
+ "} finally {\n");
+ printer->Indent();
+
+ // Make repeated field list immutable.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = sorted_fields[i];
+ field_generators_.get(field).GenerateParsingDoneCode(printer);
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ // Make unknown fields immutable.
+ printer->Print("this.unknownFields = unknownFields.build();\n");
+ }
+
+ if (descriptor_->extension_range_count() > 0) {
+ // Make extensions immutable.
+ printer->Print(
+ "makeExtensionsImmutable(extensions);\n");
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n" // finally
+ "}\n");
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) {
+ printer->Print(
+ "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
+ " new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+ "\n",
+ "classname", descriptor_->name());
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ }
+}
+
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h
new file mode 100644
index 00000000..2bd3cdd4
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_lite.h
@@ -0,0 +1,91 @@
+// 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: dweis@google.com (Daniel Weis)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
+
+#include <string>
+#include <map>
+#include <google/protobuf/compiler/java/java_field.h>
+#include <google/protobuf/compiler/java/java_message.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMessageLiteGenerator : public MessageGenerator {
+ public:
+ explicit ImmutableMessageLiteGenerator(const Descriptor* descriptor,
+ Context* context);
+ virtual ~ImmutableMessageLiteGenerator();
+
+ virtual void Generate(io::Printer* printer);
+ virtual void GenerateInterface(io::Printer* printer);
+ virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
+ virtual void GenerateStaticVariables(io::Printer* printer);
+ virtual int GenerateStaticVariableInitializers(io::Printer* printer);
+
+ private:
+
+ void GenerateMessageSerializationMethods(io::Printer* printer);
+ void GenerateParseFromMethods(io::Printer* printer);
+ void GenerateSerializeOneField(io::Printer* printer,
+ const FieldDescriptor* field);
+ void GenerateSerializeOneExtensionRange(
+ io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+ void GenerateBuilder(io::Printer* printer);
+ void GenerateDynamicMethodIsInitialized(io::Printer* printer);
+ void GenerateDynamicMethodMakeImmutable(io::Printer* printer);
+ void GenerateDynamicMethodMergeFrom(io::Printer* printer);
+ void GenerateDynamicMethodNewBuilder(io::Printer* printer);
+ void GenerateInitializers(io::Printer* printer);
+ void GenerateEqualsAndHashCode(io::Printer* printer);
+ void GenerateParser(io::Printer* printer);
+ void GenerateParsingConstructor(io::Printer* printer);
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+ FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 48757c60..7bebe12a 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -74,7 +74,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
"" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
(*variables)["capitalized_type"] =
GetCapitalizedType(descriptor, /* immutable = */ true);
- (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ if (descriptor->is_packed()) {
+ (*variables)["tag"] = SimpleItoa(WireFormatLite::MakeTag(
+ descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+ } else {
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ }
(*variables)["tag_size"] = SimpleItoa(
WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
if (IsReferenceType(GetJavaType(descriptor))) {
@@ -599,7 +604,7 @@ GenerateMembers(io::Printer* printer) const {
" return $name$_.get(index);\n"
"}\n");
- if (descriptor_->options().packed() &&
+ if (descriptor_->is_packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
printer->Print(variables_,
"private int $name$MemoizedSerializedSize = -1;\n");
@@ -771,7 +776,7 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void RepeatedImmutablePrimitiveFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
// We invoke getSerializedSize in writeTo for messages that have packed
// fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
// That makes it safe to rely on the memoized size here.
@@ -812,7 +817,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(
"size += dataSize;\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"if (!get$capitalized_name$List().isEmpty()) {\n"
" size += $tag_size$;\n"
@@ -825,7 +830,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
// cache the data size for packed fields.
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packed()) {
printer->Print(variables_,
"$name$MemoizedSerializedSize = dataSize;\n");
}
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
new file mode 100644
index 00000000..217ff9b6
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -0,0 +1,892 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_primitive_field_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor));
+ (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor));
+ (*variables)["field_type"] = (*variables)["type"];
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ?
+ "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
+ (*variables)["capitalized_type"] =
+ GetCapitalizedType(descriptor, /* immutable = */ true);
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+
+ string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName(
+ GetJavaType(descriptor)), true /* cap_next_letter */);
+ switch (GetJavaType(descriptor)) {
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_FLOAT:
+ case JAVATYPE_DOUBLE:
+ case JAVATYPE_BOOLEAN:
+ (*variables)["field_list_type"] =
+ "com.google.protobuf.Internal." + capitalized_type + "List";
+ (*variables)["new_list"] = "new" + capitalized_type + "List";
+ (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
+ (*variables)["make_name_unmodifiable"] =
+ (*variables)["name"] + "_.makeImmutable()";
+ (*variables)["repeated_index_get"] =
+ (*variables)["name"] + "_.get" + capitalized_type + "(index)";
+ (*variables)["repeated_add"] =
+ (*variables)["name"] + "_.add" + capitalized_type;
+ (*variables)["repeated_set"] =
+ (*variables)["name"] + "_.set" + capitalized_type;
+ break;
+ default:
+ (*variables)["field_list_type"] =
+ "com.google.protobuf.Internal.ProtobufList<" +
+ (*variables)["boxed_type"] + ">";
+ (*variables)["new_list"] = "newProtobufList";
+ (*variables)["empty_list"] = "emptyProtobufList()";
+ (*variables)["make_name_unmodifiable"] =
+ (*variables)["name"] + "_.makeImmutable()";
+ (*variables)["repeated_index_get"] =
+ (*variables)["name"] + "_.get(index)";
+ (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
+ (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
+ }
+
+ if (IsReferenceType(GetJavaType(descriptor))) {
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+ } else {
+ (*variables)["null_check"] = "";
+ }
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ int fixed_size = FixedSize(GetType(descriptor));
+ if (fixed_size != -1) {
+ (*variables)["fixed_size"] = SimpleItoa(fixed_size);
+ }
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ if (SupportFieldPresence(descriptor->file())) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
+ (*variables)["is_field_present_message"] =
+ "!" + (*variables)["name"] + "_.isEmpty()";
+ } else {
+ (*variables)["is_field_present_message"] =
+ (*variables)["name"] + "_ != " + (*variables)["default"];
+ }
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutablePrimitiveFieldLiteGenerator::
+ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
+
+int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$();\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private $field_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return $name$_;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n");
+ JavaType type = GetJavaType(descriptor_);
+ if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
+ // The default value is not a simple literal so we want to avoid executing
+ // it multiple times. Instead, get the default out of the default instance.
+ printer->Print(variables_,
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n");
+ } else {
+ printer->Print(variables_,
+ " $name$_ = $default$;\n");
+ }
+ printer->Print(variables_,
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (other.get$capitalized_name$() != $default$) {\n"
+ " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "}\n");
+ }
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$set_has_field_bit_message$\n"
+ "$name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for primitives.
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.write$capitalized_type$($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$Size($number$, $name$_);\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ switch (GetJavaType(descriptor_)) {
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "result = result && (get$capitalized_name$()\n"
+ " == other.get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "result = result && (\n"
+ " java.lang.Float.floatToIntBits(get$capitalized_name$())\n"
+ " == java.lang.Float.floatToIntBits(\n"
+ " other.get$capitalized_name$()));\n");
+ break;
+
+ case JAVATYPE_DOUBLE:
+ printer->Print(variables_,
+ "result = result && (\n"
+ " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n"
+ " == java.lang.Double.doubleToLongBits(\n"
+ " other.get$capitalized_name$()));\n");
+ break;
+
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_ENUM:
+ case JAVATYPE_MESSAGE:
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+}
+
+void ImmutablePrimitiveFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n");
+ switch (GetJavaType(descriptor_)) {
+ case JAVATYPE_INT:
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$();\n");
+ break;
+
+ case JAVATYPE_LONG:
+ printer->Print(variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_BOOLEAN:
+ printer->Print(variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_FLOAT:
+ printer->Print(variables_,
+ "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n"
+ " get$capitalized_name$());\n");
+ break;
+
+ case JAVATYPE_DOUBLE:
+ printer->Print(variables_,
+ "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n"
+ " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n");
+ break;
+
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+ break;
+
+ case JAVATYPE_ENUM:
+ case JAVATYPE_MESSAGE:
+ default:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+}
+
+string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+// ===================================================================
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutablePrimitiveFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutablePrimitiveOneofFieldLiteGenerator::
+~ImmutablePrimitiveOneofFieldLiteGenerator() {}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ($boxed_type$) $oneof_name$_;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+}
+
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "set$capitalized_name$(other.get$capitalized_name$());\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = input.read$capitalized_type$();\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.write$capitalized_type$(\n"
+ " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+ "}\n");
+}
+
+void ImmutablePrimitiveOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$Size(\n"
+ " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutablePrimitiveFieldLiteGenerator::
+~RepeatedImmutablePrimitiveFieldLiteGenerator() {}
+
+int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$$type$ get$capitalized_name$(int index);\n");
+}
+
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private $field_list_type$ $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return $repeated_index_get$;\n"
+ "}\n");
+
+ if (descriptor_->options().packed() &&
+ HasGeneratedMethods(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize = -1;\n");
+ }
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = $new_list$($name$_);\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_set$(index, value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$($type$ value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $repeated_add$(value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $boxed_type$> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = $empty_list$;\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<$boxed_type$>\n"
+ " get$capitalized_name$List() {\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, $type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<? extends $boxed_type$> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // The code below does two optimizations:
+ // 1. If the other list is empty, there's nothing to do. This ensures we
+ // don't allocate a new array if we already have an immutable one.
+ // 2. If the other list is non-empty and our current list is empty, we can
+ // reuse the other list which is guaranteed to be immutable.
+ printer->Print(variables_,
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = other.$name$_;\n"
+ " } else {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.addAll(other.$name$_);\n"
+ " }\n"
+ " $on_changed$\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ // noop for primitives
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = $new_list$();\n"
+ "}\n"
+ "$repeated_add$(input.read$capitalized_type$());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"
+ " $name$_ = $new_list$();\n"
+ "}\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " $repeated_add$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $make_name_unmodifiable$;\n"
+ "}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ // We invoke getSerializedSize in writeTo for messages that have packed
+ // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
+ // That makes it safe to rely on the memoized size here.
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$($number$, $name$_.get(i));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ if (FixedSize(GetType(descriptor_)) == -1) {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ printer->Print(
+ "size += dataSize;\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {\n"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeInt32SizeNoTag(dataSize);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutablePrimitiveFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const {
+ return BoxedPrimitiveTypeName(GetJavaType(descriptor_));
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
new file mode 100644
index 00000000..ad603c2a
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
@@ -0,0 +1,163 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutablePrimitiveFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutablePrimitiveFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator);
+};
+
+class ImmutablePrimitiveOneofFieldLiteGenerator
+ : public ImmutablePrimitiveFieldLiteGenerator {
+ public:
+ ImmutablePrimitiveOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutablePrimitiveOneofFieldLiteGenerator();
+
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateBuildingCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutablePrimitiveFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 8aa5699c..68e863cc 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -208,7 +208,7 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void ImmutableStringFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.lang.Object $name$_;\n");
+ "private volatile java.lang.Object $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
if (SupportFieldPresence(descriptor_->file())) {
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
new file mode 100644
index 00000000..51bb245c
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -0,0 +1,1013 @@
+// 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)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/compiler/java/java_string_field_lite.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["empty_list"] = "emptyLazyStringArrayList()";
+
+ (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_init"] =
+ "= " + ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["capitalized_type"] = "String";
+ (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
+ (*variables)["tag_size"] = SimpleItoa(
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
+ (*variables)["null_check"] =
+ " if (value == null) {\n"
+ " throw new NullPointerException();\n"
+ " }\n";
+
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ if (SupportFieldPresence(descriptor->file())) {
+ // For singular messages and builders, one bit is used for the hasField bit.
+ (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
+
+ // Note that these have a trailing ";".
+ (*variables)["set_has_field_bit_message"] =
+ GenerateSetBit(messageBitIndex) + ";";
+ (*variables)["clear_has_field_bit_message"] =
+ GenerateClearBit(messageBitIndex) + ";";
+
+ (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex);
+ } else {
+ (*variables)["set_has_field_bit_message"] = "";
+ (*variables)["clear_has_field_bit_message"] = "";
+
+ (*variables)["is_field_present_message"] =
+ "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
+ }
+
+ // For repeated builders, the underlying list tracks mutability state.
+ (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()";
+
+ (*variables)["get_has_field_bit_from_local"] =
+ GenerateGetBitFromLocal(builderBitIndex);
+ (*variables)["set_has_field_bit_to_local"] =
+ GenerateSetBitToLocal(messageBitIndex);
+}
+
+bool CheckUtf8(const FieldDescriptor* descriptor) {
+ return descriptor->file()->options().java_string_check_utf8();
+}
+
+} // namespace
+
+// ===================================================================
+
+ImmutableStringFieldLiteGenerator::
+ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
+
+int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 1;
+}
+
+int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+// A note about how strings are handled. This code used to just store a String
+// in the Message. This had two issues:
+//
+// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
+// strings, but rather fields that were raw bytes incorrectly marked
+// as strings in the proto file. This is common because in the proto1
+// syntax, string was the way to indicate bytes and C++ engineers can
+// easily make this mistake without affecting the C++ API. By converting to
+// strings immediately, some java code might corrupt these byte arrays as
+// it passes through a java server even if the field was never accessed by
+// application code.
+//
+// 2. There's a performance hit to converting between bytes and strings and
+// it many cases, the field is never even read by the application code. This
+// avoids unnecessary conversions in the common use cases.
+//
+// So now, the field for String is maintained as an Object reference which can
+// either store a String or a ByteString. The code uses an instanceof check
+// to see which one it has and converts to the other one if needed. It remembers
+// the last value requested (in a thread safe manner) as this is most likely
+// the one needed next. The thread safety is such that if two threads both
+// convert the field because the changes made by each thread were not visible to
+// the other, they may cause a conversion to happen more times than would
+// otherwise be necessary. This was deemed better than adding synchronization
+// overhead. It will not cause any corruption issues or affect the behavior of
+// the API. The instanceof check is also highly optimized in the JVM and we
+// decided it was better to reduce the memory overhead by not having two
+// separate fields but rather use dynamic type checking.
+//
+// For single fields, the logic for this is done inside the generated code. For
+// repeated fields, the logic is done in LazyStringArrayList and
+// UnmodifiableLazyStringList.
+void ImmutableStringFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$boolean has$capitalized_name$();\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.lang.String get$capitalized_name$();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes();\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private java.lang.Object $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $get_has_field_bit_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " return (java.lang.String) ref;\n"
+ " } else {\n"
+ " com.google.protobuf.ByteString bs = \n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " $name$_ = s;\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8()) {\n"
+ " $name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " return s;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " java.lang.Object ref = $name$_;\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " $name$_ = b;\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $clear_has_field_bit_message$\n"
+ // The default value is not a simple literal so we want to avoid executing
+ // it multiple times. Instead, get the default out of the default instance.
+ " $name$_ = getDefaultInstance().get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $set_has_field_bit_message$\n"
+ " $name$_ = value;\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " return instance.get$capitalized_name$Bytes();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for strings
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ // Allow a slight breach of abstraction here in order to avoid forcing
+ // all string fields to Strings when copying fields from a Message.
+ printer->Print(variables_,
+ "if (other.has$capitalized_name$()) {\n"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = other.$name$_;\n"
+ " $on_changed$\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "if (!other.get$capitalized_name$().isEmpty()) {\n"
+ " $name$_ = other.$name$_;\n"
+ " $on_changed$\n"
+ "}\n");
+ }
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ // noop for scalars
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "String s = input.readStringRequireUtf8();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = s;\n");
+ } else 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"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = bs;\n");
+ }
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // noop for strings
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_field_present_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+}
+
+void ImmutableStringFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n");
+ printer->Print(variables_,
+ "hash = (53 * hash) + get$capitalized_name$().hashCode();\n");
+}
+
+string ImmutableStringFieldLiteGenerator::GetBoxedType() const {
+ return "java.lang.String";
+}
+
+// ===================================================================
+
+ImmutableStringOneofFieldLiteGenerator::
+ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : ImmutableStringFieldLiteGenerator(
+ descriptor, messageBitIndex, builderBitIndex, context) {
+ const OneofGeneratorInfo* info =
+ context->GetOneofGeneratorInfo(descriptor->containing_oneof());
+ SetCommonOneofVariables(descriptor, info, &variables_);
+}
+
+ImmutableStringOneofFieldLiteGenerator::
+~ImmutableStringOneofFieldLiteGenerator() {}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ PrintExtraFieldInfo(variables_, printer);
+
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case_message$;\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " return (java.lang.String) ref;\n"
+ " } else {\n"
+ " com.google.protobuf.ByteString bs = \n"
+ " (com.google.protobuf.ByteString) ref;\n"
+ " java.lang.String s = bs.toStringUtf8();\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " if ($has_oneof_case_message$) {\n"
+ " $oneof_name$_ = s;\n"
+ " }\n");
+ } else {
+ printer->Print(variables_,
+ " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
+ " $oneof_name$_ = s;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " return s;\n"
+ " }\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " java.lang.Object ref $default_init$;\n"
+ " if ($has_oneof_case_message$) {\n"
+ " ref = $oneof_name$_;\n"
+ " }\n"
+ " if (ref instanceof java.lang.String) {\n"
+ " com.google.protobuf.ByteString b = \n"
+ " com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " (java.lang.String) ref);\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $oneof_name$_ = b;\n"
+ " }\n"
+ " return b;\n"
+ " } else {\n"
+ " return (com.google.protobuf.ByteString) ref;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " $clear_oneof_case_message$;\n"
+ " $oneof_name$_ = null;\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ if (SupportFieldPresence(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public boolean has$capitalized_name$() {\n"
+ " return instance.has$capitalized_name$();\n"
+ "}\n");
+ }
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+ " return instance.get$capitalized_name$();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes() {\n"
+ " return instance.get$capitalized_name$Bytes();\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // Allow a slight breach of abstraction here in order to avoid forcing
+ // all string fields to Strings when copying fields from a Message.
+ printer->Print(variables_,
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = other.$oneof_name$_;\n"
+ "$on_changed$\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ "String s = input.readStringRequireUtf8();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = s;\n");
+ } 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"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = bs;\n");
+ }
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+void ImmutableStringOneofFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case_message$) {\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ "}\n");
+}
+
+// ===================================================================
+
+RepeatedImmutableStringFieldLiteGenerator::
+RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+RepeatedImmutableStringFieldLiteGenerator::
+~RepeatedImmutableStringFieldLiteGenerator() {}
+
+int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
+ return 0;
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ProtocolStringList\n"
+ " get$capitalized_name$List();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Count();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index);\n");
+}
+
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(variables_,
+ "private com.google.protobuf.LazyStringArrayList $name$_;\n");
+ PrintExtraFieldInfo(variables_, printer);
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ " get$capitalized_name$List() {\n"
+ " return $name$_;\n" // note: unmodifiable list
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return $name$_.size();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index) {\n"
+ " return $name$_.getByteString(index);\n"
+ "}\n");
+
+ if (descriptor_->options().packed() &&
+ HasGeneratedMethods(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ "private int $name$MemoizedSerializedSize = -1;\n");
+ }
+
+ printer->Print(variables_,
+ "private void ensure$capitalized_name$IsMutable() {\n"
+ " if (!$is_mutable$) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+ " }\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void set$capitalized_name$(\n"
+ " int index, java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ "$null_check$"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void addAll$capitalized_name$(\n"
+ " java.lang.Iterable<java.lang.String> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " com.google.protobuf.AbstractMessageLite.addAll(\n"
+ " values, $name$_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void clear$capitalized_name$() {\n"
+ " $name$_ = $empty_list$;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "private void add$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ "$null_check$");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " checkByteStringIsUtf8(value);\n");
+ }
+ printer->Print(variables_,
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ " get$capitalized_name$List() {\n"
+ " return ((com.google.protobuf.LazyStringList)\n"
+ " instance.get$capitalized_name$List()).getUnmodifiableView();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Count() {\n"
+ " return instance.get$capitalized_name$Count();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+ " return instance.get$capitalized_name$(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public com.google.protobuf.ByteString\n"
+ " get$capitalized_name$Bytes(int index) {\n"
+ " return instance.get$capitalized_name$Bytes(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$(\n"
+ " int index, java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.set$capitalized_name$(index, value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$(\n"
+ " java.lang.String value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$(value);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$(\n"
+ " java.lang.Iterable<java.lang.String> values) {\n"
+ " copyOnWrite();\n"
+ " instance.addAll$capitalized_name$(values);\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder clear$capitalized_name$() {\n"
+ " copyOnWrite();\n"
+ " instance.clear$capitalized_name$();\n"
+ " return this;\n"
+ "}\n");
+
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+ " com.google.protobuf.ByteString value) {\n"
+ " copyOnWrite();\n"
+ " instance.add$capitalized_name$Bytes(value);\n"
+ " return this;\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // noop for strings
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $empty_list$;\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ // The code below does two optimizations:
+ // 1. If the other list is empty, there's nothing to do. This ensures we
+ // don't allocate a new array if we already have an immutable one.
+ // 2. If the other list is non-empty and our current list is empty, we can
+ // reuse the other list which is guaranteed to be immutable.
+ printer->Print(variables_,
+ "if (!other.$name$_.isEmpty()) {\n"
+ " if ($name$_.isEmpty()) {\n"
+ " $name$_ = other.$name$_;\n"
+ " } else {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.addAll(other.$name$_);\n"
+ " }\n"
+ " $on_changed$\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$_.makeImmutable();\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+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");
+ }
+ printer->Print(variables_,
+ "if (!$is_mutable$) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ "}\n");
+ if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
+ printer->Print(variables_,
+ "$name$_.add(s);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.add(bs);\n");
+ }
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"
+ " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ "}\n"
+ "while (input.getBytesUntilLimit() > 0) {\n");
+ if (CheckUtf8(descriptor_)) {
+ printer->Print(variables_,
+ " String s = input.readStringRequireUtf8();\n");
+ } else {
+ printer->Print(variables_,
+ " String s = input.readString();\n");
+ }
+ printer->Print(variables_,
+ " $name$.add(s);\n");
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(limit);\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($is_mutable$) {\n"
+ " $name$_.makeImmutable();\n"
+ "}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (get$capitalized_name$List().size() > 0) {\n"
+ " output.writeRawVarint32($tag$);\n"
+ " output.writeRawVarint32($name$MemoizedSerializedSize);\n"
+ "}\n"
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " output.writeBytes($number$, $name$_.getByteString(i));\n"
+ "}\n");
+ }
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "{\n"
+ " int dataSize = 0;\n");
+ printer->Indent();
+
+ printer->Print(variables_,
+ "for (int i = 0; i < $name$_.size(); i++) {\n"
+ " dataSize += com.google.protobuf.CodedOutputStream\n"
+ " .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+ "}\n");
+
+ printer->Print(
+ "size += dataSize;\n");
+
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "if (!get$capitalized_name$List().isEmpty()) {\n"
+ " size += $tag_size$;\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeInt32SizeNoTag(dataSize);\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "size += $tag_size$ * get$capitalized_name$List().size();\n");
+ }
+
+ // cache the data size for packed fields.
+ if (descriptor_->options().packed()) {
+ printer->Print(variables_,
+ "$name$MemoizedSerializedSize = dataSize;\n");
+ }
+
+ printer->Outdent();
+ printer->Print("}\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$List()\n"
+ " .equals(other.get$capitalized_name$List());\n");
+}
+
+void RepeatedImmutableStringFieldLiteGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (get$capitalized_name$Count() > 0) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n"
+ "}\n");
+}
+
+string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
+ return "String";
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h
new file mode 100644
index 00000000..9d93b307
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.h
@@ -0,0 +1,158 @@
+// 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)
+// Author: jonp@google.com (Jon Perlow)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator {
+ public:
+ explicit ImmutableStringFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableStringFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateMergingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ protected:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator);
+};
+
+class ImmutableStringOneofFieldLiteGenerator
+ : public ImmutableStringFieldLiteGenerator {
+ public:
+ ImmutableStringOneofFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableStringOneofFieldLiteGenerator();
+
+ private:
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
+};
+
+class RepeatedImmutableStringFieldLiteGenerator
+ : public ImmutableFieldLiteGenerator {
+ public:
+ explicit RepeatedImmutableStringFieldLiteGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~RepeatedImmutableStringFieldLiteGenerator();
+
+ // implements ImmutableFieldLiteGenerator ------------------------------------
+ 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 GenerateMergingCode(io::Printer* printer) const;
+ void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index c50cdf54..a2eeee2d 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -686,6 +686,8 @@ bool Parser::ParseMessageStatement(DescriptorProto* message,
LocationRecorder location(message_location,
DescriptorProto::kExtensionRangeFieldNumber);
return ParseExtensions(message, location, containing_file);
+ } else if (LookingAt("reserved")) {
+ return ParseReserved(message, message_location);
} else if (LookingAt("extend")) {
LocationRecorder location(message_location,
DescriptorProto::kExtensionFieldNumber);
@@ -733,6 +735,13 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
FieldDescriptorProto::Label label;
if (ParseLabel(&label, containing_file)) {
field->set_label(label);
+ if (label == FieldDescriptorProto::LABEL_OPTIONAL &&
+ syntax_identifier_ == "proto3") {
+ AddError(
+ "Explicit 'optional' labels are disallowed in the Proto3 syntax. "
+ "To define 'optional' fields in Proto3, simply remove the "
+ "'optional' label, as fields are 'optional' by default.");
+ }
}
}
@@ -1353,6 +1362,77 @@ bool Parser::ParseExtensions(DescriptorProto* message,
return true;
}
+// This is similar to extension range parsing, except that "max" is not
+// supported, and accepts field name literals.
+bool Parser::ParseReserved(DescriptorProto* message,
+ const LocationRecorder& message_location) {
+ // Parse the declaration.
+ DO(Consume("reserved"));
+ if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedNameFieldNumber);
+ return ParseReservedNames(message, location);
+ } else {
+ LocationRecorder location(message_location,
+ DescriptorProto::kReservedRangeFieldNumber);
+ return ParseReservedNumbers(message, location);
+ }
+}
+
+
+bool Parser::ParseReservedNames(DescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ do {
+ LocationRecorder location(parent_location, message->reserved_name_size());
+ DO(ConsumeString(message->add_reserved_name(), "Expected field name."));
+ } while (TryConsume(","));
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
+bool Parser::ParseReservedNumbers(DescriptorProto* message,
+ const LocationRecorder& parent_location) {
+ bool first = true;
+ do {
+ LocationRecorder location(parent_location, message->reserved_range_size());
+
+ DescriptorProto::ReservedRange* range = message->add_reserved_range();
+ int start, end;
+ io::Tokenizer::Token start_token;
+ {
+ LocationRecorder start_location(
+ location, DescriptorProto::ReservedRange::kStartFieldNumber);
+ start_token = input_->current();
+ DO(ConsumeInteger(&start, (first ?
+ "Expected field name or number range." :
+ "Expected field number range.")));
+ }
+
+ if (TryConsume("to")) {
+ LocationRecorder end_location(
+ location, DescriptorProto::ReservedRange::kEndFieldNumber);
+ DO(ConsumeInteger(&end, "Expected integer."));
+ } else {
+ LocationRecorder end_location(
+ location, DescriptorProto::ReservedRange::kEndFieldNumber);
+ end_location.StartAt(start_token);
+ end_location.EndAt(start_token);
+ end = start;
+ }
+
+ // Users like to specify inclusive ranges, but in code we like the end
+ // number to be exclusive.
+ ++end;
+
+ range->set_start(start);
+ range->set_end(end);
+ first = false;
+ } while (TryConsume(","));
+
+ DO(ConsumeEndOfDeclaration(";", &parent_location));
+ return true;
+}
+
bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
RepeatedPtrField<DescriptorProto>* messages,
const LocationRecorder& parent_location,
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index 7cb1678a..16012e96 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -364,6 +364,14 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& extensions_location,
const FileDescriptorProto* containing_file);
+ // Parse an "reserved" declaration.
+ bool ParseReserved(DescriptorProto* message,
+ const LocationRecorder& message_location);
+ bool ParseReservedNames(DescriptorProto* message,
+ const LocationRecorder& parent_location);
+ bool ParseReservedNumbers(DescriptorProto* message,
+ const LocationRecorder& parent_location);
+
// Parse an "extend" declaration. (See also comments for
// ParseMessageField().)
bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 1684bebe..ddf34bfa 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -620,6 +620,36 @@ TEST_F(ParseMessageTest, NestedEnum) {
"}");
}
+TEST_F(ParseMessageTest, ReservedRange) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " required int32 foo = 1;\n"
+ " reserved 2, 15, 9 to 11, 3;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
+ " reserved_range { start:2 end:3 }"
+ " reserved_range { start:15 end:16 }"
+ " reserved_range { start:9 end:12 }"
+ " reserved_range { start:3 end:4 }"
+ "}");
+}
+
+TEST_F(ParseMessageTest, ReservedNames) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " reserved \"foo\", \"bar\";\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ "}");
+}
+
TEST_F(ParseMessageTest, ExtensionRange) {
ExpectParsesTo(
"message TestMessage {\n"
@@ -715,19 +745,17 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
" type_name:\"TestMessage\" extendee: \"Extendee1\" }");
}
-TEST_F(ParseMessageTest, OptionalOptionalLabelProto3) {
+TEST_F(ParseMessageTest, OptionalLabelProto3) {
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 } }");
+ " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } }");
}
// ===================================================================
@@ -1230,6 +1258,18 @@ TEST_F(ParseErrorTest, EofInAggregateValue) {
"1:0: Unexpected end of stream while parsing aggregate value.\n");
}
+TEST_F(ParseErrorTest, ExplicitOptionalLabelProto3) {
+ ExpectHasErrors(
+ "syntax = 'proto3';\n"
+ "message TestMessage {\n"
+ " optional int32 foo = 1;\n"
+ "}\n",
+ "2:11: Explicit 'optional' labels are disallowed in the Proto3 syntax. "
+ "To define 'optional' fields in Proto3, simply remove the 'optional' "
+ "label, as fields are 'optional' by default.\n");
+}
+
+
// -------------------------------------------------------------------
// Enum errors
@@ -1248,6 +1288,33 @@ TEST_F(ParseErrorTest, EnumValueMissingNumber) {
}
// -------------------------------------------------------------------
+// Reserved field number errors
+
+TEST_F(ParseErrorTest, ReservedMaxNotAllowed) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved 10 to max;\n"
+ "}\n",
+ "1:17: Expected integer.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved 10, \"foo\";\n"
+ "}\n",
+ "1:15: Expected field number range.\n");
+}
+
+TEST_F(ParseErrorTest, ReservedMissingQuotes) {
+ ExpectHasErrors(
+ "message Foo {\n"
+ " reserved foo;\n"
+ "}\n",
+ "1:11: Expected field name or number range.\n");
+}
+
+// -------------------------------------------------------------------
// Service errors
TEST_F(ParseErrorTest, EofInService) {
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index ad501acf..cdcaffde 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -134,20 +134,34 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
CodeGeneratorResponse response;
GeneratorResponseContext context(&response, parsed_files);
- for (int i = 0; i < parsed_files.size(); i++) {
- const FileDescriptor* file = parsed_files[i];
-
+ if (generator->HasGenerateAll()) {
string error;
- bool succeeded = generator->Generate(
- file, request.parameter(), &context, &error);
+ bool succeeded = generator->GenerateAll(
+ parsed_files, request.parameter(), &context, &error);
if (!succeeded && error.empty()) {
error = "Code generator returned false but provided no error "
"description.";
}
if (!error.empty()) {
- response.set_error(file->name() + ": " + error);
- break;
+ response.set_error(error);
+ }
+ } else {
+ for (int i = 0; i < parsed_files.size(); i++) {
+ const FileDescriptor* file = parsed_files[i];
+
+ string error;
+ bool succeeded = generator->Generate(
+ file, request.parameter(), &context, &error);
+
+ if (!succeeded && error.empty()) {
+ error = "Code generator returned false but provided no error "
+ "description.";
+ }
+ if (!error.empty()) {
+ response.set_error(file->name() + ": " + error);
+ break;
+ }
}
}
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index d78b715e..344ed450 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -179,7 +179,7 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorRequest::CodeGeneratorRequest()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
}
@@ -300,12 +300,15 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
case 15: {
if (tag == 122) {
parse_proto_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_proto_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_proto_file()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(122)) goto parse_proto_file;
+ if (input->ExpectTag(122)) goto parse_loop_proto_file;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -445,9 +448,9 @@ int CodeGeneratorRequest::ByteSize() const {
void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const CodeGeneratorRequest* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorRequest*>(
- &from);
+ const CodeGeneratorRequest* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -513,10 +516,10 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
// CodeGeneratorRequest
// repeated string file_to_generate = 1;
- int CodeGeneratorRequest::file_to_generate_size() const {
+int CodeGeneratorRequest::file_to_generate_size() const {
return file_to_generate_.size();
}
- void CodeGeneratorRequest::clear_file_to_generate() {
+void CodeGeneratorRequest::clear_file_to_generate() {
file_to_generate_.Clear();
}
const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
@@ -567,16 +570,16 @@ CodeGeneratorRequest::mutable_file_to_generate() {
}
// optional string parameter = 2;
- bool CodeGeneratorRequest::has_parameter() const {
+bool CodeGeneratorRequest::has_parameter() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void CodeGeneratorRequest::set_has_parameter() {
+void CodeGeneratorRequest::set_has_parameter() {
_has_bits_[0] |= 0x00000002u;
}
- void CodeGeneratorRequest::clear_has_parameter() {
+void CodeGeneratorRequest::clear_has_parameter() {
_has_bits_[0] &= ~0x00000002u;
}
- void CodeGeneratorRequest::clear_parameter() {
+void CodeGeneratorRequest::clear_parameter() {
parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_parameter();
}
@@ -620,10 +623,10 @@ CodeGeneratorRequest::mutable_file_to_generate() {
}
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
- int CodeGeneratorRequest::proto_file_size() const {
+int CodeGeneratorRequest::proto_file_size() const {
return proto_file_.size();
}
- void CodeGeneratorRequest::clear_proto_file() {
+void CodeGeneratorRequest::clear_proto_file() {
proto_file_.Clear();
}
const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
@@ -660,7 +663,7 @@ const int CodeGeneratorResponse_File::kContentFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse_File::CodeGeneratorResponse_File()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
}
@@ -946,9 +949,9 @@ int CodeGeneratorResponse_File::ByteSize() const {
void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const CodeGeneratorResponse_File* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse_File*>(
- &from);
+ const CodeGeneratorResponse_File* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1024,7 +1027,7 @@ const int CodeGeneratorResponse::kFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse::CodeGeneratorResponse()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
@@ -1124,12 +1127,15 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
case 15: {
if (tag == 122) {
parse_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_file()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(122)) goto parse_file;
+ if (input->ExpectTag(122)) goto parse_loop_file;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1242,9 +1248,9 @@ int CodeGeneratorResponse::ByteSize() const {
void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const CodeGeneratorResponse* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse*>(
- &from);
+ const CodeGeneratorResponse* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1307,16 +1313,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
// CodeGeneratorResponse_File
// optional string name = 1;
- bool CodeGeneratorResponse_File::has_name() const {
+bool CodeGeneratorResponse_File::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void CodeGeneratorResponse_File::set_has_name() {
+void CodeGeneratorResponse_File::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void CodeGeneratorResponse_File::clear_has_name() {
+void CodeGeneratorResponse_File::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void CodeGeneratorResponse_File::clear_name() {
+void CodeGeneratorResponse_File::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -1360,16 +1366,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
}
// optional string insertion_point = 2;
- bool CodeGeneratorResponse_File::has_insertion_point() const {
+bool CodeGeneratorResponse_File::has_insertion_point() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void CodeGeneratorResponse_File::set_has_insertion_point() {
+void CodeGeneratorResponse_File::set_has_insertion_point() {
_has_bits_[0] |= 0x00000002u;
}
- void CodeGeneratorResponse_File::clear_has_insertion_point() {
+void CodeGeneratorResponse_File::clear_has_insertion_point() {
_has_bits_[0] &= ~0x00000002u;
}
- void CodeGeneratorResponse_File::clear_insertion_point() {
+void CodeGeneratorResponse_File::clear_insertion_point() {
insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_insertion_point();
}
@@ -1413,16 +1419,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
}
// optional string content = 15;
- bool CodeGeneratorResponse_File::has_content() const {
+bool CodeGeneratorResponse_File::has_content() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void CodeGeneratorResponse_File::set_has_content() {
+void CodeGeneratorResponse_File::set_has_content() {
_has_bits_[0] |= 0x00000004u;
}
- void CodeGeneratorResponse_File::clear_has_content() {
+void CodeGeneratorResponse_File::clear_has_content() {
_has_bits_[0] &= ~0x00000004u;
}
- void CodeGeneratorResponse_File::clear_content() {
+void CodeGeneratorResponse_File::clear_content() {
content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_content();
}
@@ -1470,16 +1476,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
// CodeGeneratorResponse
// optional string error = 1;
- bool CodeGeneratorResponse::has_error() const {
+bool CodeGeneratorResponse::has_error() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void CodeGeneratorResponse::set_has_error() {
+void CodeGeneratorResponse::set_has_error() {
_has_bits_[0] |= 0x00000001u;
}
- void CodeGeneratorResponse::clear_has_error() {
+void CodeGeneratorResponse::clear_has_error() {
_has_bits_[0] &= ~0x00000001u;
}
- void CodeGeneratorResponse::clear_error() {
+void CodeGeneratorResponse::clear_error() {
error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_error();
}
@@ -1523,10 +1529,10 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
}
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
- int CodeGeneratorResponse::file_size() const {
+int CodeGeneratorResponse::file_size() const {
return file_.size();
}
- void CodeGeneratorResponse::clear_file() {
+void CodeGeneratorResponse::clear_file() {
file_.Clear();
}
const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index ea48b8b5..6fcaea2e 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -796,6 +796,10 @@ CodeGeneratorResponse::mutable_file() {
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index bfdacd95..2855c377 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -1518,6 +1518,18 @@ Descriptor::FindExtensionRangeContainingNumber(int number) const {
return NULL;
}
+const Descriptor::ReservedRange*
+Descriptor::FindReservedRangeContainingNumber(int number) const {
+ // TODO(chrisn): Consider a non-linear search.
+ for (int i = 0; i < reserved_range_count(); i++) {
+ if (number >= reserved_range(i)->start &&
+ number < reserved_range(i)->end) {
+ return reserved_range(i);
+ }
+ }
+ return NULL;
+}
+
// -------------------------------------------------------------------
bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const {
@@ -1741,6 +1753,14 @@ void Descriptor::CopyTo(DescriptorProto* proto) const {
for (int i = 0; i < extension_count(); i++) {
extension(i)->CopyTo(proto->add_extension());
}
+ for (int i = 0; i < reserved_range_count(); i++) {
+ DescriptorProto::ReservedRange* range = proto->add_reserved_range();
+ range->set_start(reserved_range(i)->start);
+ range->set_end(reserved_range(i)->end);
+ }
+ for (int i = 0; i < reserved_name_count(); i++) {
+ proto->add_reserved_name(reserved_name(i));
+ }
if (&options() != &MessageOptions::default_instance()) {
proto->mutable_options()->CopyFrom(options());
@@ -2186,6 +2206,29 @@ void Descriptor::DebugString(int depth, string *contents,
if (extension_count() > 0)
strings::SubstituteAndAppend(contents, "$0 }\n", prefix);
+ if (reserved_range_count() > 0) {
+ strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
+ for (int i = 0; i < reserved_range_count(); i++) {
+ const Descriptor::ReservedRange* range = reserved_range(i);
+ if (range->end == range->start + 1) {
+ strings::SubstituteAndAppend(contents, "$0, ", range->start);
+ } else {
+ strings::SubstituteAndAppend(contents, "$0 to $1, ",
+ range->start, range->end - 1);
+ }
+ }
+ contents->replace(contents->size() - 2, 2, ";\n");
+ }
+
+ if (reserved_name_count() > 0) {
+ strings::SubstituteAndAppend(contents, "$0 reserved ", prefix);
+ for (int i = 0; i < reserved_name_count(); i++) {
+ strings::SubstituteAndAppend(contents, "\"$0\", ",
+ CEscape(reserved_name(i)));
+ }
+ contents->replace(contents->size() - 2, 2, ";\n");
+ }
+
strings::SubstituteAndAppend(contents, "$0}\n", prefix);
comment_printer.AddPostComment(contents);
}
@@ -2278,8 +2321,12 @@ void FieldDescriptor::DebugString(int depth,
}
if (type() == TYPE_GROUP) {
- message_type()->DebugString(depth, contents, debug_string_options,
- /* include_opening_clause */ false);
+ if (debug_string_options.elide_group_body) {
+ contents->append(" { ... };\n");
+ } else {
+ message_type()->DebugString(depth, contents, debug_string_options,
+ /* include_opening_clause */ false);
+ }
} else {
contents->append(";\n");
}
@@ -2308,12 +2355,16 @@ void OneofDescriptor::DebugString(int depth, string* contents,
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,
- debug_string_options);
+ contents, "$0 oneof $1 {", prefix, name());
+ if (debug_string_options.elide_oneof_body) {
+ contents->append(" ... }\n");
+ } else {
+ for (int i = 0; i < field_count(); i++) {
+ field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents,
+ debug_string_options);
+ }
+ strings::SubstituteAndAppend(contents, "$0}\n", prefix);
}
- strings::SubstituteAndAppend(contents, "$0}\n", prefix);
comment_printer.AddPostComment(contents);
}
@@ -2491,7 +2542,12 @@ bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
}
bool FieldDescriptor::is_packed() const {
- return is_packable() && (options_ != NULL) && options_->packed();
+ if (!is_packable()) return false;
+ if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
+ return (options_ != NULL) && options_->packed();
+ } else {
+ return options_ == NULL || !options_->has_packed() || options_->packed();
+ }
}
bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
@@ -2604,7 +2660,7 @@ void MethodDescriptor::GetLocationPath(vector<int>* output) const {
namespace {
// Represents an options message to interpret. Extension names in the option
-// name are respolved relative to name_scope. element_name and orig_opt are
+// name are resolved relative to name_scope. element_name and orig_opt are
// used only for error reporting (since the parser records locations against
// pointers in the original options, not the mutable copy). The Message must be
// one of the Options messages in descriptor.proto.
@@ -2830,6 +2886,9 @@ class DescriptorBuilder {
void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
const Descriptor* parent,
Descriptor::ExtensionRange* result);
+ void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
+ const Descriptor* parent,
+ Descriptor::ReservedRange* result);
void BuildOneof(const OneofDescriptorProto& proto,
Descriptor* parent,
OneofDescriptor* result);
@@ -3920,6 +3979,17 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
BUILD_ARRAY(proto, result, enum_type , BuildEnum , result);
BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
BUILD_ARRAY(proto, result, extension , BuildExtension , result);
+ BUILD_ARRAY(proto, result, reserved_range , BuildReservedRange , result);
+
+ // Copy reserved names.
+ int reserved_name_count = proto.reserved_name_size();
+ result->reserved_name_count_ = reserved_name_count;
+ result->reserved_names_ =
+ tables_->AllocateArray<const string*>(reserved_name_count);
+ for (int i = 0; i < reserved_name_count; ++i) {
+ result->reserved_names_[i] =
+ tables_->AllocateString(proto.reserved_name(i));
+ }
// Copy options.
if (!proto.has_options()) {
@@ -3931,7 +4001,34 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
AddSymbol(result->full_name(), parent, result->name(),
proto, Symbol(result));
- // Check that no fields have numbers in extension ranges.
+ for (int i = 0; i < proto.reserved_range_size(); i++) {
+ const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
+ for (int j = i + 1; j < proto.reserved_range_size(); j++) {
+ const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
+ if (range1.end() > range2.start() && range2.end() > range1.start()) {
+ AddError(result->full_name(), proto.reserved_range(i),
+ DescriptorPool::ErrorCollector::NUMBER,
+ strings::Substitute("Reserved range $0 to $1 overlaps with "
+ "already-defined range $2 to $3.",
+ range2.start(), range2.end() - 1,
+ range1.start(), range1.end() - 1));
+ }
+ }
+ }
+
+ hash_set<string> reserved_name_set;
+ for (int i = 0; i < proto.reserved_name_size(); i++) {
+ const string& name = proto.reserved_name(i);
+ if (reserved_name_set.find(name) == reserved_name_set.end()) {
+ reserved_name_set.insert(name);
+ } else {
+ AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
+ strings::Substitute(
+ "Field name \"$0\" is reserved multiple times.",
+ name));
+ }
+ }
+
for (int i = 0; i < result->field_count(); i++) {
const FieldDescriptor* field = result->field(i);
for (int j = 0; j < result->extension_range_count(); j++) {
@@ -3945,11 +4042,39 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
field->name(), field->number()));
}
}
+ for (int j = 0; j < result->reserved_range_count(); j++) {
+ const Descriptor::ReservedRange* range = result->reserved_range(j);
+ if (range->start <= field->number() && field->number() < range->end) {
+ AddError(field->full_name(), proto.reserved_range(j),
+ DescriptorPool::ErrorCollector::NUMBER,
+ strings::Substitute(
+ "Field \"$0\" uses reserved number $1.",
+ field->name(), field->number()));
+ }
+ }
+ if (reserved_name_set.find(field->name()) != reserved_name_set.end()) {
+ AddError(field->full_name(), proto.field(i),
+ DescriptorPool::ErrorCollector::NAME,
+ strings::Substitute(
+ "Field name \"$0\" is reserved.", field->name()));
+ }
}
- // Check that extension ranges don't overlap.
+ // Check that extension ranges don't overlap and don't include
+ // reserved field numbers.
for (int i = 0; i < result->extension_range_count(); i++) {
const Descriptor::ExtensionRange* range1 = result->extension_range(i);
+ for (int j = 0; j < result->reserved_range_count(); j++) {
+ const Descriptor::ReservedRange* range2 = result->reserved_range(j);
+ if (range1->end > range2->start && range2->end > range1->start) {
+ AddError(result->full_name(), proto.extension_range(j),
+ DescriptorPool::ErrorCollector::NUMBER,
+ strings::Substitute("Extension range $0 to $1 overlaps with "
+ "reserved range $2 to $3.",
+ range1->start, range1->end - 1,
+ range2->start, range2->end - 1));
+ }
+ }
for (int j = i + 1; j < result->extension_range_count(); j++) {
const Descriptor::ExtensionRange* range2 = result->extension_range(j);
if (range1->end > range2->start && range2->end > range1->start) {
@@ -4262,6 +4387,19 @@ void DescriptorBuilder::BuildExtensionRange(
}
}
+void DescriptorBuilder::BuildReservedRange(
+ const DescriptorProto::ReservedRange& proto,
+ const Descriptor* parent,
+ Descriptor::ReservedRange* result) {
+ result->start = proto.start();
+ result->end = proto.end();
+ if (result->start <= 0) {
+ AddError(parent->full_name(), proto,
+ DescriptorPool::ErrorCollector::NUMBER,
+ "Reserved numbers must be positive integers.");
+ }
+}
+
void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
Descriptor* parent,
OneofDescriptor* result) {
@@ -4503,6 +4641,23 @@ void DescriptorBuilder::CrossLinkMessage(
for (int i = 0; i < message->field_count(); i++) {
const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
if (oneof_decl != NULL) {
+ // Make sure fields belonging to the same oneof are defined consecutively.
+ // This enables optimizations in codegens and reflection libraries to
+ // skip fields in the oneof group, as only one of the field can be set.
+ // Note that field_count() returns how many fields in this oneof we have
+ // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
+ // safe.
+ if (oneof_decl->field_count() > 0 &&
+ message->field(i - 1)->containing_oneof() != oneof_decl) {
+ AddWarning(
+ message->full_name() + "." + message->field(i - 1)->name(),
+ proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER,
+ strings::Substitute(
+ "Fields in the same oneof must be defined consecutively. "
+ "\"$0\" cannot be defined before the completion of the "
+ "\"$1\" oneof definition.",
+ message->field(i - 1)->name(), oneof_decl->name()));
+ }
// Must go through oneof_decls_ array to get a non-const version of the
// OneofDescriptor.
++message->oneof_decls_[oneof_decl->index()].field_count_;
@@ -4933,6 +5088,12 @@ void DescriptorBuilder::ValidateProto3Field(
field->containing_type()->full_name() +
"\" which is a proto3 message type.");
}
+ bool allow_groups = false;
+ if (field->type() == FieldDescriptor::TYPE_GROUP && !allow_groups) {
+ AddError(field->full_name(), proto,
+ DescriptorPool::ErrorCollector::TYPE,
+ "Groups are not supported in proto3 syntax.");
+ }
}
void DescriptorBuilder::ValidateProto3Enum(
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index c0a48cea..ca87d634 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -135,10 +135,14 @@ struct DebugStringOptions {
// example, the C++ code generation for fields in the proto compiler) rely on
// DebugString() output being unobstructed by user comments.
bool include_comments;
+ // If true, elide the braced body in the debug string.
+ bool elide_group_body;
+ bool elide_oneof_body;
DebugStringOptions()
- : include_comments(false)
- {}
+ : include_comments(false),
+ elide_group_body(false),
+ elide_oneof_body(false) {}
};
// Describes a type of protocol message, or a particular group within a
@@ -298,6 +302,36 @@ class LIBPROTOBUF_EXPORT Descriptor {
// this message type's scope.
const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const;
+ // Reserved fields -------------------------------------------------
+
+ // A range of reserved field numbers.
+ struct ReservedRange {
+ int start; // inclusive
+ int end; // exclusive
+ };
+
+ // The number of reserved ranges in this message type.
+ int reserved_range_count() const;
+ // Gets an reserved range by index, where 0 <= index <
+ // reserved_range_count(). These are returned in the order they were defined
+ // in the .proto file.
+ const ReservedRange* reserved_range(int index) const;
+
+ // Returns true if the number is in one of the reserved ranges.
+ bool IsReservedNumber(int number) const;
+
+ // Returns NULL if no reserved range contains the given number.
+ const ReservedRange* FindReservedRangeContainingNumber(int number) const;
+
+ // The number of reserved field names in this message type.
+ int reserved_name_count() const;
+
+ // Gets a reserved name by index, where 0 <= index < reserved_name_count().
+ const string& reserved_name(int index) const;
+
+ // Returns true if the field name is reserved.
+ bool IsReservedName(const string& name) const;
+
// Source Location ---------------------------------------------------
// Updates |*out_location| to the source location of the complete
@@ -343,6 +377,10 @@ class LIBPROTOBUF_EXPORT Descriptor {
ExtensionRange* extension_ranges_;
int extension_count_;
FieldDescriptor* extensions_;
+ int reserved_range_count_;
+ ReservedRange* reserved_ranges_;
+ int reserved_name_count_;
+ const string** reserved_names_;
// IMPORTANT: If you add a new field, make sure to search for all instances
// of Allocate<Descriptor>() and AllocateArray<Descriptor>() in descriptor.cc
// and update them to initialize the field.
@@ -1567,6 +1605,12 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range,
const Descriptor::ExtensionRange*)
PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension,
const FieldDescriptor*)
+
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_range_count, int)
+PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, reserved_range,
+ const Descriptor::ReservedRange*)
+PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_name_count, int)
+
PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions);
PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool)
@@ -1667,6 +1711,25 @@ inline bool Descriptor::IsExtensionNumber(int number) const {
return FindExtensionRangeContainingNumber(number) != NULL;
}
+inline bool Descriptor::IsReservedNumber(int number) const {
+ return FindReservedRangeContainingNumber(number) != NULL;
+}
+
+inline bool Descriptor::IsReservedName(const string& name) const {
+ for (int i = 0; i < reserved_name_count(); i++) {
+ if (name == reserved_name(i)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually
+// an array of pointers rather than the usual array of objects.
+inline const string& Descriptor::reserved_name(int index) const {
+ return *reserved_names_[index];
+}
+
inline bool FieldDescriptor::is_required() const {
return label() == LABEL_REQUIRED;
}
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 8968f362..755c2617 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -33,6 +33,9 @@ const ::google::protobuf::internal::GeneratedMessageReflection*
const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
DescriptorProto_ExtensionRange_reflection_ = NULL;
+const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+ DescriptorProto_ReservedRange_reflection_ = NULL;
const ::google::protobuf::Descriptor* FieldDescriptorProto_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
FieldDescriptorProto_reflection_ = NULL;
@@ -64,6 +67,7 @@ const ::google::protobuf::Descriptor* FieldOptions_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
FieldOptions_reflection_ = NULL;
const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor_ = NULL;
+const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor_ = NULL;
const ::google::protobuf::Descriptor* EnumOptions_descriptor_ = NULL;
const ::google::protobuf::internal::GeneratedMessageReflection*
EnumOptions_reflection_ = NULL;
@@ -140,7 +144,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_),
-1);
DescriptorProto_descriptor_ = file->message_type(2);
- static const int DescriptorProto_offsets_[8] = {
+ static const int DescriptorProto_offsets_[10] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_),
@@ -149,6 +153,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, oneof_decl_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_range_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_name_),
};
DescriptorProto_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -177,6 +183,22 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
sizeof(DescriptorProto_ExtensionRange),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_),
-1);
+ DescriptorProto_ReservedRange_descriptor_ = DescriptorProto_descriptor_->nested_type(1);
+ static const int DescriptorProto_ReservedRange_offsets_[2] = {
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, start_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, end_),
+ };
+ DescriptorProto_ReservedRange_reflection_ =
+ ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
+ DescriptorProto_ReservedRange_descriptor_,
+ DescriptorProto_ReservedRange::default_instance_,
+ DescriptorProto_ReservedRange_offsets_,
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _has_bits_[0]),
+ -1,
+ -1,
+ sizeof(DescriptorProto_ReservedRange),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_),
+ -1);
FieldDescriptorProto_descriptor_ = file->message_type(3);
static const int FieldDescriptorProto_offsets_[9] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_),
@@ -338,9 +360,10 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_),
-1);
FieldOptions_descriptor_ = file->message_type(11);
- static const int FieldOptions_offsets_[6] = {
+ static const int FieldOptions_offsets_[7] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, jstype_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_),
@@ -358,6 +381,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_),
-1);
FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0);
+ FieldOptions_JSType_descriptor_ = FieldOptions_descriptor_->enum_type(1);
EnumOptions_descriptor_ = file->message_type(12);
static const int EnumOptions_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_),
@@ -515,6 +539,8 @@ void protobuf_RegisterTypes(const ::std::string&) {
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
DescriptorProto_ExtensionRange_descriptor_, &DescriptorProto_ExtensionRange::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+ DescriptorProto_ReservedRange_descriptor_, &DescriptorProto_ReservedRange::default_instance());
+ ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
OneofDescriptorProto_descriptor_, &OneofDescriptorProto::default_instance());
@@ -561,6 +587,8 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() {
delete DescriptorProto_reflection_;
delete DescriptorProto_ExtensionRange::default_instance_;
delete DescriptorProto_ExtensionRange_reflection_;
+ delete DescriptorProto_ReservedRange::default_instance_;
+ delete DescriptorProto_ReservedRange_reflection_;
delete FieldDescriptorProto::default_instance_;
delete FieldDescriptorProto_reflection_;
delete OneofDescriptorProto::default_instance_;
@@ -619,7 +647,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"\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\022\016\n\006syntax\030\014 \001"
- "(\t\"\344\003\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
+ "(\t\"\360\004\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"
@@ -630,104 +658,111 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"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\"\301\001\n\025MethodDescriptorProto\022\014\n"
- "\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013outpu"
- "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p"
- "rotobuf.MethodOptions\022\037\n\020client_streamin"
- "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010"
- ":\005false\"\201\005\n\013FileOptions\022\024\n\014java_package\030"
- "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j"
- "ava_multiple_files\030\n \001(\010:\005false\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\014"
- "optimize_for\030\t \001(\0162).google.protobuf.Fil"
- "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa"
- "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f"
- "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal"
- "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031"
- "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a"
- "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030"
- "$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022C\n\024unint"
- "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
- ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005"
- "SPEED\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\"\346\001\n\016MessageOptions\022&\n\027messag"
- "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta"
- "ndard_descriptor_accessor\030\002 \001(\010:\005false\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$.go"
- "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
- "\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.g"
- "oogle.protobuf.FieldOptions.CType:\006STRIN"
- "G\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\023\n\004weak\030\n \001(\010:"
- "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
- "google.protobuf.UninterpretedOption\"/\n\005C"
- "Type\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIE"
- "CE\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\022"
- "C\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.UninterpretedOption*\t\010\350\007"
- "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!"
+ "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro"
+ "tobuf.DescriptorProto.ReservedRange\022\025\n\rr"
+ "eserved_name\030\n \003(\t\032,\n\016ExtensionRange\022\r\n\005"
+ "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\032+\n\rReservedRang"
+ "e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024FieldD"
+ "escriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003"
+ " \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf.Fi"
+ "eldDescriptorProto.Label\0228\n\004type\030\005 \001(\0162*"
+ ".google.protobuf.FieldDescriptorProto.Ty"
+ "pe\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(\0132\035.google.protobuf.F"
+ "ieldOptions\"\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\013TYPE_UI"
+ "NT64\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\013TYP"
+ "E_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSA"
+ "GE\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_SINT32\020\021\022\017\n\013TYPE_SINT"
+ "64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LAB"
+ "EL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n\024One"
+ "ofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023Enum"
+ "DescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002"
+ " \003(\0132).google.protobuf.EnumValueDescript"
+ "orProto\022-\n\007options\030\003 \001(\0132\034.google.protob"
+ "uf.EnumOptions\"l\n\030EnumValueDescriptorPro"
+ "to\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007opti"
+ "ons\030\003 \001(\0132!.google.protobuf.EnumValueOpt"
+ "ions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004name\030"
+ "\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.protobuf."
+ "MethodDescriptorProto\0220\n\007options\030\003 \001(\0132\037"
+ ".google.protobuf.ServiceOptions\"\301\001\n\025Meth"
+ "odDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput"
+ "_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007opti"
+ "ons\030\004 \001(\0132\036.google.protobuf.MethodOption"
+ "s\022\037\n\020client_streaming\030\005 \001(\010:\005false\022\037\n\020se"
+ "rver_streaming\030\006 \001(\010:\005false\"\201\005\n\013FileOpti"
+ "ons\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_generate_equals_and_"
+ "hash\030\024 \001(\010:\005false\022%\n\026java_string_check_u"
+ "tf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(\0162)"
+ ".google.protobuf.FileOptions.OptimizeMod"
+ "e:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_gener"
+ "ic_services\030\020 \001(\010:\005false\022$\n\025java_generic"
+ "_services\030\021 \001(\010:\005false\022\"\n\023py_generic_ser"
+ "vices\030\022 \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005"
+ "false\022\037\n\020cc_enable_arenas\030\037 \001(\010:\005false\022\031"
+ "\n\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_name"
+ "space\030% \001(\t\022C\n\024uninterpreted_option\030\347\007 \003"
+ "(\0132$.google.protobuf.UninterpretedOption"
+ "\":\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\"\346\001\n\016Mess"
+ "ageOptions\022&\n\027message_set_wire_format\030\001 "
+ "\001(\010:\005false\022.\n\037no_standard_descriptor_acc"
+ "essor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005"
+ "false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterprete"
+ "d_option\030\347\007 \003(\0132$.google.protobuf.Uninte"
+ "rpretedOption*\t\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOption"
+ "s\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Field"
+ "Options.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n"
+ "\006jstype\030\006 \001(\0162$.google.protobuf.FieldOpt"
+ "ions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005fa"
+ "lse\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.UninterpretedOption"
- "*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecat"
- "ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030"
- "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
- "tion*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022"
- ";\n\004name\030\002 \003(\0132-.google.protobuf.Uninterp"
- "retedOption.NamePart\022\030\n\020identifier_value"
- "\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022ne"
- "gative_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\017aggregate_"
- "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\"\325\001\n\016SourceCodeI"
- "nfo\022:\n\010location\030\001 \003(\0132(.google.protobuf."
- "SourceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004"
- "path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lead"
- "ing_comments\030\003 \001(\t\022\031\n\021trailing_comments\030"
- "\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003(\t"
- "BY\n\023com.google.protobufB\020DescriptorProto"
- "sH\001\242\002\003GPB\252\002\'Google.ProtocolBuffers.Descr"
- "iptorProtos", 4691);
+ "\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRIN"
+ "G_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS"
+ "_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013"
+ "EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndepr"
+ "ecated\030\003 \001(\010:\005false\022C\n\024uninterpreted_opt"
+ "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
+ "edOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022"
+ "\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterpre"
+ "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin"
+ "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOpt"
+ "ions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024unint"
+ "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
+ ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMetho"
+ "dOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024u"
+ "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
+ "obuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023"
+ "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog"
+ "le.protobuf.UninterpretedOption.NamePart"
+ "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i"
+ "nt_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\017aggregate_value\030\010 \001(\t\0323\n\010NameP"
+ "art\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002"
+ " \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003("
+ "\0132(.google.protobuf.SourceCodeInfo.Locat"
+ "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp"
+ "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031"
+ "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det"
+ "ached_comments\030\006 \003(\tBY\n\023com.google.proto"
+ "bufB\020DescriptorProtosH\001\242\002\003GPB\252\002\'Google.P"
+ "rotocolBuffers.DescriptorProtos", 4951);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
FileDescriptorProto::default_instance_ = new FileDescriptorProto();
DescriptorProto::default_instance_ = new DescriptorProto();
DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange();
+ DescriptorProto_ReservedRange::default_instance_ = new DescriptorProto_ReservedRange();
FieldDescriptorProto::default_instance_ = new FieldDescriptorProto();
OneofDescriptorProto::default_instance_ = new OneofDescriptorProto();
EnumDescriptorProto::default_instance_ = new EnumDescriptorProto();
@@ -749,6 +784,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
FileDescriptorProto::default_instance_->InitAsDefaultInstance();
DescriptorProto::default_instance_->InitAsDefaultInstance();
DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance();
+ DescriptorProto_ReservedRange::default_instance_->InitAsDefaultInstance();
FieldDescriptorProto::default_instance_->InitAsDefaultInstance();
OneofDescriptorProto::default_instance_->InitAsDefaultInstance();
EnumDescriptorProto::default_instance_->InitAsDefaultInstance();
@@ -793,7 +829,7 @@ const int FileDescriptorSet::kFileFieldNumber;
#endif // !_MSC_VER
FileDescriptorSet::FileDescriptorSet()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet)
}
@@ -870,13 +906,15 @@ bool FileDescriptorSet::MergePartialFromCodedStream(
// repeated .google.protobuf.FileDescriptorProto file = 1;
case 1: {
if (tag == 10) {
- parse_file:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_file:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_file()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(10)) goto parse_file;
+ if (input->ExpectTag(10)) goto parse_loop_file;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -961,9 +999,9 @@ int FileDescriptorSet::ByteSize() const {
void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FileDescriptorSet* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FileDescriptorSet*>(
- &from);
+ const FileDescriptorSet* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1020,10 +1058,10 @@ void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
// FileDescriptorSet
// repeated .google.protobuf.FileDescriptorProto file = 1;
- int FileDescriptorSet::file_size() const {
+int FileDescriptorSet::file_size() const {
return file_.size();
}
- void FileDescriptorSet::clear_file() {
+void FileDescriptorSet::clear_file() {
file_.Clear();
}
const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
@@ -1069,7 +1107,7 @@ const int FileDescriptorProto::kSyntaxFieldNumber;
#endif // !_MSC_VER
FileDescriptorProto::FileDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto)
}
@@ -1237,54 +1275,63 @@ bool FileDescriptorProto::MergePartialFromCodedStream(
case 4: {
if (tag == 34) {
parse_message_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_message_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_message_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(34)) goto parse_message_type;
- if (input->ExpectTag(42)) goto parse_enum_type;
+ if (input->ExpectTag(34)) goto parse_loop_message_type;
+ if (input->ExpectTag(42)) goto parse_loop_enum_type;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
case 5: {
if (tag == 42) {
- parse_enum_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_enum_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(42)) goto parse_enum_type;
- if (input->ExpectTag(50)) goto parse_service;
+ if (input->ExpectTag(42)) goto parse_loop_enum_type;
+ if (input->ExpectTag(50)) goto parse_loop_service;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
case 6: {
if (tag == 50) {
- parse_service:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_service:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_service()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(50)) goto parse_service;
- if (input->ExpectTag(58)) goto parse_extension;
+ if (input->ExpectTag(50)) goto parse_loop_service;
+ if (input->ExpectTag(58)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
case 7: {
if (tag == 58) {
- parse_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_extension()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(58)) goto parse_extension;
+ if (input->ExpectTag(58)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(66)) goto parse_options;
break;
}
@@ -1712,9 +1759,9 @@ int FileDescriptorProto::ByteSize() const {
void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FileDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FileDescriptorProto*>(
- &from);
+ const FileDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1816,16 +1863,16 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
// FileDescriptorProto
// optional string name = 1;
- bool FileDescriptorProto::has_name() const {
+bool FileDescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void FileDescriptorProto::set_has_name() {
+void FileDescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void FileDescriptorProto::clear_has_name() {
+void FileDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void FileDescriptorProto::clear_name() {
+void FileDescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -1869,16 +1916,16 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
}
// optional string package = 2;
- bool FileDescriptorProto::has_package() const {
+bool FileDescriptorProto::has_package() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void FileDescriptorProto::set_has_package() {
+void FileDescriptorProto::set_has_package() {
_has_bits_[0] |= 0x00000002u;
}
- void FileDescriptorProto::clear_has_package() {
+void FileDescriptorProto::clear_has_package() {
_has_bits_[0] &= ~0x00000002u;
}
- void FileDescriptorProto::clear_package() {
+void FileDescriptorProto::clear_package() {
package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_package();
}
@@ -1922,10 +1969,10 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
}
// repeated string dependency = 3;
- int FileDescriptorProto::dependency_size() const {
+int FileDescriptorProto::dependency_size() const {
return dependency_.size();
}
- void FileDescriptorProto::clear_dependency() {
+void FileDescriptorProto::clear_dependency() {
dependency_.Clear();
}
const ::std::string& FileDescriptorProto::dependency(int index) const {
@@ -1976,10 +2023,10 @@ FileDescriptorProto::mutable_dependency() {
}
// repeated int32 public_dependency = 10;
- int FileDescriptorProto::public_dependency_size() const {
+int FileDescriptorProto::public_dependency_size() const {
return public_dependency_.size();
}
- void FileDescriptorProto::clear_public_dependency() {
+void FileDescriptorProto::clear_public_dependency() {
public_dependency_.Clear();
}
::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
@@ -2006,10 +2053,10 @@ FileDescriptorProto::mutable_public_dependency() {
}
// repeated int32 weak_dependency = 11;
- int FileDescriptorProto::weak_dependency_size() const {
+int FileDescriptorProto::weak_dependency_size() const {
return weak_dependency_.size();
}
- void FileDescriptorProto::clear_weak_dependency() {
+void FileDescriptorProto::clear_weak_dependency() {
weak_dependency_.Clear();
}
::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
@@ -2036,10 +2083,10 @@ FileDescriptorProto::mutable_weak_dependency() {
}
// repeated .google.protobuf.DescriptorProto message_type = 4;
- int FileDescriptorProto::message_type_size() const {
+int FileDescriptorProto::message_type_size() const {
return message_type_.size();
}
- void FileDescriptorProto::clear_message_type() {
+void FileDescriptorProto::clear_message_type() {
message_type_.Clear();
}
const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
@@ -2066,10 +2113,10 @@ FileDescriptorProto::mutable_message_type() {
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
- int FileDescriptorProto::enum_type_size() const {
+int FileDescriptorProto::enum_type_size() const {
return enum_type_.size();
}
- void FileDescriptorProto::clear_enum_type() {
+void FileDescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
@@ -2096,10 +2143,10 @@ FileDescriptorProto::mutable_enum_type() {
}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
- int FileDescriptorProto::service_size() const {
+int FileDescriptorProto::service_size() const {
return service_.size();
}
- void FileDescriptorProto::clear_service() {
+void FileDescriptorProto::clear_service() {
service_.Clear();
}
const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
@@ -2126,10 +2173,10 @@ FileDescriptorProto::mutable_service() {
}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
- int FileDescriptorProto::extension_size() const {
+int FileDescriptorProto::extension_size() const {
return extension_.size();
}
- void FileDescriptorProto::clear_extension() {
+void FileDescriptorProto::clear_extension() {
extension_.Clear();
}
const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
@@ -2156,16 +2203,16 @@ FileDescriptorProto::mutable_extension() {
}
// optional .google.protobuf.FileOptions options = 8;
- bool FileDescriptorProto::has_options() const {
+bool FileDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000200u) != 0;
}
- void FileDescriptorProto::set_has_options() {
+void FileDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000200u;
}
- void FileDescriptorProto::clear_has_options() {
+void FileDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000200u;
}
- void FileDescriptorProto::clear_options() {
+void FileDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
clear_has_options();
}
@@ -2199,16 +2246,16 @@ FileDescriptorProto::mutable_extension() {
}
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
- bool FileDescriptorProto::has_source_code_info() const {
+bool FileDescriptorProto::has_source_code_info() const {
return (_has_bits_[0] & 0x00000400u) != 0;
}
- void FileDescriptorProto::set_has_source_code_info() {
+void FileDescriptorProto::set_has_source_code_info() {
_has_bits_[0] |= 0x00000400u;
}
- void FileDescriptorProto::clear_has_source_code_info() {
+void FileDescriptorProto::clear_has_source_code_info() {
_has_bits_[0] &= ~0x00000400u;
}
- void FileDescriptorProto::clear_source_code_info() {
+void FileDescriptorProto::clear_source_code_info() {
if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
clear_has_source_code_info();
}
@@ -2242,16 +2289,16 @@ FileDescriptorProto::mutable_extension() {
}
// optional string syntax = 12;
- bool FileDescriptorProto::has_syntax() const {
+bool FileDescriptorProto::has_syntax() const {
return (_has_bits_[0] & 0x00000800u) != 0;
}
- void FileDescriptorProto::set_has_syntax() {
+void FileDescriptorProto::set_has_syntax() {
_has_bits_[0] |= 0x00000800u;
}
- void FileDescriptorProto::clear_has_syntax() {
+void FileDescriptorProto::clear_has_syntax() {
_has_bits_[0] &= ~0x00000800u;
}
- void FileDescriptorProto::clear_syntax() {
+void FileDescriptorProto::clear_syntax() {
syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_syntax();
}
@@ -2304,7 +2351,7 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber;
#endif // !_MSC_VER
DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange)
}
@@ -2516,9 +2563,9 @@ int DescriptorProto_ExtensionRange::ByteSize() const {
void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const DescriptorProto_ExtensionRange* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const DescriptorProto_ExtensionRange*>(
- &from);
+ const DescriptorProto_ExtensionRange* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -2582,6 +2629,289 @@ void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange
// -------------------------------------------------------------------
#ifndef _MSC_VER
+const int DescriptorProto_ReservedRange::kStartFieldNumber;
+const int DescriptorProto_ReservedRange::kEndFieldNumber;
+#endif // !_MSC_VER
+
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange()
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ SharedCtor();
+ // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+void DescriptorProto_ReservedRange::InitAsDefaultInstance() {
+}
+
+DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
+ SharedCtor();
+ MergeFrom(from);
+ // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+void DescriptorProto_ReservedRange::SharedCtor() {
+ _cached_size_ = 0;
+ start_ = 0;
+ end_ = 0;
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() {
+ // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange)
+ SharedDtor();
+}
+
+void DescriptorProto_ReservedRange::SharedDtor() {
+ if (this != default_instance_) {
+ }
+}
+
+void DescriptorProto_ReservedRange::SetCachedSize(int size) const {
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange::descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return DescriptorProto_ReservedRange_descriptor_;
+}
+
+const DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::default_instance() {
+ if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ return *default_instance_;
+}
+
+DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::default_instance_ = NULL;
+
+DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::New(::google::protobuf::Arena* arena) const {
+ DescriptorProto_ReservedRange* n = new DescriptorProto_ReservedRange;
+ if (arena != NULL) {
+ arena->Own(n);
+ }
+ return n;
+}
+
+void DescriptorProto_ReservedRange::Clear() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<DescriptorProto_ReservedRange*>(16)->f)
+
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
+
+ ZR_(start_, end_);
+
+#undef ZR_HELPER_
+#undef ZR_
+
+ ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
+}
+
+bool DescriptorProto_ReservedRange::MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure
+ ::google::protobuf::uint32 tag;
+ // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ReservedRange)
+ for (;;) {
+ ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
+ tag = p.first;
+ if (!p.second) goto handle_unusual;
+ switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+ // optional int32 start = 1;
+ case 1: {
+ if (tag == 8) {
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &start_)));
+ set_has_start();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(16)) goto parse_end;
+ break;
+ }
+
+ // optional int32 end = 2;
+ case 2: {
+ if (tag == 16) {
+ parse_end:
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
+ input, &end_)));
+ set_has_end();
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectAtEnd()) goto success;
+ break;
+ }
+
+ default: {
+ handle_unusual:
+ if (tag == 0 ||
+ ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+ ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+ goto success;
+ }
+ DO_(::google::protobuf::internal::WireFormat::SkipField(
+ input, tag, mutable_unknown_fields()));
+ break;
+ }
+ }
+ }
+success:
+ // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ReservedRange)
+ return true;
+failure:
+ // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ReservedRange)
+ return false;
+#undef DO_
+}
+
+void DescriptorProto_ReservedRange::SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const {
+ // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ReservedRange)
+ // optional int32 start = 1;
+ if (has_start()) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
+ }
+
+ // optional int32 end = 2;
+ if (has_end()) {
+ ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+ unknown_fields(), output);
+ }
+ // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ReservedRange)
+}
+
+::google::protobuf::uint8* DescriptorProto_ReservedRange::SerializeWithCachedSizesToArray(
+ ::google::protobuf::uint8* target) const {
+ // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange)
+ // optional int32 start = 1;
+ if (has_start()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
+ }
+
+ // optional int32 end = 2;
+ if (has_end()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
+ }
+
+ if (_internal_metadata_.have_unknown_fields()) {
+ target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+ unknown_fields(), target);
+ }
+ // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange)
+ return target;
+}
+
+int DescriptorProto_ReservedRange::ByteSize() const {
+ int total_size = 0;
+
+ if (_has_bits_[0 / 32] & 3) {
+ // optional int32 start = 1;
+ if (has_start()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->start());
+ }
+
+ // optional int32 end = 2;
+ if (has_end()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::Int32Size(
+ this->end());
+ }
+
+ }
+ if (_internal_metadata_.have_unknown_fields()) {
+ total_size +=
+ ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+ unknown_fields());
+ }
+ GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+ _cached_size_ = total_size;
+ GOOGLE_SAFE_CONCURRENT_WRITES_END();
+ return total_size;
+}
+
+void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const DescriptorProto_ReservedRange* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>(
+ &from);
+ if (source == NULL) {
+ ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+ } else {
+ MergeFrom(*source);
+ }
+}
+
+void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) {
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (from.has_start()) {
+ set_start(from.start());
+ }
+ if (from.has_end()) {
+ set_end(from.end());
+ }
+ }
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
+}
+
+void DescriptorProto_ReservedRange::CopyFrom(const ::google::protobuf::Message& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) {
+ if (&from == this) return;
+ Clear();
+ MergeFrom(from);
+}
+
+bool DescriptorProto_ReservedRange::IsInitialized() const {
+
+ return true;
+}
+
+void DescriptorProto_ReservedRange::Swap(DescriptorProto_ReservedRange* other) {
+ if (other == this) return;
+ InternalSwap(other);
+}
+void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* 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_ReservedRange::GetMetadata() const {
+ protobuf_AssignDescriptorsOnce();
+ ::google::protobuf::Metadata metadata;
+ metadata.descriptor = DescriptorProto_ReservedRange_descriptor_;
+ metadata.reflection = DescriptorProto_ReservedRange_reflection_;
+ return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+#ifndef _MSC_VER
const int DescriptorProto::kNameFieldNumber;
const int DescriptorProto::kFieldFieldNumber;
const int DescriptorProto::kExtensionFieldNumber;
@@ -2590,10 +2920,12 @@ const int DescriptorProto::kEnumTypeFieldNumber;
const int DescriptorProto::kExtensionRangeFieldNumber;
const int DescriptorProto::kOneofDeclFieldNumber;
const int DescriptorProto::kOptionsFieldNumber;
+const int DescriptorProto::kReservedRangeFieldNumber;
+const int DescriptorProto::kReservedNameFieldNumber;
#endif // !_MSC_VER
DescriptorProto::DescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto)
}
@@ -2670,6 +3002,8 @@ void DescriptorProto::Clear() {
enum_type_.Clear();
extension_range_.Clear();
oneof_decl_.Clear();
+ reserved_range_.Clear();
+ reserved_name_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->Clear();
@@ -2706,68 +3040,79 @@ bool DescriptorProto::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_field:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_field:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_field()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_field;
- if (input->ExpectTag(26)) goto parse_nested_type;
+ if (input->ExpectTag(18)) goto parse_loop_field;
+ if (input->ExpectTag(26)) goto parse_loop_nested_type;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
case 3: {
if (tag == 26) {
- parse_nested_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_nested_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_nested_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(26)) goto parse_nested_type;
- if (input->ExpectTag(34)) goto parse_enum_type;
+ if (input->ExpectTag(26)) goto parse_loop_nested_type;
+ if (input->ExpectTag(34)) goto parse_loop_enum_type;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
case 4: {
if (tag == 34) {
- parse_enum_type:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_enum_type:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_enum_type()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(34)) goto parse_enum_type;
- if (input->ExpectTag(42)) goto parse_extension_range;
+ if (input->ExpectTag(34)) goto parse_loop_enum_type;
+ if (input->ExpectTag(42)) goto parse_loop_extension_range;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
case 5: {
if (tag == 42) {
- parse_extension_range:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_extension_range:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_extension_range()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(42)) goto parse_extension_range;
- if (input->ExpectTag(50)) goto parse_extension;
+ if (input->ExpectTag(42)) goto parse_loop_extension_range;
+ if (input->ExpectTag(50)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
case 6: {
if (tag == 50) {
- parse_extension:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_extension:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_extension()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(50)) goto parse_extension;
+ if (input->ExpectTag(50)) goto parse_loop_extension;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(58)) goto parse_options;
break;
}
@@ -2789,12 +3134,50 @@ bool DescriptorProto::MergePartialFromCodedStream(
case 8: {
if (tag == 66) {
parse_oneof_decl:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_oneof_decl:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_oneof_decl()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(66)) goto parse_oneof_decl;
+ if (input->ExpectTag(66)) goto parse_loop_oneof_decl;
+ if (input->ExpectTag(74)) goto parse_loop_reserved_range;
+ input->UnsafeDecrementRecursionDepth();
+ break;
+ }
+
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ case 9: {
+ if (tag == 74) {
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_reserved_range:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ input, add_reserved_range()));
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(74)) goto parse_loop_reserved_range;
+ input->UnsafeDecrementRecursionDepth();
+ if (input->ExpectTag(82)) goto parse_reserved_name;
+ break;
+ }
+
+ // repeated string reserved_name = 10;
+ case 10: {
+ if (tag == 82) {
+ parse_reserved_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_reserved_name()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->reserved_name(this->reserved_name_size() - 1).data(),
+ this->reserved_name(this->reserved_name_size() - 1).length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.DescriptorProto.reserved_name");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(82)) goto parse_reserved_name;
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -2876,6 +3259,22 @@ void DescriptorProto::SerializeWithCachedSizes(
8, this->oneof_decl(i), output);
}
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+ ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+ 9, this->reserved_range(i), output);
+ }
+
+ // repeated string reserved_name = 10;
+ for (int i = 0; i < this->reserved_name_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->reserved_name(i).data(), this->reserved_name(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.DescriptorProto.reserved_name");
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 10, this->reserved_name(i), output);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
@@ -2946,6 +3345,23 @@ void DescriptorProto::SerializeWithCachedSizes(
8, this->oneof_decl(i), target);
}
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteMessageNoVirtualToArray(
+ 9, this->reserved_range(i), target);
+ }
+
+ // repeated string reserved_name = 10;
+ for (int i = 0; i < this->reserved_name_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->reserved_name(i).data(), this->reserved_name(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.DescriptorProto.reserved_name");
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteStringToArray(10, this->reserved_name(i), target);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -3021,6 +3437,21 @@ int DescriptorProto::ByteSize() const {
this->oneof_decl(i));
}
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ total_size += 1 * this->reserved_range_size();
+ for (int i = 0; i < this->reserved_range_size(); i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->reserved_range(i));
+ }
+
+ // repeated string reserved_name = 10;
+ total_size += 1 * this->reserved_name_size();
+ for (int i = 0; i < this->reserved_name_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->reserved_name(i));
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@@ -3034,9 +3465,9 @@ int DescriptorProto::ByteSize() const {
void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const DescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const DescriptorProto*>(
- &from);
+ const DescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -3052,6 +3483,8 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) {
enum_type_.MergeFrom(from.enum_type_);
extension_range_.MergeFrom(from.extension_range_);
oneof_decl_.MergeFrom(from.oneof_decl_);
+ reserved_range_.MergeFrom(from.reserved_range_);
+ reserved_name_.MergeFrom(from.reserved_name_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -3103,6 +3536,8 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
extension_range_.UnsafeArenaSwap(&other->extension_range_);
oneof_decl_.UnsafeArenaSwap(&other->oneof_decl_);
std::swap(options_, other->options_);
+ reserved_range_.UnsafeArenaSwap(&other->reserved_range_);
+ reserved_name_.UnsafeArenaSwap(&other->reserved_name_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
@@ -3120,16 +3555,16 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
// DescriptorProto_ExtensionRange
// optional int32 start = 1;
- bool DescriptorProto_ExtensionRange::has_start() const {
+bool DescriptorProto_ExtensionRange::has_start() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void DescriptorProto_ExtensionRange::set_has_start() {
+void DescriptorProto_ExtensionRange::set_has_start() {
_has_bits_[0] |= 0x00000001u;
}
- void DescriptorProto_ExtensionRange::clear_has_start() {
+void DescriptorProto_ExtensionRange::clear_has_start() {
_has_bits_[0] &= ~0x00000001u;
}
- void DescriptorProto_ExtensionRange::clear_start() {
+void DescriptorProto_ExtensionRange::clear_start() {
start_ = 0;
clear_has_start();
}
@@ -3144,16 +3579,16 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
}
// optional int32 end = 2;
- bool DescriptorProto_ExtensionRange::has_end() const {
+bool DescriptorProto_ExtensionRange::has_end() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void DescriptorProto_ExtensionRange::set_has_end() {
+void DescriptorProto_ExtensionRange::set_has_end() {
_has_bits_[0] |= 0x00000002u;
}
- void DescriptorProto_ExtensionRange::clear_has_end() {
+void DescriptorProto_ExtensionRange::clear_has_end() {
_has_bits_[0] &= ~0x00000002u;
}
- void DescriptorProto_ExtensionRange::clear_end() {
+void DescriptorProto_ExtensionRange::clear_end() {
end_ = 0;
clear_has_end();
}
@@ -3169,19 +3604,71 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
// -------------------------------------------------------------------
+// DescriptorProto_ReservedRange
+
+// optional int32 start = 1;
+bool DescriptorProto_ReservedRange::has_start() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto_ReservedRange::set_has_start() {
+ _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto_ReservedRange::clear_has_start() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto_ReservedRange::clear_start() {
+ start_ = 0;
+ clear_has_start();
+}
+ ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start)
+ return start_;
+}
+ void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) {
+ set_has_start();
+ start_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start)
+}
+
+// optional int32 end = 2;
+bool DescriptorProto_ReservedRange::has_end() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+void DescriptorProto_ReservedRange::set_has_end() {
+ _has_bits_[0] |= 0x00000002u;
+}
+void DescriptorProto_ReservedRange::clear_has_end() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+void DescriptorProto_ReservedRange::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+ ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end)
+ return end_;
+}
+ void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end)
+}
+
+// -------------------------------------------------------------------
+
// DescriptorProto
// optional string name = 1;
- bool DescriptorProto::has_name() const {
+bool DescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void DescriptorProto::set_has_name() {
+void DescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void DescriptorProto::clear_has_name() {
+void DescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void DescriptorProto::clear_name() {
+void DescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -3225,10 +3712,10 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
}
// repeated .google.protobuf.FieldDescriptorProto field = 2;
- int DescriptorProto::field_size() const {
+int DescriptorProto::field_size() const {
return field_.size();
}
- void DescriptorProto::clear_field() {
+void DescriptorProto::clear_field() {
field_.Clear();
}
const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
@@ -3255,10 +3742,10 @@ DescriptorProto::mutable_field() {
}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
- int DescriptorProto::extension_size() const {
+int DescriptorProto::extension_size() const {
return extension_.size();
}
- void DescriptorProto::clear_extension() {
+void DescriptorProto::clear_extension() {
extension_.Clear();
}
const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
@@ -3285,10 +3772,10 @@ DescriptorProto::mutable_extension() {
}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
- int DescriptorProto::nested_type_size() const {
+int DescriptorProto::nested_type_size() const {
return nested_type_.size();
}
- void DescriptorProto::clear_nested_type() {
+void DescriptorProto::clear_nested_type() {
nested_type_.Clear();
}
const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
@@ -3315,10 +3802,10 @@ DescriptorProto::mutable_nested_type() {
}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
- int DescriptorProto::enum_type_size() const {
+int DescriptorProto::enum_type_size() const {
return enum_type_.size();
}
- void DescriptorProto::clear_enum_type() {
+void DescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
@@ -3345,10 +3832,10 @@ DescriptorProto::mutable_enum_type() {
}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
- int DescriptorProto::extension_range_size() const {
+int DescriptorProto::extension_range_size() const {
return extension_range_.size();
}
- void DescriptorProto::clear_extension_range() {
+void DescriptorProto::clear_extension_range() {
extension_range_.Clear();
}
const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
@@ -3375,10 +3862,10 @@ DescriptorProto::mutable_extension_range() {
}
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
- int DescriptorProto::oneof_decl_size() const {
+int DescriptorProto::oneof_decl_size() const {
return oneof_decl_.size();
}
- void DescriptorProto::clear_oneof_decl() {
+void DescriptorProto::clear_oneof_decl() {
oneof_decl_.Clear();
}
const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
@@ -3405,16 +3892,16 @@ DescriptorProto::mutable_oneof_decl() {
}
// optional .google.protobuf.MessageOptions options = 7;
- bool DescriptorProto::has_options() const {
+bool DescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000080u) != 0;
}
- void DescriptorProto::set_has_options() {
+void DescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000080u;
}
- void DescriptorProto::clear_has_options() {
+void DescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000080u;
}
- void DescriptorProto::clear_options() {
+void DescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
clear_has_options();
}
@@ -3447,6 +3934,90 @@ DescriptorProto::mutable_oneof_decl() {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
}
+// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+int DescriptorProto::reserved_range_size() const {
+ return reserved_range_.size();
+}
+void DescriptorProto::clear_reserved_range() {
+ reserved_range_.Clear();
+}
+ const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Get(index);
+}
+ ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+DescriptorProto::mutable_reserved_range() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
+ return &reserved_range_;
+}
+
+// repeated string reserved_name = 10;
+int DescriptorProto::reserved_name_size() const {
+ return reserved_name_.size();
+}
+void DescriptorProto::clear_reserved_name() {
+ reserved_name_.Clear();
+}
+ const ::std::string& DescriptorProto::reserved_name(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Get(index);
+}
+ ::std::string* DescriptorProto::mutable_reserved_name(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Mutable(index);
+}
+ void DescriptorProto::set_reserved_name(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
+ reserved_name_.Mutable(index)->assign(value);
+}
+ void DescriptorProto::set_reserved_name(int index, const char* value) {
+ reserved_name_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+ reserved_name_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+ ::std::string* DescriptorProto::add_reserved_name() {
+ return reserved_name_.Add();
+}
+ void DescriptorProto::add_reserved_name(const ::std::string& value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::add_reserved_name(const char* value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name)
+}
+ void DescriptorProto::add_reserved_name(const char* value, size_t size) {
+ reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+DescriptorProto::reserved_name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+DescriptorProto::mutable_reserved_name() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name)
+ return &reserved_name_;
+}
+
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -3540,7 +4111,7 @@ const int FieldDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
FieldDescriptorProto::FieldDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto)
}
@@ -4063,9 +4634,9 @@ int FieldDescriptorProto::ByteSize() const {
void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FieldDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FieldDescriptorProto*>(
- &from);
+ const FieldDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -4166,16 +4737,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
// FieldDescriptorProto
// optional string name = 1;
- bool FieldDescriptorProto::has_name() const {
+bool FieldDescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void FieldDescriptorProto::set_has_name() {
+void FieldDescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void FieldDescriptorProto::clear_has_name() {
+void FieldDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void FieldDescriptorProto::clear_name() {
+void FieldDescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -4219,16 +4790,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional int32 number = 3;
- bool FieldDescriptorProto::has_number() const {
+bool FieldDescriptorProto::has_number() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void FieldDescriptorProto::set_has_number() {
+void FieldDescriptorProto::set_has_number() {
_has_bits_[0] |= 0x00000002u;
}
- void FieldDescriptorProto::clear_has_number() {
+void FieldDescriptorProto::clear_has_number() {
_has_bits_[0] &= ~0x00000002u;
}
- void FieldDescriptorProto::clear_number() {
+void FieldDescriptorProto::clear_number() {
number_ = 0;
clear_has_number();
}
@@ -4243,16 +4814,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
- bool FieldDescriptorProto::has_label() const {
+bool FieldDescriptorProto::has_label() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void FieldDescriptorProto::set_has_label() {
+void FieldDescriptorProto::set_has_label() {
_has_bits_[0] |= 0x00000004u;
}
- void FieldDescriptorProto::clear_has_label() {
+void FieldDescriptorProto::clear_has_label() {
_has_bits_[0] &= ~0x00000004u;
}
- void FieldDescriptorProto::clear_label() {
+void FieldDescriptorProto::clear_label() {
label_ = 1;
clear_has_label();
}
@@ -4268,16 +4839,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
- bool FieldDescriptorProto::has_type() const {
+bool FieldDescriptorProto::has_type() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
- void FieldDescriptorProto::set_has_type() {
+void FieldDescriptorProto::set_has_type() {
_has_bits_[0] |= 0x00000008u;
}
- void FieldDescriptorProto::clear_has_type() {
+void FieldDescriptorProto::clear_has_type() {
_has_bits_[0] &= ~0x00000008u;
}
- void FieldDescriptorProto::clear_type() {
+void FieldDescriptorProto::clear_type() {
type_ = 1;
clear_has_type();
}
@@ -4293,16 +4864,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional string type_name = 6;
- bool FieldDescriptorProto::has_type_name() const {
+bool FieldDescriptorProto::has_type_name() const {
return (_has_bits_[0] & 0x00000010u) != 0;
}
- void FieldDescriptorProto::set_has_type_name() {
+void FieldDescriptorProto::set_has_type_name() {
_has_bits_[0] |= 0x00000010u;
}
- void FieldDescriptorProto::clear_has_type_name() {
+void FieldDescriptorProto::clear_has_type_name() {
_has_bits_[0] &= ~0x00000010u;
}
- void FieldDescriptorProto::clear_type_name() {
+void FieldDescriptorProto::clear_type_name() {
type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_type_name();
}
@@ -4346,16 +4917,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional string extendee = 2;
- bool FieldDescriptorProto::has_extendee() const {
+bool FieldDescriptorProto::has_extendee() const {
return (_has_bits_[0] & 0x00000020u) != 0;
}
- void FieldDescriptorProto::set_has_extendee() {
+void FieldDescriptorProto::set_has_extendee() {
_has_bits_[0] |= 0x00000020u;
}
- void FieldDescriptorProto::clear_has_extendee() {
+void FieldDescriptorProto::clear_has_extendee() {
_has_bits_[0] &= ~0x00000020u;
}
- void FieldDescriptorProto::clear_extendee() {
+void FieldDescriptorProto::clear_extendee() {
extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_extendee();
}
@@ -4399,16 +4970,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional string default_value = 7;
- bool FieldDescriptorProto::has_default_value() const {
+bool FieldDescriptorProto::has_default_value() const {
return (_has_bits_[0] & 0x00000040u) != 0;
}
- void FieldDescriptorProto::set_has_default_value() {
+void FieldDescriptorProto::set_has_default_value() {
_has_bits_[0] |= 0x00000040u;
}
- void FieldDescriptorProto::clear_has_default_value() {
+void FieldDescriptorProto::clear_has_default_value() {
_has_bits_[0] &= ~0x00000040u;
}
- void FieldDescriptorProto::clear_default_value() {
+void FieldDescriptorProto::clear_default_value() {
default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_default_value();
}
@@ -4452,16 +5023,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional int32 oneof_index = 9;
- bool FieldDescriptorProto::has_oneof_index() const {
+bool FieldDescriptorProto::has_oneof_index() const {
return (_has_bits_[0] & 0x00000080u) != 0;
}
- void FieldDescriptorProto::set_has_oneof_index() {
+void FieldDescriptorProto::set_has_oneof_index() {
_has_bits_[0] |= 0x00000080u;
}
- void FieldDescriptorProto::clear_has_oneof_index() {
+void FieldDescriptorProto::clear_has_oneof_index() {
_has_bits_[0] &= ~0x00000080u;
}
- void FieldDescriptorProto::clear_oneof_index() {
+void FieldDescriptorProto::clear_oneof_index() {
oneof_index_ = 0;
clear_has_oneof_index();
}
@@ -4476,16 +5047,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
}
// optional .google.protobuf.FieldOptions options = 8;
- bool FieldDescriptorProto::has_options() const {
+bool FieldDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000100u) != 0;
}
- void FieldDescriptorProto::set_has_options() {
+void FieldDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000100u;
}
- void FieldDescriptorProto::clear_has_options() {
+void FieldDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000100u;
}
- void FieldDescriptorProto::clear_options() {
+void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
clear_has_options();
}
@@ -4527,7 +5098,7 @@ const int OneofDescriptorProto::kNameFieldNumber;
#endif // !_MSC_VER
OneofDescriptorProto::OneofDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto)
}
@@ -4709,9 +5280,9 @@ int OneofDescriptorProto::ByteSize() const {
void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const OneofDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const OneofDescriptorProto*>(
- &from);
+ const OneofDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -4772,16 +5343,16 @@ void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
// OneofDescriptorProto
// optional string name = 1;
- bool OneofDescriptorProto::has_name() const {
+bool OneofDescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void OneofDescriptorProto::set_has_name() {
+void OneofDescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void OneofDescriptorProto::clear_has_name() {
+void OneofDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void OneofDescriptorProto::clear_name() {
+void OneofDescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -4835,7 +5406,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumDescriptorProto::EnumDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto)
}
@@ -4943,12 +5514,15 @@ bool EnumDescriptorProto::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_value:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_value:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_value()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_value;
+ if (input->ExpectTag(18)) goto parse_loop_value;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(26)) goto parse_options;
break;
}
@@ -5096,9 +5670,9 @@ int EnumDescriptorProto::ByteSize() const {
void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumDescriptorProto*>(
- &from);
+ const EnumDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -5169,16 +5743,16 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
// EnumDescriptorProto
// optional string name = 1;
- bool EnumDescriptorProto::has_name() const {
+bool EnumDescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void EnumDescriptorProto::set_has_name() {
+void EnumDescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void EnumDescriptorProto::clear_has_name() {
+void EnumDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void EnumDescriptorProto::clear_name() {
+void EnumDescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -5222,10 +5796,10 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
}
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
- int EnumDescriptorProto::value_size() const {
+int EnumDescriptorProto::value_size() const {
return value_.size();
}
- void EnumDescriptorProto::clear_value() {
+void EnumDescriptorProto::clear_value() {
value_.Clear();
}
const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
@@ -5252,16 +5826,16 @@ EnumDescriptorProto::mutable_value() {
}
// optional .google.protobuf.EnumOptions options = 3;
- bool EnumDescriptorProto::has_options() const {
+bool EnumDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void EnumDescriptorProto::set_has_options() {
+void EnumDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000004u;
}
- void EnumDescriptorProto::clear_has_options() {
+void EnumDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000004u;
}
- void EnumDescriptorProto::clear_options() {
+void EnumDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
clear_has_options();
}
@@ -5305,7 +5879,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumValueDescriptorProto::EnumValueDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto)
}
@@ -5564,9 +6138,9 @@ int EnumValueDescriptorProto::ByteSize() const {
void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumValueDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumValueDescriptorProto*>(
- &from);
+ const EnumValueDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -5638,16 +6212,16 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
// EnumValueDescriptorProto
// optional string name = 1;
- bool EnumValueDescriptorProto::has_name() const {
+bool EnumValueDescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void EnumValueDescriptorProto::set_has_name() {
+void EnumValueDescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void EnumValueDescriptorProto::clear_has_name() {
+void EnumValueDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void EnumValueDescriptorProto::clear_name() {
+void EnumValueDescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -5691,16 +6265,16 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
}
// optional int32 number = 2;
- bool EnumValueDescriptorProto::has_number() const {
+bool EnumValueDescriptorProto::has_number() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void EnumValueDescriptorProto::set_has_number() {
+void EnumValueDescriptorProto::set_has_number() {
_has_bits_[0] |= 0x00000002u;
}
- void EnumValueDescriptorProto::clear_has_number() {
+void EnumValueDescriptorProto::clear_has_number() {
_has_bits_[0] &= ~0x00000002u;
}
- void EnumValueDescriptorProto::clear_number() {
+void EnumValueDescriptorProto::clear_number() {
number_ = 0;
clear_has_number();
}
@@ -5715,16 +6289,16 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
}
// optional .google.protobuf.EnumValueOptions options = 3;
- bool EnumValueDescriptorProto::has_options() const {
+bool EnumValueDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void EnumValueDescriptorProto::set_has_options() {
+void EnumValueDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000004u;
}
- void EnumValueDescriptorProto::clear_has_options() {
+void EnumValueDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000004u;
}
- void EnumValueDescriptorProto::clear_options() {
+void EnumValueDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
clear_has_options();
}
@@ -5768,7 +6342,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber;
#endif // !_MSC_VER
ServiceDescriptorProto::ServiceDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto)
}
@@ -5876,12 +6450,15 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_method:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_method:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_method()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_method;
+ if (input->ExpectTag(18)) goto parse_loop_method;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(26)) goto parse_options;
break;
}
@@ -6029,9 +6606,9 @@ int ServiceDescriptorProto::ByteSize() const {
void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const ServiceDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const ServiceDescriptorProto*>(
- &from);
+ const ServiceDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -6102,16 +6679,16 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
// ServiceDescriptorProto
// optional string name = 1;
- bool ServiceDescriptorProto::has_name() const {
+bool ServiceDescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void ServiceDescriptorProto::set_has_name() {
+void ServiceDescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void ServiceDescriptorProto::clear_has_name() {
+void ServiceDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void ServiceDescriptorProto::clear_name() {
+void ServiceDescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -6155,10 +6732,10 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
}
// repeated .google.protobuf.MethodDescriptorProto method = 2;
- int ServiceDescriptorProto::method_size() const {
+int ServiceDescriptorProto::method_size() const {
return method_.size();
}
- void ServiceDescriptorProto::clear_method() {
+void ServiceDescriptorProto::clear_method() {
method_.Clear();
}
const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
@@ -6185,16 +6762,16 @@ ServiceDescriptorProto::mutable_method() {
}
// optional .google.protobuf.ServiceOptions options = 3;
- bool ServiceDescriptorProto::has_options() const {
+bool ServiceDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void ServiceDescriptorProto::set_has_options() {
+void ServiceDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000004u;
}
- void ServiceDescriptorProto::clear_has_options() {
+void ServiceDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000004u;
}
- void ServiceDescriptorProto::clear_options() {
+void ServiceDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
clear_has_options();
}
@@ -6241,7 +6818,7 @@ const int MethodDescriptorProto::kServerStreamingFieldNumber;
#endif // !_MSC_VER
MethodDescriptorProto::MethodDescriptorProto()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto)
}
@@ -6641,9 +7218,9 @@ int MethodDescriptorProto::ByteSize() const {
void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const MethodDescriptorProto* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const MethodDescriptorProto*>(
- &from);
+ const MethodDescriptorProto* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -6729,16 +7306,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
// MethodDescriptorProto
// optional string name = 1;
- bool MethodDescriptorProto::has_name() const {
+bool MethodDescriptorProto::has_name() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void MethodDescriptorProto::set_has_name() {
+void MethodDescriptorProto::set_has_name() {
_has_bits_[0] |= 0x00000001u;
}
- void MethodDescriptorProto::clear_has_name() {
+void MethodDescriptorProto::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
- void MethodDescriptorProto::clear_name() {
+void MethodDescriptorProto::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
@@ -6782,16 +7359,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
}
// optional string input_type = 2;
- bool MethodDescriptorProto::has_input_type() const {
+bool MethodDescriptorProto::has_input_type() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void MethodDescriptorProto::set_has_input_type() {
+void MethodDescriptorProto::set_has_input_type() {
_has_bits_[0] |= 0x00000002u;
}
- void MethodDescriptorProto::clear_has_input_type() {
+void MethodDescriptorProto::clear_has_input_type() {
_has_bits_[0] &= ~0x00000002u;
}
- void MethodDescriptorProto::clear_input_type() {
+void MethodDescriptorProto::clear_input_type() {
input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_input_type();
}
@@ -6835,16 +7412,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
}
// optional string output_type = 3;
- bool MethodDescriptorProto::has_output_type() const {
+bool MethodDescriptorProto::has_output_type() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void MethodDescriptorProto::set_has_output_type() {
+void MethodDescriptorProto::set_has_output_type() {
_has_bits_[0] |= 0x00000004u;
}
- void MethodDescriptorProto::clear_has_output_type() {
+void MethodDescriptorProto::clear_has_output_type() {
_has_bits_[0] &= ~0x00000004u;
}
- void MethodDescriptorProto::clear_output_type() {
+void MethodDescriptorProto::clear_output_type() {
output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_output_type();
}
@@ -6888,16 +7465,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
}
// optional .google.protobuf.MethodOptions options = 4;
- bool MethodDescriptorProto::has_options() const {
+bool MethodDescriptorProto::has_options() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
- void MethodDescriptorProto::set_has_options() {
+void MethodDescriptorProto::set_has_options() {
_has_bits_[0] |= 0x00000008u;
}
- void MethodDescriptorProto::clear_has_options() {
+void MethodDescriptorProto::clear_has_options() {
_has_bits_[0] &= ~0x00000008u;
}
- void MethodDescriptorProto::clear_options() {
+void MethodDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
clear_has_options();
}
@@ -6931,16 +7508,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
}
// optional bool client_streaming = 5 [default = false];
- bool MethodDescriptorProto::has_client_streaming() const {
+bool MethodDescriptorProto::has_client_streaming() const {
return (_has_bits_[0] & 0x00000010u) != 0;
}
- void MethodDescriptorProto::set_has_client_streaming() {
+void MethodDescriptorProto::set_has_client_streaming() {
_has_bits_[0] |= 0x00000010u;
}
- void MethodDescriptorProto::clear_has_client_streaming() {
+void MethodDescriptorProto::clear_has_client_streaming() {
_has_bits_[0] &= ~0x00000010u;
}
- void MethodDescriptorProto::clear_client_streaming() {
+void MethodDescriptorProto::clear_client_streaming() {
client_streaming_ = false;
clear_has_client_streaming();
}
@@ -6955,16 +7532,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
}
// optional bool server_streaming = 6 [default = false];
- bool MethodDescriptorProto::has_server_streaming() const {
+bool MethodDescriptorProto::has_server_streaming() const {
return (_has_bits_[0] & 0x00000020u) != 0;
}
- void MethodDescriptorProto::set_has_server_streaming() {
+void MethodDescriptorProto::set_has_server_streaming() {
_has_bits_[0] |= 0x00000020u;
}
- void MethodDescriptorProto::clear_has_server_streaming() {
+void MethodDescriptorProto::clear_has_server_streaming() {
_has_bits_[0] &= ~0x00000020u;
}
- void MethodDescriptorProto::clear_server_streaming() {
+void MethodDescriptorProto::clear_server_streaming() {
server_streaming_ = false;
clear_has_server_streaming();
}
@@ -7024,7 +7601,7 @@ const int FileOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FileOptions::FileOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FileOptions)
}
@@ -7381,12 +7958,15 @@ bool FileOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -7768,9 +8348,9 @@ int FileOptions::ByteSize() const {
void FileOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FileOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FileOptions*>(
- &from);
+ const FileOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -7895,16 +8475,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
// FileOptions
// optional string java_package = 1;
- bool FileOptions::has_java_package() const {
+bool FileOptions::has_java_package() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void FileOptions::set_has_java_package() {
+void FileOptions::set_has_java_package() {
_has_bits_[0] |= 0x00000001u;
}
- void FileOptions::clear_has_java_package() {
+void FileOptions::clear_has_java_package() {
_has_bits_[0] &= ~0x00000001u;
}
- void FileOptions::clear_java_package() {
+void FileOptions::clear_java_package() {
java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_java_package();
}
@@ -7948,16 +8528,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional string java_outer_classname = 8;
- bool FileOptions::has_java_outer_classname() const {
+bool FileOptions::has_java_outer_classname() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void FileOptions::set_has_java_outer_classname() {
+void FileOptions::set_has_java_outer_classname() {
_has_bits_[0] |= 0x00000002u;
}
- void FileOptions::clear_has_java_outer_classname() {
+void FileOptions::clear_has_java_outer_classname() {
_has_bits_[0] &= ~0x00000002u;
}
- void FileOptions::clear_java_outer_classname() {
+void FileOptions::clear_java_outer_classname() {
java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_java_outer_classname();
}
@@ -8001,16 +8581,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool java_multiple_files = 10 [default = false];
- bool FileOptions::has_java_multiple_files() const {
+bool FileOptions::has_java_multiple_files() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void FileOptions::set_has_java_multiple_files() {
+void FileOptions::set_has_java_multiple_files() {
_has_bits_[0] |= 0x00000004u;
}
- void FileOptions::clear_has_java_multiple_files() {
+void FileOptions::clear_has_java_multiple_files() {
_has_bits_[0] &= ~0x00000004u;
}
- void FileOptions::clear_java_multiple_files() {
+void FileOptions::clear_java_multiple_files() {
java_multiple_files_ = false;
clear_has_java_multiple_files();
}
@@ -8025,16 +8605,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool java_generate_equals_and_hash = 20 [default = false];
- bool FileOptions::has_java_generate_equals_and_hash() const {
+bool FileOptions::has_java_generate_equals_and_hash() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
- void FileOptions::set_has_java_generate_equals_and_hash() {
+void FileOptions::set_has_java_generate_equals_and_hash() {
_has_bits_[0] |= 0x00000008u;
}
- void FileOptions::clear_has_java_generate_equals_and_hash() {
+void FileOptions::clear_has_java_generate_equals_and_hash() {
_has_bits_[0] &= ~0x00000008u;
}
- void FileOptions::clear_java_generate_equals_and_hash() {
+void FileOptions::clear_java_generate_equals_and_hash() {
java_generate_equals_and_hash_ = false;
clear_has_java_generate_equals_and_hash();
}
@@ -8049,16 +8629,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool java_string_check_utf8 = 27 [default = false];
- bool FileOptions::has_java_string_check_utf8() const {
+bool FileOptions::has_java_string_check_utf8() const {
return (_has_bits_[0] & 0x00000010u) != 0;
}
- void FileOptions::set_has_java_string_check_utf8() {
+void FileOptions::set_has_java_string_check_utf8() {
_has_bits_[0] |= 0x00000010u;
}
- void FileOptions::clear_has_java_string_check_utf8() {
+void FileOptions::clear_has_java_string_check_utf8() {
_has_bits_[0] &= ~0x00000010u;
}
- void FileOptions::clear_java_string_check_utf8() {
+void FileOptions::clear_java_string_check_utf8() {
java_string_check_utf8_ = false;
clear_has_java_string_check_utf8();
}
@@ -8073,16 +8653,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
- bool FileOptions::has_optimize_for() const {
+bool FileOptions::has_optimize_for() const {
return (_has_bits_[0] & 0x00000020u) != 0;
}
- void FileOptions::set_has_optimize_for() {
+void FileOptions::set_has_optimize_for() {
_has_bits_[0] |= 0x00000020u;
}
- void FileOptions::clear_has_optimize_for() {
+void FileOptions::clear_has_optimize_for() {
_has_bits_[0] &= ~0x00000020u;
}
- void FileOptions::clear_optimize_for() {
+void FileOptions::clear_optimize_for() {
optimize_for_ = 1;
clear_has_optimize_for();
}
@@ -8098,16 +8678,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional string go_package = 11;
- bool FileOptions::has_go_package() const {
+bool FileOptions::has_go_package() const {
return (_has_bits_[0] & 0x00000040u) != 0;
}
- void FileOptions::set_has_go_package() {
+void FileOptions::set_has_go_package() {
_has_bits_[0] |= 0x00000040u;
}
- void FileOptions::clear_has_go_package() {
+void FileOptions::clear_has_go_package() {
_has_bits_[0] &= ~0x00000040u;
}
- void FileOptions::clear_go_package() {
+void FileOptions::clear_go_package() {
go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_go_package();
}
@@ -8151,16 +8731,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool cc_generic_services = 16 [default = false];
- bool FileOptions::has_cc_generic_services() const {
+bool FileOptions::has_cc_generic_services() const {
return (_has_bits_[0] & 0x00000080u) != 0;
}
- void FileOptions::set_has_cc_generic_services() {
+void FileOptions::set_has_cc_generic_services() {
_has_bits_[0] |= 0x00000080u;
}
- void FileOptions::clear_has_cc_generic_services() {
+void FileOptions::clear_has_cc_generic_services() {
_has_bits_[0] &= ~0x00000080u;
}
- void FileOptions::clear_cc_generic_services() {
+void FileOptions::clear_cc_generic_services() {
cc_generic_services_ = false;
clear_has_cc_generic_services();
}
@@ -8175,16 +8755,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool java_generic_services = 17 [default = false];
- bool FileOptions::has_java_generic_services() const {
+bool FileOptions::has_java_generic_services() const {
return (_has_bits_[0] & 0x00000100u) != 0;
}
- void FileOptions::set_has_java_generic_services() {
+void FileOptions::set_has_java_generic_services() {
_has_bits_[0] |= 0x00000100u;
}
- void FileOptions::clear_has_java_generic_services() {
+void FileOptions::clear_has_java_generic_services() {
_has_bits_[0] &= ~0x00000100u;
}
- void FileOptions::clear_java_generic_services() {
+void FileOptions::clear_java_generic_services() {
java_generic_services_ = false;
clear_has_java_generic_services();
}
@@ -8199,16 +8779,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool py_generic_services = 18 [default = false];
- bool FileOptions::has_py_generic_services() const {
+bool FileOptions::has_py_generic_services() const {
return (_has_bits_[0] & 0x00000200u) != 0;
}
- void FileOptions::set_has_py_generic_services() {
+void FileOptions::set_has_py_generic_services() {
_has_bits_[0] |= 0x00000200u;
}
- void FileOptions::clear_has_py_generic_services() {
+void FileOptions::clear_has_py_generic_services() {
_has_bits_[0] &= ~0x00000200u;
}
- void FileOptions::clear_py_generic_services() {
+void FileOptions::clear_py_generic_services() {
py_generic_services_ = false;
clear_has_py_generic_services();
}
@@ -8223,16 +8803,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool deprecated = 23 [default = false];
- bool FileOptions::has_deprecated() const {
+bool FileOptions::has_deprecated() const {
return (_has_bits_[0] & 0x00000400u) != 0;
}
- void FileOptions::set_has_deprecated() {
+void FileOptions::set_has_deprecated() {
_has_bits_[0] |= 0x00000400u;
}
- void FileOptions::clear_has_deprecated() {
+void FileOptions::clear_has_deprecated() {
_has_bits_[0] &= ~0x00000400u;
}
- void FileOptions::clear_deprecated() {
+void FileOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
}
@@ -8247,16 +8827,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional bool cc_enable_arenas = 31 [default = false];
- bool FileOptions::has_cc_enable_arenas() const {
+bool FileOptions::has_cc_enable_arenas() const {
return (_has_bits_[0] & 0x00000800u) != 0;
}
- void FileOptions::set_has_cc_enable_arenas() {
+void FileOptions::set_has_cc_enable_arenas() {
_has_bits_[0] |= 0x00000800u;
}
- void FileOptions::clear_has_cc_enable_arenas() {
+void FileOptions::clear_has_cc_enable_arenas() {
_has_bits_[0] &= ~0x00000800u;
}
- void FileOptions::clear_cc_enable_arenas() {
+void FileOptions::clear_cc_enable_arenas() {
cc_enable_arenas_ = false;
clear_has_cc_enable_arenas();
}
@@ -8271,16 +8851,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional string objc_class_prefix = 36;
- bool FileOptions::has_objc_class_prefix() const {
+bool FileOptions::has_objc_class_prefix() const {
return (_has_bits_[0] & 0x00001000u) != 0;
}
- void FileOptions::set_has_objc_class_prefix() {
+void FileOptions::set_has_objc_class_prefix() {
_has_bits_[0] |= 0x00001000u;
}
- void FileOptions::clear_has_objc_class_prefix() {
+void FileOptions::clear_has_objc_class_prefix() {
_has_bits_[0] &= ~0x00001000u;
}
- void FileOptions::clear_objc_class_prefix() {
+void FileOptions::clear_objc_class_prefix() {
objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_objc_class_prefix();
}
@@ -8324,16 +8904,16 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// optional string csharp_namespace = 37;
- bool FileOptions::has_csharp_namespace() const {
+bool FileOptions::has_csharp_namespace() const {
return (_has_bits_[0] & 0x00002000u) != 0;
}
- void FileOptions::set_has_csharp_namespace() {
+void FileOptions::set_has_csharp_namespace() {
_has_bits_[0] |= 0x00002000u;
}
- void FileOptions::clear_has_csharp_namespace() {
+void FileOptions::clear_has_csharp_namespace() {
_has_bits_[0] &= ~0x00002000u;
}
- void FileOptions::clear_csharp_namespace() {
+void FileOptions::clear_csharp_namespace() {
csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_csharp_namespace();
}
@@ -8377,10 +8957,10 @@ void FileOptions::InternalSwap(FileOptions* other) {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- int FileOptions::uninterpreted_option_size() const {
+int FileOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
}
- void FileOptions::clear_uninterpreted_option() {
+void FileOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
@@ -8419,7 +8999,7 @@ const int MessageOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MessageOptions::MessageOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MessageOptions)
}
@@ -8574,12 +9154,15 @@ bool MessageOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -8741,9 +9324,9 @@ int MessageOptions::ByteSize() const {
void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const MessageOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const MessageOptions*>(
- &from);
+ const MessageOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -8821,16 +9404,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) {
// MessageOptions
// optional bool message_set_wire_format = 1 [default = false];
- bool MessageOptions::has_message_set_wire_format() const {
+bool MessageOptions::has_message_set_wire_format() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void MessageOptions::set_has_message_set_wire_format() {
+void MessageOptions::set_has_message_set_wire_format() {
_has_bits_[0] |= 0x00000001u;
}
- void MessageOptions::clear_has_message_set_wire_format() {
+void MessageOptions::clear_has_message_set_wire_format() {
_has_bits_[0] &= ~0x00000001u;
}
- void MessageOptions::clear_message_set_wire_format() {
+void MessageOptions::clear_message_set_wire_format() {
message_set_wire_format_ = false;
clear_has_message_set_wire_format();
}
@@ -8845,16 +9428,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) {
}
// optional bool no_standard_descriptor_accessor = 2 [default = false];
- bool MessageOptions::has_no_standard_descriptor_accessor() const {
+bool MessageOptions::has_no_standard_descriptor_accessor() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void MessageOptions::set_has_no_standard_descriptor_accessor() {
+void MessageOptions::set_has_no_standard_descriptor_accessor() {
_has_bits_[0] |= 0x00000002u;
}
- void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+void MessageOptions::clear_has_no_standard_descriptor_accessor() {
_has_bits_[0] &= ~0x00000002u;
}
- void MessageOptions::clear_no_standard_descriptor_accessor() {
+void MessageOptions::clear_no_standard_descriptor_accessor() {
no_standard_descriptor_accessor_ = false;
clear_has_no_standard_descriptor_accessor();
}
@@ -8869,16 +9452,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) {
}
// optional bool deprecated = 3 [default = false];
- bool MessageOptions::has_deprecated() const {
+bool MessageOptions::has_deprecated() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void MessageOptions::set_has_deprecated() {
+void MessageOptions::set_has_deprecated() {
_has_bits_[0] |= 0x00000004u;
}
- void MessageOptions::clear_has_deprecated() {
+void MessageOptions::clear_has_deprecated() {
_has_bits_[0] &= ~0x00000004u;
}
- void MessageOptions::clear_deprecated() {
+void MessageOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
}
@@ -8893,16 +9476,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) {
}
// optional bool map_entry = 7;
- bool MessageOptions::has_map_entry() const {
+bool MessageOptions::has_map_entry() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
- void MessageOptions::set_has_map_entry() {
+void MessageOptions::set_has_map_entry() {
_has_bits_[0] |= 0x00000008u;
}
- void MessageOptions::clear_has_map_entry() {
+void MessageOptions::clear_has_map_entry() {
_has_bits_[0] &= ~0x00000008u;
}
- void MessageOptions::clear_map_entry() {
+void MessageOptions::clear_map_entry() {
map_entry_ = false;
clear_has_map_entry();
}
@@ -8917,10 +9500,10 @@ void MessageOptions::InternalSwap(MessageOptions* other) {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- int MessageOptions::uninterpreted_option_size() const {
+int MessageOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
}
- void MessageOptions::clear_uninterpreted_option() {
+void MessageOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
@@ -8973,9 +9556,33 @@ const FieldOptions_CType FieldOptions::CType_MIN;
const FieldOptions_CType FieldOptions::CType_MAX;
const int FieldOptions::CType_ARRAYSIZE;
#endif // _MSC_VER
+const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor() {
+ protobuf_AssignDescriptorsOnce();
+ return FieldOptions_JSType_descriptor_;
+}
+bool FieldOptions_JSType_IsValid(int value) {
+ switch(value) {
+ case 0:
+ case 1:
+ case 2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#ifndef _MSC_VER
+const FieldOptions_JSType FieldOptions::JS_NORMAL;
+const FieldOptions_JSType FieldOptions::JS_STRING;
+const FieldOptions_JSType FieldOptions::JS_NUMBER;
+const FieldOptions_JSType FieldOptions::JSType_MIN;
+const FieldOptions_JSType FieldOptions::JSType_MAX;
+const int FieldOptions::JSType_ARRAYSIZE;
+#endif // _MSC_VER
#ifndef _MSC_VER
const int FieldOptions::kCtypeFieldNumber;
const int FieldOptions::kPackedFieldNumber;
+const int FieldOptions::kJstypeFieldNumber;
const int FieldOptions::kLazyFieldNumber;
const int FieldOptions::kDeprecatedFieldNumber;
const int FieldOptions::kWeakFieldNumber;
@@ -8983,7 +9590,7 @@ const int FieldOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
FieldOptions::FieldOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FieldOptions)
}
@@ -9003,6 +9610,7 @@ void FieldOptions::SharedCtor() {
_cached_size_ = 0;
ctype_ = 0;
packed_ = false;
+ jstype_ = 0;
lazy_ = false;
deprecated_ = false;
weak_ = false;
@@ -9054,8 +9662,9 @@ void FieldOptions::Clear() {
ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
} while (0)
- if (_has_bits_[0 / 32] & 31u) {
- ZR_(ctype_, weak_);
+ if (_has_bits_[0 / 32] & 63u) {
+ ZR_(ctype_, jstype_);
+ ZR_(packed_, weak_);
}
#undef ZR_HELPER_
@@ -9138,6 +9747,26 @@ bool FieldOptions::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(48)) goto parse_jstype;
+ break;
+ }
+
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ case 6: {
+ if (tag == 48) {
+ parse_jstype:
+ int value;
+ DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
+ input, &value)));
+ if (::google::protobuf::FieldOptions_JSType_IsValid(value)) {
+ set_jstype(static_cast< ::google::protobuf::FieldOptions_JSType >(value));
+ } else {
+ mutable_unknown_fields()->AddVarint(6, value);
+ }
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectTag(80)) goto parse_weak;
break;
}
@@ -9161,12 +9790,15 @@ bool FieldOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -9222,6 +9854,12 @@ void FieldOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output);
}
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ if (has_jstype()) {
+ ::google::protobuf::internal::WireFormatLite::WriteEnum(
+ 6, this->jstype(), output);
+ }
+
// optional bool weak = 10 [default = false];
if (has_weak()) {
::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output);
@@ -9268,6 +9906,12 @@ void FieldOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target);
}
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ if (has_jstype()) {
+ target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+ 6, this->jstype(), target);
+ }
+
// optional bool weak = 10 [default = false];
if (has_weak()) {
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target);
@@ -9295,7 +9939,7 @@ void FieldOptions::SerializeWithCachedSizes(
int FieldOptions::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & 31) {
+ if (_has_bits_[0 / 32] & 63) {
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
if (has_ctype()) {
total_size += 1 +
@@ -9307,6 +9951,12 @@ int FieldOptions::ByteSize() const {
total_size += 1 + 1;
}
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ if (has_jstype()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::EnumSize(this->jstype());
+ }
+
// optional bool lazy = 5 [default = false];
if (has_lazy()) {
total_size += 1 + 1;
@@ -9346,9 +9996,9 @@ int FieldOptions::ByteSize() const {
void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FieldOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FieldOptions*>(
- &from);
+ const FieldOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -9366,6 +10016,9 @@ void FieldOptions::MergeFrom(const FieldOptions& from) {
if (from.has_packed()) {
set_packed(from.packed());
}
+ if (from.has_jstype()) {
+ set_jstype(from.jstype());
+ }
if (from.has_lazy()) {
set_lazy(from.lazy());
}
@@ -9408,6 +10061,7 @@ void FieldOptions::Swap(FieldOptions* other) {
void FieldOptions::InternalSwap(FieldOptions* other) {
std::swap(ctype_, other->ctype_);
std::swap(packed_, other->packed_);
+ std::swap(jstype_, other->jstype_);
std::swap(lazy_, other->lazy_);
std::swap(deprecated_, other->deprecated_);
std::swap(weak_, other->weak_);
@@ -9430,16 +10084,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
// FieldOptions
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
- bool FieldOptions::has_ctype() const {
+bool FieldOptions::has_ctype() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void FieldOptions::set_has_ctype() {
+void FieldOptions::set_has_ctype() {
_has_bits_[0] |= 0x00000001u;
}
- void FieldOptions::clear_has_ctype() {
+void FieldOptions::clear_has_ctype() {
_has_bits_[0] &= ~0x00000001u;
}
- void FieldOptions::clear_ctype() {
+void FieldOptions::clear_ctype() {
ctype_ = 0;
clear_has_ctype();
}
@@ -9455,16 +10109,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
}
// optional bool packed = 2;
- bool FieldOptions::has_packed() const {
+bool FieldOptions::has_packed() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void FieldOptions::set_has_packed() {
+void FieldOptions::set_has_packed() {
_has_bits_[0] |= 0x00000002u;
}
- void FieldOptions::clear_has_packed() {
+void FieldOptions::clear_has_packed() {
_has_bits_[0] &= ~0x00000002u;
}
- void FieldOptions::clear_packed() {
+void FieldOptions::clear_packed() {
packed_ = false;
clear_has_packed();
}
@@ -9478,17 +10132,42 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
// @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
}
-// optional bool lazy = 5 [default = false];
- bool FieldOptions::has_lazy() const {
+// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+bool FieldOptions::has_jstype() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void FieldOptions::set_has_lazy() {
+void FieldOptions::set_has_jstype() {
_has_bits_[0] |= 0x00000004u;
}
- void FieldOptions::clear_has_lazy() {
+void FieldOptions::clear_has_jstype() {
_has_bits_[0] &= ~0x00000004u;
}
- void FieldOptions::clear_lazy() {
+void FieldOptions::clear_jstype() {
+ jstype_ = 0;
+ clear_has_jstype();
+}
+ ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype)
+ return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_);
+}
+ void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) {
+ assert(::google::protobuf::FieldOptions_JSType_IsValid(value));
+ set_has_jstype();
+ jstype_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype)
+}
+
+// optional bool lazy = 5 [default = false];
+bool FieldOptions::has_lazy() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+void FieldOptions::set_has_lazy() {
+ _has_bits_[0] |= 0x00000008u;
+}
+void FieldOptions::clear_has_lazy() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+void FieldOptions::clear_lazy() {
lazy_ = false;
clear_has_lazy();
}
@@ -9503,16 +10182,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
}
// optional bool deprecated = 3 [default = false];
- bool FieldOptions::has_deprecated() const {
- return (_has_bits_[0] & 0x00000008u) != 0;
+bool FieldOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
}
- void FieldOptions::set_has_deprecated() {
- _has_bits_[0] |= 0x00000008u;
+void FieldOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000010u;
}
- void FieldOptions::clear_has_deprecated() {
- _has_bits_[0] &= ~0x00000008u;
+void FieldOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000010u;
}
- void FieldOptions::clear_deprecated() {
+void FieldOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
}
@@ -9527,16 +10206,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
}
// optional bool weak = 10 [default = false];
- bool FieldOptions::has_weak() const {
- return (_has_bits_[0] & 0x00000010u) != 0;
+bool FieldOptions::has_weak() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
}
- void FieldOptions::set_has_weak() {
- _has_bits_[0] |= 0x00000010u;
+void FieldOptions::set_has_weak() {
+ _has_bits_[0] |= 0x00000020u;
}
- void FieldOptions::clear_has_weak() {
- _has_bits_[0] &= ~0x00000010u;
+void FieldOptions::clear_has_weak() {
+ _has_bits_[0] &= ~0x00000020u;
}
- void FieldOptions::clear_weak() {
+void FieldOptions::clear_weak() {
weak_ = false;
clear_has_weak();
}
@@ -9551,10 +10230,10 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- int FieldOptions::uninterpreted_option_size() const {
+int FieldOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
}
- void FieldOptions::clear_uninterpreted_option() {
+void FieldOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
@@ -9591,7 +10270,7 @@ const int EnumOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumOptions::EnumOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumOptions)
}
@@ -9714,12 +10393,15 @@ bool EnumOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -9851,9 +10533,9 @@ int EnumOptions::ByteSize() const {
void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumOptions*>(
- &from);
+ const EnumOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -9923,16 +10605,16 @@ void EnumOptions::InternalSwap(EnumOptions* other) {
// EnumOptions
// optional bool allow_alias = 2;
- bool EnumOptions::has_allow_alias() const {
+bool EnumOptions::has_allow_alias() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void EnumOptions::set_has_allow_alias() {
+void EnumOptions::set_has_allow_alias() {
_has_bits_[0] |= 0x00000001u;
}
- void EnumOptions::clear_has_allow_alias() {
+void EnumOptions::clear_has_allow_alias() {
_has_bits_[0] &= ~0x00000001u;
}
- void EnumOptions::clear_allow_alias() {
+void EnumOptions::clear_allow_alias() {
allow_alias_ = false;
clear_has_allow_alias();
}
@@ -9947,16 +10629,16 @@ void EnumOptions::InternalSwap(EnumOptions* other) {
}
// optional bool deprecated = 3 [default = false];
- bool EnumOptions::has_deprecated() const {
+bool EnumOptions::has_deprecated() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void EnumOptions::set_has_deprecated() {
+void EnumOptions::set_has_deprecated() {
_has_bits_[0] |= 0x00000002u;
}
- void EnumOptions::clear_has_deprecated() {
+void EnumOptions::clear_has_deprecated() {
_has_bits_[0] &= ~0x00000002u;
}
- void EnumOptions::clear_deprecated() {
+void EnumOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
}
@@ -9971,10 +10653,10 @@ void EnumOptions::InternalSwap(EnumOptions* other) {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- int EnumOptions::uninterpreted_option_size() const {
+int EnumOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
}
- void EnumOptions::clear_uninterpreted_option() {
+void EnumOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
@@ -10010,7 +10692,7 @@ const int EnumValueOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
EnumValueOptions::EnumValueOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions)
}
@@ -10105,12 +10787,15 @@ bool EnumValueOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -10225,9 +10910,9 @@ int EnumValueOptions::ByteSize() const {
void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumValueOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumValueOptions*>(
- &from);
+ const EnumValueOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -10293,16 +10978,16 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
// EnumValueOptions
// optional bool deprecated = 1 [default = false];
- bool EnumValueOptions::has_deprecated() const {
+bool EnumValueOptions::has_deprecated() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void EnumValueOptions::set_has_deprecated() {
+void EnumValueOptions::set_has_deprecated() {
_has_bits_[0] |= 0x00000001u;
}
- void EnumValueOptions::clear_has_deprecated() {
+void EnumValueOptions::clear_has_deprecated() {
_has_bits_[0] &= ~0x00000001u;
}
- void EnumValueOptions::clear_deprecated() {
+void EnumValueOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
}
@@ -10317,10 +11002,10 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- int EnumValueOptions::uninterpreted_option_size() const {
+int EnumValueOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
}
- void EnumValueOptions::clear_uninterpreted_option() {
+void EnumValueOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
@@ -10356,7 +11041,7 @@ const int ServiceOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
ServiceOptions::ServiceOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions)
}
@@ -10451,12 +11136,15 @@ bool ServiceOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -10571,9 +11259,9 @@ int ServiceOptions::ByteSize() const {
void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const ServiceOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const ServiceOptions*>(
- &from);
+ const ServiceOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -10639,16 +11327,16 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) {
// ServiceOptions
// optional bool deprecated = 33 [default = false];
- bool ServiceOptions::has_deprecated() const {
+bool ServiceOptions::has_deprecated() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void ServiceOptions::set_has_deprecated() {
+void ServiceOptions::set_has_deprecated() {
_has_bits_[0] |= 0x00000001u;
}
- void ServiceOptions::clear_has_deprecated() {
+void ServiceOptions::clear_has_deprecated() {
_has_bits_[0] &= ~0x00000001u;
}
- void ServiceOptions::clear_deprecated() {
+void ServiceOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
}
@@ -10663,10 +11351,10 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- int ServiceOptions::uninterpreted_option_size() const {
+int ServiceOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
}
- void ServiceOptions::clear_uninterpreted_option() {
+void ServiceOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
@@ -10702,7 +11390,7 @@ const int MethodOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
MethodOptions::MethodOptions()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.MethodOptions)
}
@@ -10797,12 +11485,15 @@ bool MethodOptions::MergePartialFromCodedStream(
case 999: {
if (tag == 7994) {
parse_uninterpreted_option:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_uninterpreted_option:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_uninterpreted_option()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
+ if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -10917,9 +11608,9 @@ int MethodOptions::ByteSize() const {
void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const MethodOptions* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const MethodOptions*>(
- &from);
+ const MethodOptions* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -10985,16 +11676,16 @@ void MethodOptions::InternalSwap(MethodOptions* other) {
// MethodOptions
// optional bool deprecated = 33 [default = false];
- bool MethodOptions::has_deprecated() const {
+bool MethodOptions::has_deprecated() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void MethodOptions::set_has_deprecated() {
+void MethodOptions::set_has_deprecated() {
_has_bits_[0] |= 0x00000001u;
}
- void MethodOptions::clear_has_deprecated() {
+void MethodOptions::clear_has_deprecated() {
_has_bits_[0] &= ~0x00000001u;
}
- void MethodOptions::clear_deprecated() {
+void MethodOptions::clear_deprecated() {
deprecated_ = false;
clear_has_deprecated();
}
@@ -11009,10 +11700,10 @@ void MethodOptions::InternalSwap(MethodOptions* other) {
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- int MethodOptions::uninterpreted_option_size() const {
+int MethodOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
}
- void MethodOptions::clear_uninterpreted_option() {
+void MethodOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
@@ -11048,7 +11739,7 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber;
#endif // !_MSC_VER
UninterpretedOption_NamePart::UninterpretedOption_NamePart()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart)
}
@@ -11281,9 +11972,9 @@ int UninterpretedOption_NamePart::ByteSize() const {
void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const UninterpretedOption_NamePart* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const UninterpretedOption_NamePart*>(
- &from);
+ const UninterpretedOption_NamePart* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -11359,7 +12050,7 @@ const int UninterpretedOption::kAggregateValueFieldNumber;
#endif // !_MSC_VER
UninterpretedOption::UninterpretedOption()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption)
}
@@ -11470,13 +12161,15 @@ bool UninterpretedOption::MergePartialFromCodedStream(
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
case 2: {
if (tag == 18) {
- parse_name:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_name:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_name()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_name;
+ if (input->ExpectTag(18)) goto parse_loop_name;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(26)) goto parse_identifier_value;
break;
}
@@ -11780,9 +12473,9 @@ int UninterpretedOption::ByteSize() const {
void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const UninterpretedOption* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const UninterpretedOption*>(
- &from);
+ const UninterpretedOption* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -11868,16 +12561,16 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
// UninterpretedOption_NamePart
// required string name_part = 1;
- bool UninterpretedOption_NamePart::has_name_part() const {
+bool UninterpretedOption_NamePart::has_name_part() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
- void UninterpretedOption_NamePart::set_has_name_part() {
+void UninterpretedOption_NamePart::set_has_name_part() {
_has_bits_[0] |= 0x00000001u;
}
- void UninterpretedOption_NamePart::clear_has_name_part() {
+void UninterpretedOption_NamePart::clear_has_name_part() {
_has_bits_[0] &= ~0x00000001u;
}
- void UninterpretedOption_NamePart::clear_name_part() {
+void UninterpretedOption_NamePart::clear_name_part() {
name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name_part();
}
@@ -11921,16 +12614,16 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
}
// required bool is_extension = 2;
- bool UninterpretedOption_NamePart::has_is_extension() const {
+bool UninterpretedOption_NamePart::has_is_extension() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void UninterpretedOption_NamePart::set_has_is_extension() {
+void UninterpretedOption_NamePart::set_has_is_extension() {
_has_bits_[0] |= 0x00000002u;
}
- void UninterpretedOption_NamePart::clear_has_is_extension() {
+void UninterpretedOption_NamePart::clear_has_is_extension() {
_has_bits_[0] &= ~0x00000002u;
}
- void UninterpretedOption_NamePart::clear_is_extension() {
+void UninterpretedOption_NamePart::clear_is_extension() {
is_extension_ = false;
clear_has_is_extension();
}
@@ -11949,10 +12642,10 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
// UninterpretedOption
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
- int UninterpretedOption::name_size() const {
+int UninterpretedOption::name_size() const {
return name_.size();
}
- void UninterpretedOption::clear_name() {
+void UninterpretedOption::clear_name() {
name_.Clear();
}
const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
@@ -11979,16 +12672,16 @@ UninterpretedOption::mutable_name() {
}
// optional string identifier_value = 3;
- bool UninterpretedOption::has_identifier_value() const {
+bool UninterpretedOption::has_identifier_value() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
- void UninterpretedOption::set_has_identifier_value() {
+void UninterpretedOption::set_has_identifier_value() {
_has_bits_[0] |= 0x00000002u;
}
- void UninterpretedOption::clear_has_identifier_value() {
+void UninterpretedOption::clear_has_identifier_value() {
_has_bits_[0] &= ~0x00000002u;
}
- void UninterpretedOption::clear_identifier_value() {
+void UninterpretedOption::clear_identifier_value() {
identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_identifier_value();
}
@@ -12032,16 +12725,16 @@ UninterpretedOption::mutable_name() {
}
// optional uint64 positive_int_value = 4;
- bool UninterpretedOption::has_positive_int_value() const {
+bool UninterpretedOption::has_positive_int_value() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void UninterpretedOption::set_has_positive_int_value() {
+void UninterpretedOption::set_has_positive_int_value() {
_has_bits_[0] |= 0x00000004u;
}
- void UninterpretedOption::clear_has_positive_int_value() {
+void UninterpretedOption::clear_has_positive_int_value() {
_has_bits_[0] &= ~0x00000004u;
}
- void UninterpretedOption::clear_positive_int_value() {
+void UninterpretedOption::clear_positive_int_value() {
positive_int_value_ = GOOGLE_ULONGLONG(0);
clear_has_positive_int_value();
}
@@ -12056,16 +12749,16 @@ UninterpretedOption::mutable_name() {
}
// optional int64 negative_int_value = 5;
- bool UninterpretedOption::has_negative_int_value() const {
+bool UninterpretedOption::has_negative_int_value() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
- void UninterpretedOption::set_has_negative_int_value() {
+void UninterpretedOption::set_has_negative_int_value() {
_has_bits_[0] |= 0x00000008u;
}
- void UninterpretedOption::clear_has_negative_int_value() {
+void UninterpretedOption::clear_has_negative_int_value() {
_has_bits_[0] &= ~0x00000008u;
}
- void UninterpretedOption::clear_negative_int_value() {
+void UninterpretedOption::clear_negative_int_value() {
negative_int_value_ = GOOGLE_LONGLONG(0);
clear_has_negative_int_value();
}
@@ -12080,16 +12773,16 @@ UninterpretedOption::mutable_name() {
}
// optional double double_value = 6;
- bool UninterpretedOption::has_double_value() const {
+bool UninterpretedOption::has_double_value() const {
return (_has_bits_[0] & 0x00000010u) != 0;
}
- void UninterpretedOption::set_has_double_value() {
+void UninterpretedOption::set_has_double_value() {
_has_bits_[0] |= 0x00000010u;
}
- void UninterpretedOption::clear_has_double_value() {
+void UninterpretedOption::clear_has_double_value() {
_has_bits_[0] &= ~0x00000010u;
}
- void UninterpretedOption::clear_double_value() {
+void UninterpretedOption::clear_double_value() {
double_value_ = 0;
clear_has_double_value();
}
@@ -12104,16 +12797,16 @@ UninterpretedOption::mutable_name() {
}
// optional bytes string_value = 7;
- bool UninterpretedOption::has_string_value() const {
+bool UninterpretedOption::has_string_value() const {
return (_has_bits_[0] & 0x00000020u) != 0;
}
- void UninterpretedOption::set_has_string_value() {
+void UninterpretedOption::set_has_string_value() {
_has_bits_[0] |= 0x00000020u;
}
- void UninterpretedOption::clear_has_string_value() {
+void UninterpretedOption::clear_has_string_value() {
_has_bits_[0] &= ~0x00000020u;
}
- void UninterpretedOption::clear_string_value() {
+void UninterpretedOption::clear_string_value() {
string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_string_value();
}
@@ -12157,16 +12850,16 @@ UninterpretedOption::mutable_name() {
}
// optional string aggregate_value = 8;
- bool UninterpretedOption::has_aggregate_value() const {
+bool UninterpretedOption::has_aggregate_value() const {
return (_has_bits_[0] & 0x00000040u) != 0;
}
- void UninterpretedOption::set_has_aggregate_value() {
+void UninterpretedOption::set_has_aggregate_value() {
_has_bits_[0] |= 0x00000040u;
}
- void UninterpretedOption::clear_has_aggregate_value() {
+void UninterpretedOption::clear_has_aggregate_value() {
_has_bits_[0] &= ~0x00000040u;
}
- void UninterpretedOption::clear_aggregate_value() {
+void UninterpretedOption::clear_aggregate_value() {
aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_aggregate_value();
}
@@ -12222,7 +12915,7 @@ const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo_Location::SourceCodeInfo_Location()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location)
}
@@ -12625,9 +13318,9 @@ int SourceCodeInfo_Location::ByteSize() const {
void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const SourceCodeInfo_Location* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo_Location*>(
- &from);
+ const SourceCodeInfo_Location* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -12703,7 +13396,7 @@ const int SourceCodeInfo::kLocationFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo::SourceCodeInfo()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo)
}
@@ -12780,13 +13473,15 @@ bool SourceCodeInfo::MergePartialFromCodedStream(
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
case 1: {
if (tag == 10) {
- parse_location:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_location:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_location()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(10)) goto parse_location;
+ if (input->ExpectTag(10)) goto parse_loop_location;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -12871,9 +13566,9 @@ int SourceCodeInfo::ByteSize() const {
void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const SourceCodeInfo* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const SourceCodeInfo*>(
- &from);
+ const SourceCodeInfo* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -12929,10 +13624,10 @@ void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
// SourceCodeInfo_Location
// repeated int32 path = 1 [packed = true];
- int SourceCodeInfo_Location::path_size() const {
+int SourceCodeInfo_Location::path_size() const {
return path_.size();
}
- void SourceCodeInfo_Location::clear_path() {
+void SourceCodeInfo_Location::clear_path() {
path_.Clear();
}
::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
@@ -12959,10 +13654,10 @@ SourceCodeInfo_Location::mutable_path() {
}
// repeated int32 span = 2 [packed = true];
- int SourceCodeInfo_Location::span_size() const {
+int SourceCodeInfo_Location::span_size() const {
return span_.size();
}
- void SourceCodeInfo_Location::clear_span() {
+void SourceCodeInfo_Location::clear_span() {
span_.Clear();
}
::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
@@ -12989,16 +13684,16 @@ SourceCodeInfo_Location::mutable_span() {
}
// optional string leading_comments = 3;
- bool SourceCodeInfo_Location::has_leading_comments() const {
+bool SourceCodeInfo_Location::has_leading_comments() const {
return (_has_bits_[0] & 0x00000004u) != 0;
}
- void SourceCodeInfo_Location::set_has_leading_comments() {
+void SourceCodeInfo_Location::set_has_leading_comments() {
_has_bits_[0] |= 0x00000004u;
}
- void SourceCodeInfo_Location::clear_has_leading_comments() {
+void SourceCodeInfo_Location::clear_has_leading_comments() {
_has_bits_[0] &= ~0x00000004u;
}
- void SourceCodeInfo_Location::clear_leading_comments() {
+void SourceCodeInfo_Location::clear_leading_comments() {
leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_leading_comments();
}
@@ -13042,16 +13737,16 @@ SourceCodeInfo_Location::mutable_span() {
}
// optional string trailing_comments = 4;
- bool SourceCodeInfo_Location::has_trailing_comments() const {
+bool SourceCodeInfo_Location::has_trailing_comments() const {
return (_has_bits_[0] & 0x00000008u) != 0;
}
- void SourceCodeInfo_Location::set_has_trailing_comments() {
+void SourceCodeInfo_Location::set_has_trailing_comments() {
_has_bits_[0] |= 0x00000008u;
}
- void SourceCodeInfo_Location::clear_has_trailing_comments() {
+void SourceCodeInfo_Location::clear_has_trailing_comments() {
_has_bits_[0] &= ~0x00000008u;
}
- void SourceCodeInfo_Location::clear_trailing_comments() {
+void SourceCodeInfo_Location::clear_trailing_comments() {
trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_trailing_comments();
}
@@ -13095,10 +13790,10 @@ SourceCodeInfo_Location::mutable_span() {
}
// repeated string leading_detached_comments = 6;
- int SourceCodeInfo_Location::leading_detached_comments_size() const {
+int SourceCodeInfo_Location::leading_detached_comments_size() const {
return leading_detached_comments_.size();
}
- void SourceCodeInfo_Location::clear_leading_detached_comments() {
+void SourceCodeInfo_Location::clear_leading_detached_comments() {
leading_detached_comments_.Clear();
}
const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
@@ -13153,10 +13848,10 @@ SourceCodeInfo_Location::mutable_leading_detached_comments() {
// SourceCodeInfo
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
- int SourceCodeInfo::location_size() const {
+int SourceCodeInfo::location_size() const {
return location_.size();
}
- void SourceCodeInfo::clear_location() {
+void SourceCodeInfo::clear_location() {
location_.Clear();
}
const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 5bebf4fd..b887b8cb 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -42,6 +42,7 @@ class FileDescriptorSet;
class FileDescriptorProto;
class DescriptorProto;
class DescriptorProto_ExtensionRange;
+class DescriptorProto_ReservedRange;
class FieldDescriptorProto;
class OneofDescriptorProto;
class EnumDescriptorProto;
@@ -155,6 +156,26 @@ inline bool FieldOptions_CType_Parse(
return ::google::protobuf::internal::ParseNamedEnum<FieldOptions_CType>(
FieldOptions_CType_descriptor(), name, value);
}
+enum FieldOptions_JSType {
+ FieldOptions_JSType_JS_NORMAL = 0,
+ FieldOptions_JSType_JS_STRING = 1,
+ FieldOptions_JSType_JS_NUMBER = 2
+};
+LIBPROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value);
+const FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL;
+const FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER;
+const int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1;
+
+LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor();
+inline const ::std::string& FieldOptions_JSType_Name(FieldOptions_JSType value) {
+ return ::google::protobuf::internal::NameOfEnum(
+ FieldOptions_JSType_descriptor(), value);
+}
+inline bool FieldOptions_JSType_Parse(
+ const ::std::string& name, FieldOptions_JSType* value) {
+ return ::google::protobuf::internal::ParseNamedEnum<FieldOptions_JSType>(
+ FieldOptions_JSType_descriptor(), name, value);
+}
// ===================================================================
class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message {
@@ -591,6 +612,105 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
};
// -------------------------------------------------------------------
+class LIBPROTOBUF_EXPORT DescriptorProto_ReservedRange : public ::google::protobuf::Message {
+ public:
+ DescriptorProto_ReservedRange();
+ virtual ~DescriptorProto_ReservedRange();
+
+ DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from);
+
+ inline DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange& from) {
+ CopyFrom(from);
+ return *this;
+ }
+
+ inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+ return _internal_metadata_.unknown_fields();
+ }
+
+ inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+ return _internal_metadata_.mutable_unknown_fields();
+ }
+
+ static const ::google::protobuf::Descriptor* descriptor();
+ static const DescriptorProto_ReservedRange& default_instance();
+
+ void Swap(DescriptorProto_ReservedRange* other);
+
+ // implements Message ----------------------------------------------
+
+ inline DescriptorProto_ReservedRange* New() const { return New(NULL); }
+
+ DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena) const;
+ void CopyFrom(const ::google::protobuf::Message& from);
+ void MergeFrom(const ::google::protobuf::Message& from);
+ void CopyFrom(const DescriptorProto_ReservedRange& from);
+ void MergeFrom(const DescriptorProto_ReservedRange& from);
+ void Clear();
+ bool IsInitialized() const;
+
+ int ByteSize() const;
+ bool MergePartialFromCodedStream(
+ ::google::protobuf::io::CodedInputStream* input);
+ void SerializeWithCachedSizes(
+ ::google::protobuf::io::CodedOutputStream* output) const;
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+ int GetCachedSize() const { return _cached_size_; }
+ private:
+ void SharedCtor();
+ void SharedDtor();
+ void SetCachedSize(int size) const;
+ void InternalSwap(DescriptorProto_ReservedRange* other);
+ 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 ----------------------------------------------------
+
+ // accessors -------------------------------------------------------
+
+ // optional int32 start = 1;
+ bool has_start() const;
+ void clear_start();
+ static const int kStartFieldNumber = 1;
+ ::google::protobuf::int32 start() const;
+ void set_start(::google::protobuf::int32 value);
+
+ // optional int32 end = 2;
+ bool has_end() const;
+ void clear_end();
+ static const int kEndFieldNumber = 2;
+ ::google::protobuf::int32 end() const;
+ void set_end(::google::protobuf::int32 value);
+
+ // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange)
+ private:
+ inline void set_has_start();
+ inline void clear_has_start();
+ inline void set_has_end();
+ inline void clear_has_end();
+
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ ::google::protobuf::uint32 _has_bits_[1];
+ mutable int _cached_size_;
+ ::google::protobuf::int32 start_;
+ ::google::protobuf::int32 end_;
+ friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
+
+ void InitAsDefaultInstance();
+ static DescriptorProto_ReservedRange* default_instance_;
+};
+// -------------------------------------------------------------------
+
class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
public:
DescriptorProto();
@@ -654,6 +774,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
// nested types ----------------------------------------------------
typedef DescriptorProto_ExtensionRange ExtensionRange;
+ typedef DescriptorProto_ReservedRange ReservedRange;
// accessors -------------------------------------------------------
@@ -750,6 +871,34 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
::google::protobuf::MessageOptions* release_options();
void set_allocated_options(::google::protobuf::MessageOptions* options);
+ // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+ int reserved_range_size() const;
+ void clear_reserved_range();
+ static const int kReservedRangeFieldNumber = 9;
+ const ::google::protobuf::DescriptorProto_ReservedRange& reserved_range(int index) const;
+ ::google::protobuf::DescriptorProto_ReservedRange* mutable_reserved_range(int index);
+ ::google::protobuf::DescriptorProto_ReservedRange* add_reserved_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+ reserved_range() const;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+ mutable_reserved_range();
+
+ // repeated string reserved_name = 10;
+ int reserved_name_size() const;
+ void clear_reserved_name();
+ static const int kReservedNameFieldNumber = 10;
+ const ::std::string& reserved_name(int index) const;
+ ::std::string* mutable_reserved_name(int index);
+ void set_reserved_name(int index, const ::std::string& value);
+ void set_reserved_name(int index, const char* value);
+ void set_reserved_name(int index, const char* value, size_t size);
+ ::std::string* add_reserved_name();
+ void add_reserved_name(const ::std::string& value);
+ void add_reserved_name(const char* value);
+ void add_reserved_name(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& reserved_name() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_reserved_name();
+
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
private:
inline void set_has_name();
@@ -768,6 +917,8 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto > oneof_decl_;
::google::protobuf::MessageOptions* options_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange > reserved_range_;
+ ::google::protobuf::RepeatedPtrField< ::std::string> reserved_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();
@@ -2144,6 +2295,31 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
return FieldOptions_CType_Parse(name, value);
}
+ typedef FieldOptions_JSType JSType;
+ static const JSType JS_NORMAL = FieldOptions_JSType_JS_NORMAL;
+ static const JSType JS_STRING = FieldOptions_JSType_JS_STRING;
+ static const JSType JS_NUMBER = FieldOptions_JSType_JS_NUMBER;
+ static inline bool JSType_IsValid(int value) {
+ return FieldOptions_JSType_IsValid(value);
+ }
+ static const JSType JSType_MIN =
+ FieldOptions_JSType_JSType_MIN;
+ static const JSType JSType_MAX =
+ FieldOptions_JSType_JSType_MAX;
+ static const int JSType_ARRAYSIZE =
+ FieldOptions_JSType_JSType_ARRAYSIZE;
+ static inline const ::google::protobuf::EnumDescriptor*
+ JSType_descriptor() {
+ return FieldOptions_JSType_descriptor();
+ }
+ static inline const ::std::string& JSType_Name(JSType value) {
+ return FieldOptions_JSType_Name(value);
+ }
+ static inline bool JSType_Parse(const ::std::string& name,
+ JSType* value) {
+ return FieldOptions_JSType_Parse(name, value);
+ }
+
// accessors -------------------------------------------------------
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
@@ -2160,6 +2336,13 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
bool packed() const;
void set_packed(bool value);
+ // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+ bool has_jstype() const;
+ void clear_jstype();
+ static const int kJstypeFieldNumber = 6;
+ ::google::protobuf::FieldOptions_JSType jstype() const;
+ void set_jstype(::google::protobuf::FieldOptions_JSType value);
+
// optional bool lazy = 5 [default = false];
bool has_lazy() const;
void clear_lazy();
@@ -2200,6 +2383,8 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
inline void clear_has_ctype();
inline void set_has_packed();
inline void clear_has_packed();
+ inline void set_has_jstype();
+ inline void clear_has_jstype();
inline void set_has_lazy();
inline void clear_has_lazy();
inline void set_has_deprecated();
@@ -2213,11 +2398,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
int ctype_;
+ int jstype_;
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
bool packed_;
bool lazy_;
bool deprecated_;
bool weak_;
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
@@ -3754,6 +3940,58 @@ inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 va
// -------------------------------------------------------------------
+// DescriptorProto_ReservedRange
+
+// optional int32 start = 1;
+inline bool DescriptorProto_ReservedRange::has_start() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto_ReservedRange::set_has_start() {
+ _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto_ReservedRange::clear_has_start() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+inline void DescriptorProto_ReservedRange::clear_start() {
+ start_ = 0;
+ clear_has_start();
+}
+inline ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start)
+ return start_;
+}
+inline void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) {
+ set_has_start();
+ start_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start)
+}
+
+// optional int32 end = 2;
+inline bool DescriptorProto_ReservedRange::has_end() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+inline void DescriptorProto_ReservedRange::set_has_end() {
+ _has_bits_[0] |= 0x00000002u;
+}
+inline void DescriptorProto_ReservedRange::clear_has_end() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+inline void DescriptorProto_ReservedRange::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+inline ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end)
+ return end_;
+}
+inline void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end)
+}
+
+// -------------------------------------------------------------------
+
// DescriptorProto
// optional string name = 1;
@@ -4032,6 +4270,90 @@ inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOp
// @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
}
+// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
+inline int DescriptorProto::reserved_range_size() const {
+ return reserved_range_.size();
+}
+inline void DescriptorProto::clear_reserved_range() {
+ reserved_range_.Clear();
+}
+inline const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Get(index);
+}
+inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Mutable(index);
+}
+inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+DescriptorProto::mutable_reserved_range() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
+ return &reserved_range_;
+}
+
+// repeated string reserved_name = 10;
+inline int DescriptorProto::reserved_name_size() const {
+ return reserved_name_.size();
+}
+inline void DescriptorProto::clear_reserved_name() {
+ reserved_name_.Clear();
+}
+inline const ::std::string& DescriptorProto::reserved_name(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Get(index);
+}
+inline ::std::string* DescriptorProto::mutable_reserved_name(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_.Mutable(index);
+}
+inline void DescriptorProto::set_reserved_name(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name)
+ reserved_name_.Mutable(index)->assign(value);
+}
+inline void DescriptorProto::set_reserved_name(int index, const char* value) {
+ reserved_name_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+ reserved_name_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+inline ::std::string* DescriptorProto::add_reserved_name() {
+ return reserved_name_.Add();
+}
+inline void DescriptorProto::add_reserved_name(const ::std::string& value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::add_reserved_name(const char* value) {
+ reserved_name_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name)
+}
+inline void DescriptorProto::add_reserved_name(const char* value, size_t size) {
+ reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+DescriptorProto::reserved_name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name)
+ return reserved_name_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+DescriptorProto::mutable_reserved_name() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name)
+ return &reserved_name_;
+}
+
// -------------------------------------------------------------------
// FieldDescriptorProto
@@ -5783,15 +6105,40 @@ inline void FieldOptions::set_packed(bool value) {
// @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
}
+// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
+inline bool FieldOptions::has_jstype() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+inline void FieldOptions::set_has_jstype() {
+ _has_bits_[0] |= 0x00000004u;
+}
+inline void FieldOptions::clear_has_jstype() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+inline void FieldOptions::clear_jstype() {
+ jstype_ = 0;
+ clear_has_jstype();
+}
+inline ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype)
+ return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_);
+}
+inline void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) {
+ assert(::google::protobuf::FieldOptions_JSType_IsValid(value));
+ set_has_jstype();
+ jstype_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype)
+}
+
// optional bool lazy = 5 [default = false];
inline bool FieldOptions::has_lazy() const {
- return (_has_bits_[0] & 0x00000004u) != 0;
+ return (_has_bits_[0] & 0x00000008u) != 0;
}
inline void FieldOptions::set_has_lazy() {
- _has_bits_[0] |= 0x00000004u;
+ _has_bits_[0] |= 0x00000008u;
}
inline void FieldOptions::clear_has_lazy() {
- _has_bits_[0] &= ~0x00000004u;
+ _has_bits_[0] &= ~0x00000008u;
}
inline void FieldOptions::clear_lazy() {
lazy_ = false;
@@ -5809,13 +6156,13 @@ inline void FieldOptions::set_lazy(bool value) {
// optional bool deprecated = 3 [default = false];
inline bool FieldOptions::has_deprecated() const {
- return (_has_bits_[0] & 0x00000008u) != 0;
+ return (_has_bits_[0] & 0x00000010u) != 0;
}
inline void FieldOptions::set_has_deprecated() {
- _has_bits_[0] |= 0x00000008u;
+ _has_bits_[0] |= 0x00000010u;
}
inline void FieldOptions::clear_has_deprecated() {
- _has_bits_[0] &= ~0x00000008u;
+ _has_bits_[0] &= ~0x00000010u;
}
inline void FieldOptions::clear_deprecated() {
deprecated_ = false;
@@ -5833,13 +6180,13 @@ inline void FieldOptions::set_deprecated(bool value) {
// optional bool weak = 10 [default = false];
inline bool FieldOptions::has_weak() const {
- return (_has_bits_[0] & 0x00000010u) != 0;
+ return (_has_bits_[0] & 0x00000020u) != 0;
}
inline void FieldOptions::set_has_weak() {
- _has_bits_[0] |= 0x00000010u;
+ _has_bits_[0] |= 0x00000020u;
}
inline void FieldOptions::clear_has_weak() {
- _has_bits_[0] &= ~0x00000010u;
+ _has_bits_[0] &= ~0x00000020u;
}
inline void FieldOptions::clear_weak() {
weak_ = false;
@@ -6746,6 +7093,48 @@ SourceCodeInfo::mutable_location() {
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
@@ -6776,6 +7165,11 @@ template <>
inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() {
return ::google::protobuf::FieldOptions_CType_descriptor();
}
+template <> struct is_proto_enum< ::google::protobuf::FieldOptions_JSType> : ::google::protobuf::internal::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_JSType>() {
+ return ::google::protobuf::FieldOptions_JSType_descriptor();
+}
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 7099135d..20a60080 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -106,6 +106,18 @@ message DescriptorProto {
repeated OneofDescriptorProto oneof_decl = 8;
optional MessageOptions options = 7;
+
+ // Range of reserved tag numbers. Reserved tag numbers may not be used by
+ // fields or extension ranges in the same message. Reserved ranges may
+ // not overlap.
+ message ReservedRange {
+ optional int32 start = 1; // Inclusive.
+ optional int32 end = 2; // Exclusive.
+ }
+ repeated ReservedRange reserved_range = 9;
+ // Reserved field names, which may not be used by fields in the same message.
+ // A given name may only be reserved once.
+ repeated string reserved_name = 10;
}
// Describes a field within a message.
@@ -251,11 +263,11 @@ message MethodDescriptorProto {
// * For options which will be published and used publicly by multiple
// independent entities, e-mail protobuf-global-extension-registry@google.com
// to reserve extension numbers. Simply provide your project name (e.g.
-// Object-C plugin) and your porject website (if available) -- there's no need
-// to explain how you intend to use them. Usually you only need one extension
-// number. You can declare multiple options with only one extension number by
-// putting them in a sub-message. See the Custom Options section of the docs
-// for examples:
+// Objective-C plugin) and your project website (if available) -- there's no
+// need to explain how you intend to use them. Usually you only need one
+// extension number. You can declare multiple options with only one extension
+// number by putting them in a sub-message. See the Custom Options section of
+// the docs for examples:
// https://developers.google.com/protocol-buffers/docs/proto#options
// If this turns out to be popular, a web service will be set up
// to automatically assign option numbers.
@@ -442,10 +454,31 @@ message FieldOptions {
// The packed option can be enabled for repeated primitive fields to enable
// a more efficient representation on the wire. Rather than repeatedly
// writing the tag and type for each element, the entire array is encoded as
- // a single length-delimited blob.
+ // a single length-delimited blob. In proto3, only explicit setting it to
+ // false will avoid using packed encoding.
optional bool packed = 2;
+ // The jstype option determines the JavaScript type used for values of the
+ // field. The option is permitted only for 64 bit integral and fixed types
+ // (int64, uint64, sint64, fixed64, sfixed64). By default these types are
+ // represented as JavaScript strings. This avoids loss of precision that can
+ // happen when a large value is converted to a floating point JavaScript
+ // numbers. Specifying JS_NUMBER for the jstype causes the generated
+ // JavaScript code to use the JavaScript "number" type instead of strings.
+ // This option is an enum to permit additional types to be added,
+ // e.g. goog.math.Integer.
+ optional JSType jstype = 6 [default = JS_NORMAL];
+ enum JSType {
+ // Use the default type.
+ JS_NORMAL = 0;
+
+ // Use JavaScript strings.
+ JS_STRING = 1;
+
+ // Use JavaScript numbers.
+ JS_NUMBER = 2;
+ }
// Should this field be parsed lazily? Lazy applies only to message-type
// fields. It means that when the outer message is initially parsed, the
diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
index 934e4022..86002d56 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -312,7 +312,7 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
// A DescriptorDatabase that fetches files from a given pool.
class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
public:
- DescriptorPoolDatabase(const DescriptorPool& pool);
+ explicit DescriptorPoolDatabase(const DescriptorPool& pool);
~DescriptorPoolDatabase();
// implements DescriptorDatabase -----------------------------------
@@ -341,7 +341,7 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase {
// Merge more than two databases. The sources remain property of the caller.
// The vector may be deleted after the constructor returns but the
// DescriptorDatabases need to stick around.
- MergedDescriptorDatabase(const vector<DescriptorDatabase*>& sources);
+ explicit MergedDescriptorDatabase(const vector<DescriptorDatabase*>& sources);
~MergedDescriptorDatabase();
// implements DescriptorDatabase -----------------------------------
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index fdce3d78..760df097 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -139,6 +139,14 @@ DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent,
return result;
}
+DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent,
+ int start, int end) {
+ DescriptorProto::ReservedRange* result = parent->add_reserved_range();
+ result->set_start(start);
+ result->set_end(end);
+ return result;
+}
+
EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto,
const string& name, int number) {
EnumValueDescriptorProto* result = enum_proto->add_value();
@@ -1720,6 +1728,84 @@ TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) {
// ===================================================================
+// Test reserved fields.
+class ReservedDescriptorTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ // Build descriptors for the following definitions:
+ //
+ // message Foo {
+ // reserved 2, 9 to 11, 15;
+ // reserved "foo", "bar";
+ // }
+
+ FileDescriptorProto foo_file;
+ foo_file.set_name("foo.proto");
+
+ DescriptorProto* foo = AddMessage(&foo_file, "Foo");
+ AddReservedRange(foo, 2, 3);
+ AddReservedRange(foo, 9, 12);
+ AddReservedRange(foo, 15, 16);
+
+ foo->add_reserved_name("foo");
+ foo->add_reserved_name("bar");
+
+ // Build the descriptors and get the pointers.
+ foo_file_ = pool_.BuildFile(foo_file);
+ ASSERT_TRUE(foo_file_ != NULL);
+
+ ASSERT_EQ(1, foo_file_->message_type_count());
+ foo_ = foo_file_->message_type(0);
+ }
+
+ DescriptorPool pool_;
+ const FileDescriptor* foo_file_;
+ const Descriptor* foo_;
+};
+
+TEST_F(ReservedDescriptorTest, ReservedRanges) {
+ ASSERT_EQ(3, foo_->reserved_range_count());
+
+ EXPECT_EQ(2, foo_->reserved_range(0)->start);
+ EXPECT_EQ(3, foo_->reserved_range(0)->end);
+
+ EXPECT_EQ(9, foo_->reserved_range(1)->start);
+ EXPECT_EQ(12, foo_->reserved_range(1)->end);
+
+ EXPECT_EQ(15, foo_->reserved_range(2)->start);
+ EXPECT_EQ(16, foo_->reserved_range(2)->end);
+};
+
+TEST_F(ReservedDescriptorTest, IsReservedNumber) {
+ EXPECT_FALSE(foo_->IsReservedNumber(1));
+ EXPECT_TRUE (foo_->IsReservedNumber(2));
+ EXPECT_FALSE(foo_->IsReservedNumber(3));
+ EXPECT_FALSE(foo_->IsReservedNumber(8));
+ EXPECT_TRUE (foo_->IsReservedNumber(9));
+ EXPECT_TRUE (foo_->IsReservedNumber(10));
+ EXPECT_TRUE (foo_->IsReservedNumber(11));
+ EXPECT_FALSE(foo_->IsReservedNumber(12));
+ EXPECT_FALSE(foo_->IsReservedNumber(13));
+ EXPECT_FALSE(foo_->IsReservedNumber(14));
+ EXPECT_TRUE (foo_->IsReservedNumber(15));
+ EXPECT_FALSE(foo_->IsReservedNumber(16));
+};
+
+TEST_F(ReservedDescriptorTest, ReservedNames) {
+ ASSERT_EQ(2, foo_->reserved_name_count());
+
+ EXPECT_EQ("foo", foo_->reserved_name(0));
+ EXPECT_EQ("bar", foo_->reserved_name(1));
+};
+
+TEST_F(ReservedDescriptorTest, IsReservedName) {
+ EXPECT_TRUE (foo_->IsReservedName("foo"));
+ EXPECT_TRUE (foo_->IsReservedName("bar"));
+ EXPECT_FALSE(foo_->IsReservedName("baz"));
+};
+
+// ===================================================================
+
class MiscTest : public testing::Test {
protected:
// Function which makes a field descriptor of the given type.
@@ -2997,10 +3083,10 @@ class ValidationErrorTest : public testing::Test {
protected:
// Parse file_text as a FileDescriptorProto in text format and add it
// to the DescriptorPool. Expect no errors.
- void BuildFile(const string& file_text) {
+ const FileDescriptor* BuildFile(const string& file_text) {
FileDescriptorProto file_proto;
- ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
- ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
+ EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto));
+ return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto));
}
// Parse file_text as a FileDescriptorProto in text format and add it
@@ -3251,6 +3337,102 @@ TEST_F(ValidationErrorTest, OverlappingExtensionRanges) {
"already-defined range 20 to 29.\n");
}
+TEST_F(ValidationErrorTest, ReservedFieldError) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " reserved_range { start: 10 end: 20 }"
+ "}",
+
+ "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedExtensionRangeError) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " extension_range { start: 10 end: 20 }"
+ " reserved_range { start: 5 end: 15 }"
+ "}",
+
+ "foo.proto: Foo: NUMBER: Extension range 10 to 19"
+ " overlaps with reserved range 5 to 14.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) {
+ BuildFile(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " extension_range { start: 10 end: 20 }"
+ " reserved_range { start: 5 end: 10 }"
+ "}");
+}
+
+TEST_F(ValidationErrorTest, ReservedRangeOverlap) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " reserved_range { start: 10 end: 20 }"
+ " reserved_range { start: 5 end: 15 }"
+ "}",
+
+ "foo.proto: Foo: NUMBER: Reserved range 5 to 14"
+ " overlaps with already-defined range 10 to 19.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedNameError) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ "}",
+
+ "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n"
+ "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedNameRedundant) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " reserved_name: \"foo\""
+ " reserved_name: \"foo\""
+ "}",
+
+ "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n");
+}
+
+TEST_F(ValidationErrorTest, ReservedFieldsDebugString) {
+ const FileDescriptor* file = BuildFile(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " reserved_name: \"foo\""
+ " reserved_name: \"bar\""
+ " reserved_range { start: 5 end: 6 }"
+ " reserved_range { start: 10 end: 20 }"
+ "}");
+
+ ASSERT_EQ(
+ "syntax = \"proto2\";\n\n"
+ "message Foo {\n"
+ " reserved 5, 10 to 19;\n"
+ " reserved \"foo\", \"bar\";\n"
+ "}\n\n",
+ file->DebugString());
+}
+
TEST_F(ValidationErrorTest, InvalidDefaults) {
BuildFileWithErrors(
"name: \"foo.proto\" "
@@ -3399,6 +3581,48 @@ TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
"range for type \"Foo\".\n");
}
+TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
+ // Fields belonging to the same oneof must be defined consecutively.
+ BuildFileWithWarnings(
+ "name: \"foo.proto\" "
+ "message_type {"
+ " name: \"Foo\""
+ " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " oneof_decl { name:\"foos\" }"
+ "}",
+
+ "foo.proto: Foo.bar: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"bar\" cannot be defined before the completion of the "
+ "\"foos\" oneof definition.\n");
+
+ // Prevent interleaved fields, which belong to different oneofs.
+ BuildFileWithWarnings(
+ "name: \"foo2.proto\" "
+ "message_type {"
+ " name: \"Foo2\""
+ " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 1 }"
+ " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 1 }"
+ " oneof_decl { name:\"foos\" }"
+ " oneof_decl { name:\"bars\" }"
+ "}",
+ "foo2.proto: Foo2.bar1: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"bar1\" cannot be defined before the completion of the "
+ "\"foos\" oneof definition.\n"
+ "foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"foo2\" cannot be defined before the completion of the "
+ "\"bars\" oneof definition.\n");
+}
+
TEST_F(ValidationErrorTest, FieldNumberConflict) {
BuildFileWithErrors(
"name: \"foo.proto\" "
@@ -5293,6 +5517,22 @@ TEST_F(ValidationErrorTest, ValidateProto3LiteRuntime) {
"in proto3.\n");
}
+TEST_F(ValidationErrorTest, ValidateProto3Group) {
+ BuildFileWithErrors(
+ "name: 'foo.proto' "
+ "syntax: 'proto3' "
+ "message_type { "
+ " name: 'Foo' "
+ " nested_type { "
+ " name: 'FooGroup' "
+ " } "
+ " field { name:'foo_group' number: 1 label:LABEL_OPTIONAL "
+ " type: TYPE_GROUP type_name:'FooGroup' } "
+ "}",
+ "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 "
+ "syntax.\n");
+}
+
TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) {
// Define an enum in a proto2 file.
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 4a11209e..f78fce21 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -117,7 +117,7 @@ const int Duration::kNanosFieldNumber;
#endif // !_MSC_VER
Duration::Duration()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Duration)
}
@@ -310,9 +310,9 @@ int Duration::ByteSize() const {
void Duration::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Duration* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Duration*>(
- &from);
+ const Duration* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Duration>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -370,7 +370,7 @@ void Duration::InternalSwap(Duration* other) {
// Duration
// optional int64 seconds = 1;
- void Duration::clear_seconds() {
+void Duration::clear_seconds() {
seconds_ = GOOGLE_LONGLONG(0);
}
::google::protobuf::int64 Duration::seconds() const {
@@ -384,7 +384,7 @@ void Duration::InternalSwap(Duration* other) {
}
// optional int32 nanos = 2;
- void Duration::clear_nanos() {
+void Duration::clear_nanos() {
nanos_ = 0;
}
::google::protobuf::int32 Duration::nanos() const {
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index f7ca5013..1a9a6661 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -111,7 +111,7 @@ static void MergeFromFail(int line) {
#endif // !_MSC_VER
Empty::Empty()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Empty)
}
@@ -221,9 +221,9 @@ int Empty::ByteSize() const {
void Empty::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Empty* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Empty*>(
- &from);
+ const Empty* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Empty>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 03b38dd0..649ae184 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -314,7 +314,7 @@ void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \
extension->is_repeated = true; \
extension->is_packed = packed; \
extension->repeated_##LOWERCASE##_value = \
- Arena::Create<RepeatedField<LOWERCASE> >(arena_, arena_); \
+ Arena::CreateMessage<RepeatedField<LOWERCASE> >(arena_); \
} else { \
GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \
GOOGLE_DCHECK_EQ(extension->is_packed, packed); \
@@ -359,43 +359,43 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type,
static_cast<WireFormatLite::FieldType>(field_type))) {
case WireFormatLite::CPPTYPE_INT32:
extension->repeated_int32_value =
- Arena::Create<RepeatedField<int32> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int32> >(arena_);
break;
case WireFormatLite::CPPTYPE_INT64:
extension->repeated_int64_value =
- Arena::Create<RepeatedField<int64> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int64> >(arena_);
break;
case WireFormatLite::CPPTYPE_UINT32:
extension->repeated_uint32_value =
- Arena::Create<RepeatedField<uint32> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<uint32> >(arena_);
break;
case WireFormatLite::CPPTYPE_UINT64:
extension->repeated_uint64_value =
- Arena::Create<RepeatedField<uint64> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<uint64> >(arena_);
break;
case WireFormatLite::CPPTYPE_DOUBLE:
extension->repeated_double_value =
- Arena::Create<RepeatedField<double> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<double> >(arena_);
break;
case WireFormatLite::CPPTYPE_FLOAT:
extension->repeated_float_value =
- Arena::Create<RepeatedField<float> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<float> >(arena_);
break;
case WireFormatLite::CPPTYPE_BOOL:
extension->repeated_bool_value =
- Arena::Create<RepeatedField<bool> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<bool> >(arena_);
break;
case WireFormatLite::CPPTYPE_ENUM:
extension->repeated_enum_value =
- Arena::Create<RepeatedField<int> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int> >(arena_);
break;
case WireFormatLite::CPPTYPE_STRING:
extension->repeated_string_value =
- Arena::Create<RepeatedPtrField< ::std::string> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField< ::std::string> >(arena_);
break;
case WireFormatLite::CPPTYPE_MESSAGE:
extension->repeated_message_value =
- Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
break;
}
}
@@ -468,7 +468,7 @@ void ExtensionSet::AddEnum(int number, FieldType type,
extension->is_repeated = true;
extension->is_packed = packed;
extension->repeated_enum_value =
- Arena::Create<RepeatedField<int> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedField<int> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM);
GOOGLE_DCHECK_EQ(extension->is_packed, packed);
@@ -529,7 +529,7 @@ string* ExtensionSet::AddString(int number, FieldType type,
extension->is_repeated = true;
extension->is_packed = false;
extension->repeated_string_value =
- Arena::Create<RepeatedPtrField<string> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<string> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING);
}
@@ -632,6 +632,35 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type,
extension->is_cleared = false;
}
+void ExtensionSet::UnsafeArenaSetAllocatedMessage(
+ int number, FieldType type, const FieldDescriptor* descriptor,
+ MessageLite* message) {
+ if (message == NULL) {
+ ClearExtension(number);
+ return;
+ }
+ Extension* extension;
+ if (MaybeNewExtension(number, descriptor, &extension)) {
+ extension->type = type;
+ GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE);
+ extension->is_repeated = false;
+ extension->is_lazy = false;
+ extension->message_value = message;
+ } else {
+ GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE);
+ if (extension->is_lazy) {
+ extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message);
+ } else {
+ if (arena_ == NULL) {
+ delete extension->message_value;
+ }
+ extension->message_value = message;
+ }
+ }
+ extension->is_cleared = false;
+}
+
+
MessageLite* ExtensionSet::ReleaseMessage(int number,
const MessageLite& prototype) {
map<int, Extension>::iterator iter = extensions_.find(number);
@@ -712,7 +741,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 =
- Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
@@ -866,7 +895,7 @@ void ExtensionSet::InternalExtensionMergeFrom(
case WireFormatLite::CPPTYPE_##UPPERCASE: \
if (is_new) { \
extension->repeated_##LOWERCASE##_value = \
- Arena::Create<REPEATED_TYPE >(arena_, arena_); \
+ Arena::CreateMessage<REPEATED_TYPE >(arena_); \
} \
extension->repeated_##LOWERCASE##_value->MergeFrom( \
*other_extension.repeated_##LOWERCASE##_value); \
@@ -886,7 +915,7 @@ void ExtensionSet::InternalExtensionMergeFrom(
case WireFormatLite::CPPTYPE_MESSAGE:
if (is_new) {
extension->repeated_message_value =
- Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
}
// We can't call RepeatedPtrField<MessageLite>::MergeFrom() because
// it would attempt to allocate new objects.
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 6d6702b3..c371e011 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -194,7 +194,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
// directly, unless you are doing low-level memory management.
//
// When calling any of these accessors, the extension number requested
- // MUST exist in the DescriptorPool provided to the constructor. Otheriwse,
+ // MUST exist in the DescriptorPool provided to the constructor. Otherwise,
// the method will fail an assert. Normally, though, you would not call
// these directly; you would either call the generated accessors of your
// message class (e.g. GetExtension()) or you would call the accessors
@@ -262,6 +262,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
void SetAllocatedMessage(int number, FieldType type,
const FieldDescriptor* descriptor,
MessageLite* message);
+ void UnsafeArenaSetAllocatedMessage(int number, FieldType type,
+ const FieldDescriptor* descriptor,
+ MessageLite* message);
MessageLite* ReleaseMessage(int number, const MessageLite& prototype);
MessageLite* UnsafeArenaReleaseMessage(
int number, const MessageLite& prototype);
@@ -432,6 +435,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const MessageLite& prototype) const = 0;
virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0;
virtual void SetAllocatedMessage(MessageLite *message) = 0;
+ virtual void UnsafeArenaSetAllocatedMessage(MessageLite *message) = 0;
virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0;
virtual MessageLite* UnsafeArenaReleaseMessage(
const MessageLite& prototype) = 0;
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 796e7a5f..330bd828 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -221,7 +221,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 =
- ::google::protobuf::Arena::Create<RepeatedPtrField<MessageLite> >(arena_, arena_);
+ ::google::protobuf::Arena::CreateMessage<RepeatedPtrField<MessageLite> >(arena_);
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index b00461d5..68314fd3 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -114,7 +114,7 @@ const int FieldMask::kPathsFieldNumber;
#endif // !_MSC_VER
FieldMask::FieldMask()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FieldMask)
}
@@ -277,9 +277,9 @@ int FieldMask::ByteSize() const {
void FieldMask::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FieldMask* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FieldMask*>(
- &from);
+ const FieldMask* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -331,10 +331,10 @@ void FieldMask::InternalSwap(FieldMask* other) {
// FieldMask
// repeated string paths = 1;
- int FieldMask::paths_size() const {
+int FieldMask::paths_size() const {
return paths_.size();
}
- void FieldMask::clear_paths() {
+void FieldMask::clear_paths() {
paths_.Clear();
}
const ::std::string& FieldMask::paths(int index) const {
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 4dddf6c7..dc8abb98 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -40,6 +40,7 @@
#include <string>
#include <vector>
+#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
// TODO(jasonh): Remove this once the compiler change to directly include this
// is released to components.
@@ -597,6 +598,42 @@ inline To dynamic_cast_if_available(From from) {
#endif
}
+// Tries to downcast this message to a generated message type.
+// Returns NULL if this class is not an instance of T.
+//
+// This is like dynamic_cast_if_available, except it works even when
+// dynamic_cast is not available by using Reflection. However it only works
+// with Message objects.
+//
+// TODO(haberman): can we remove dynamic_cast_if_available in favor of this?
+template <typename T>
+T* DynamicCastToGenerated(const Message* from) {
+ // Compile-time assert that T is a generated type that has a
+ // default_instance() accessor, but avoid actually calling it.
+ const T&(*get_default_instance)() = &T::default_instance;
+ (void)get_default_instance;
+
+ // Compile-time assert that T is a subclass of google::protobuf::Message.
+ const Message* unused = static_cast<T*>(NULL);
+ (void)unused;
+
+#if defined(GOOGLE_PROTOBUF_NO_RTTI) || \
+ (defined(_MSC_VER) && !defined(_CPPRTTI))
+ bool ok = &T::default_instance() ==
+ from->GetReflection()->GetMessageFactory()->GetPrototype(
+ from->GetDescriptor());
+ return ok ? down_cast<T*>(from) : NULL;
+#else
+ return dynamic_cast<T*>(from);
+#endif
+}
+
+template <typename T>
+T* DynamicCastToGenerated(Message* from) {
+ const Message* message_const = from;
+ return const_cast<T*>(DynamicCastToGenerated<const T>(message_const));
+}
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 678f92a7..6357e27d 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -47,6 +47,10 @@
namespace google {
namespace protobuf {
+
+class Arena;
+namespace io { class CodedInputStream; }
+
namespace internal {
@@ -106,6 +110,15 @@ template <class Type> bool AllAreInitialized(const Type& t) {
return true;
}
+class ArenaString;
+
+// Read a length (varint32), followed by a string, from *input. Return a
+// pointer to a copy of the string that resides in *arena. Requires both
+// args to be non-NULL. If something goes wrong while reading the data
+// then NULL is returned (e.g., input does not start with a valid varint).
+ArenaString* ReadArenaString(::google::protobuf::io::CodedInputStream* input,
+ ::google::protobuf::Arena* arena);
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 93e1a22e..3b8650d6 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -156,6 +156,11 @@ CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
}
+CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
+ uint32 length;
+ return PushLimit(ReadVarint32(&length) ? length : 0);
+}
+
bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
bool result = ConsumedEntireMessage();
PopLimit(limit);
@@ -164,6 +169,12 @@ bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
return result;
}
+bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) {
+ bool result = ConsumedEntireMessage();
+ PopLimit(limit);
+ return result;
+}
+
int CodedInputStream::BytesUntilLimit() const {
if (current_limit_ == INT_MAX) return -1;
int current_position = CurrentPosition();
@@ -245,20 +256,7 @@ bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
}
bool CodedInputStream::ReadRaw(void* buffer, int size) {
- int current_buffer_size;
- while ((current_buffer_size = BufferSize()) < size) {
- // Reading past end of buffer. Copy what we have, then refresh.
- memcpy(buffer, buffer_, current_buffer_size);
- buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
- size -= current_buffer_size;
- Advance(current_buffer_size);
- if (!Refresh()) return false;
- }
-
- memcpy(buffer, buffer_, size);
- Advance(size);
-
- return true;
+ return InternalReadRawInline(buffer, size);
}
bool CodedInputStream::ReadString(string* buffer, int size) {
@@ -336,17 +334,23 @@ bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
namespace {
-inline const uint8* ReadVarint32FromArray(
- const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
+// Read a varint from the given buffer, write it to *value, and return a pair.
+// The first part of the pair is true iff the read was successful. The second
+// part is buffer + (number of bytes read). This function is always inlined,
+// so returning a pair is costless.
+inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+ uint32 first_byte, const uint8* buffer,
+ uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+ uint32 first_byte, const uint8* buffer, uint32* value) {
// Fast path: We have enough bytes left in the buffer to guarantee that
// this read won't cross the end, so we can skip the checks.
+ GOOGLE_DCHECK_EQ(*buffer, first_byte);
+ GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte;
const uint8* ptr = buffer;
uint32 b;
- uint32 result;
-
- b = *(ptr++); result = b ; if (!(b & 0x80)) goto done;
- result -= 0x80;
+ uint32 result = first_byte - 0x80;
+ ++ptr; // We just processed the first byte. Move on to the second.
b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done;
result -= 0x80 << 7;
b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done;
@@ -364,38 +368,42 @@ inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) {
// We have overrun the maximum size of a varint (10 bytes). Assume
// the data is corrupt.
- return NULL;
+ return std::make_pair(false, ptr);
done:
*value = result;
- return ptr;
+ return std::make_pair(true, ptr);
}
} // namespace
bool CodedInputStream::ReadVarint32Slow(uint32* value) {
- uint64 result;
// Directly invoke ReadVarint64Fallback, since we already tried to optimize
// for one-byte varints.
- if (!ReadVarint64Fallback(&result)) return false;
- *value = (uint32)result;
- return true;
+ std::pair<uint64, bool> p = ReadVarint64Fallback();
+ *value = static_cast<uint32>(p.first);
+ return p.second;
}
-bool CodedInputStream::ReadVarint32Fallback(uint32* value) {
+int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
if (BufferSize() >= kMaxVarintBytes ||
// Optimization: We're also safe if the buffer is non-empty and it ends
// with a byte that would terminate a varint.
(buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
- const uint8* end = ReadVarint32FromArray(buffer_, value);
- if (end == NULL) return false;
- buffer_ = end;
- return true;
+ GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
+ << "Caller should provide us with *buffer_ when buffer is non-empty";
+ uint32 temp;
+ ::std::pair<bool, const uint8*> p =
+ ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
+ if (!p.first) return -1;
+ buffer_ = p.second;
+ return temp;
} else {
// Really slow case: we will incur the cost of an extra function call here,
// but moving this out of line reduces the size of this function, which
// improves the common case. In micro benchmarks, this is worth about 10-15%
- return ReadVarint32Slow(value);
+ uint32 temp;
+ return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
}
}
@@ -425,18 +433,24 @@ uint32 CodedInputStream::ReadTagSlow() {
return static_cast<uint32>(result);
}
-uint32 CodedInputStream::ReadTagFallback() {
+uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
const int buf_size = BufferSize();
if (buf_size >= kMaxVarintBytes ||
// Optimization: We're also safe if the buffer is non-empty and it ends
// with a byte that would terminate a varint.
(buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
+ GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]);
+ if (first_byte_or_zero == 0) {
+ ++buffer_;
+ return 0;
+ }
uint32 tag;
- const uint8* end = ReadVarint32FromArray(buffer_, &tag);
- if (end == NULL) {
+ ::std::pair<bool, const uint8*> p =
+ ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
+ if (!p.first) {
return 0;
}
- buffer_ = end;
+ buffer_ = p.second;
return tag;
} else {
// We are commonly at a limit when attempting to read tags. Try to quickly
@@ -479,7 +493,7 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) {
return true;
}
-bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
+std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
if (BufferSize() >= kMaxVarintBytes ||
// Optimization: We're also safe if the buffer is non-empty and it ends
// with a byte that would terminate a varint.
@@ -517,16 +531,18 @@ bool CodedInputStream::ReadVarint64Fallback(uint64* value) {
// We have overrun the maximum size of a varint (10 bytes). The data
// must be corrupt.
- return false;
+ return std::make_pair(0, false);
done:
Advance(ptr - buffer_);
- *value = (static_cast<uint64>(part0) ) |
- (static_cast<uint64>(part1) << 28) |
- (static_cast<uint64>(part2) << 56);
- return true;
+ return std::make_pair((static_cast<uint64>(part0)) |
+ (static_cast<uint64>(part1) << 28) |
+ (static_cast<uint64>(part2) << 56),
+ true);
} else {
- return ReadVarint64Slow(value);
+ uint64 temp;
+ bool success = ReadVarint64Slow(&temp);
+ return std::make_pair(temp, success);
}
}
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index dea4b650..961c1a3f 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -197,6 +197,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Read raw bytes, copying them into the given buffer.
bool ReadRaw(void* buffer, int size);
+ // Like the above, with inlined optimizations. This should only be used
+ // by the protobuf implementation.
+ inline bool InternalReadRawInline(void* buffer,
+ int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+
// Like ReadRaw, but reads into a string.
//
// Implementation Note: ReadString() grows the string gradually as it
@@ -387,9 +392,14 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// under the limit, false if it has gone over.
bool IncrementRecursionDepth();
- // Decrements the recursion depth.
+ // Decrements the recursion depth if possible.
void DecrementRecursionDepth();
+ // Decrements the recursion depth blindly. This is faster than
+ // DecrementRecursionDepth(). It should be used only if all previous
+ // increments to recursion depth were successful.
+ void UnsafeDecrementRecursionDepth();
+
// 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
@@ -398,15 +408,25 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
std::pair<CodedInputStream::Limit, int> IncrementRecursionDepthAndPushLimit(
int byte_limit);
+ // Shorthand for PushLimit(ReadVarint32(&length) ? length : 0).
+ Limit ReadLengthAndPushLimit();
+
// Helper that is equivalent to: {
// bool result = ConsumedEntireMessage();
// PopLimit(limit);
- // DecrementRecursionDepth();
+ // UnsafeDecrementRecursionDepth();
// 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);
+ // Helper that is equivalent to: {
+ // bool result = ConsumedEntireMessage();
+ // PopLimit(limit);
+ // return result; }
+ // Using this can reduce code size and complexity in some cases.
+ bool CheckEntireMessageConsumedAndPopLimit(Limit limit);
+
// Extension Registry ----------------------------------------------
// ADVANCED USAGE: 99.9% of people can ignore this section.
//
@@ -568,9 +588,13 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// optimization. The Slow method is yet another fallback when the buffer is
// not large enough. Making the slow path out-of-line speeds up the common
// case by 10-15%. The slow path is fairly uncommon: it only triggers when a
- // message crosses multiple buffers.
- bool ReadVarint32Fallback(uint32* value);
- bool ReadVarint64Fallback(uint64* value);
+ // message crosses multiple buffers. Note: ReadVarint32Fallback() and
+ // ReadVarint64Fallback() are called frequently and generally not inlined, so
+ // they have been optimized to avoid "out" parameters. The former returns -1
+ // if it fails and the uint32 it read otherwise. The latter has a bool
+ // indicating success or failure as part of its return type.
+ int64 ReadVarint32Fallback(uint32 first_byte_or_zero);
+ std::pair<uint64, bool> ReadVarint64Fallback();
bool ReadVarint32Slow(uint32* value);
bool ReadVarint64Slow(uint64* value);
bool ReadLittleEndian32Fallback(uint32* value);
@@ -578,7 +602,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Fallback/slow methods for reading tags. These do not update last_tag_,
// but will set legitimate_message_end_ if we are at the end of the input
// stream.
- uint32 ReadTagFallback();
+ uint32 ReadTagFallback(uint32 first_byte_or_zero);
uint32 ReadTagSlow();
bool ReadStringFallback(string* buffer, int size);
@@ -818,13 +842,18 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// methods optimize for that case.
inline bool CodedInputStream::ReadVarint32(uint32* value) {
- if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) {
- *value = *buffer_;
- Advance(1);
- return true;
- } else {
- return ReadVarint32Fallback(value);
+ uint32 v = 0;
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
+ v = *buffer_;
+ if (v < 0x80) {
+ *value = v;
+ Advance(1);
+ return true;
+ }
}
+ int64 result = ReadVarint32Fallback(v);
+ *value = static_cast<uint32>(result);
+ return result >= 0;
}
inline bool CodedInputStream::ReadVarint64(uint64* value) {
@@ -832,9 +861,10 @@ inline bool CodedInputStream::ReadVarint64(uint64* value) {
*value = *buffer_;
Advance(1);
return true;
- } else {
- return ReadVarint64Fallback(value);
}
+ std::pair<uint64, bool> p = ReadVarint64Fallback();
+ *value = p.first;
+ return p.second;
}
// static
@@ -903,14 +933,17 @@ inline bool CodedInputStream::ReadLittleEndian64(uint64* value) {
}
inline uint32 CodedInputStream::ReadTag() {
- if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] < 0x80) {
- last_tag_ = buffer_[0];
- Advance(1);
- return last_tag_;
- } else {
- last_tag_ = ReadTagFallback();
- return last_tag_;
+ uint32 v = 0;
+ if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
+ v = *buffer_;
+ if (v < 0x80) {
+ last_tag_ = v;
+ Advance(1);
+ return v;
+ }
}
+ last_tag_ = ReadTagFallback(v);
+ return last_tag_;
}
inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
@@ -918,10 +951,12 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
// In performance-sensitive code we can expect cutoff to be a compile-time
// constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at
// compile time.
+ uint32 first_byte_or_zero = 0;
if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
// Hot case: buffer_ non_empty, buffer_[0] in [1, 128).
// TODO(gpike): Is it worth rearranging this? E.g., if the number of fields
// is large enough then is it better to check for the two-byte case first?
+ first_byte_or_zero = buffer_[0];
if (static_cast<int8>(buffer_[0]) > 0) {
const uint32 kMax1ByteVarint = 0x7f;
uint32 tag = last_tag_ = buffer_[0];
@@ -948,7 +983,7 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
}
}
// Slow path
- last_tag_ = ReadTagFallback();
+ last_tag_ = ReadTagFallback(first_byte_or_zero);
return std::make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
}
@@ -1177,6 +1212,11 @@ inline void CodedInputStream::DecrementRecursionDepth() {
if (recursion_budget_ < recursion_limit_) ++recursion_budget_;
}
+inline void CodedInputStream::UnsafeDecrementRecursionDepth() {
+ assert(recursion_budget_ < recursion_limit_);
+ ++recursion_budget_;
+}
+
inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool,
MessageFactory* factory) {
extension_pool_ = pool;
diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h
index cd8d1746..fa20f208 100644
--- a/src/google/protobuf/io/coded_stream_inl.h
+++ b/src/google/protobuf/io/coded_stream_inl.h
@@ -66,6 +66,23 @@ inline bool CodedInputStream::InternalReadStringInline(string* buffer,
return ReadStringFallback(buffer, size);
}
+inline bool CodedInputStream::InternalReadRawInline(void* buffer, int size) {
+ int current_buffer_size;
+ while ((current_buffer_size = BufferSize()) < size) {
+ // Reading past end of buffer. Copy what we have, then refresh.
+ memcpy(buffer, buffer_, current_buffer_size);
+ buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
+ size -= current_buffer_size;
+ Advance(current_buffer_size);
+ if (!Refresh()) return false;
+ }
+
+ memcpy(buffer, buffer_, size);
+ Advance(size);
+
+ return true;
+}
+
} // namespace io
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index e621ba1d..3ae8c268 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -155,6 +155,78 @@ 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,
+ const char* variable5, const string& value5) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ 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,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ vars[variable6] = value6;
+ 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,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ vars[variable6] = value6;
+ vars[variable7] = value7;
+ 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,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7,
+ const char* variable8, const string& value8) {
+ map<string, string> vars;
+ vars[variable1] = value1;
+ vars[variable2] = value2;
+ vars[variable3] = value3;
+ vars[variable4] = value4;
+ vars[variable5] = value5;
+ vars[variable6] = value6;
+ vars[variable7] = value7;
+ vars[variable8] = value8;
+ Print(vars, text);
+}
+
void Printer::Indent() {
indent_ += " ";
}
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index 92ce3409..f1490bbe 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -91,8 +91,36 @@ class LIBPROTOBUF_EXPORT Printer {
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.
+ // 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,
+ const char* variable5, const string& value5);
+ // 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,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6);
+ // 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,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7);
+ // 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,
+ const char* variable5, const string& value5,
+ const char* variable6, const string& value6,
+ const char* variable7, const string& value7,
+ const char* variable8, const string& value8);
// Indent text by two spaces. After calling Indent(), two spaces will be
// inserted at the beginning of each line of text. Indent() may be called
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index 4ea21007..1995cf08 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -34,12 +34,16 @@
#include <iostream>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_lite_test_util.h>
#include <google/protobuf/test_util_lite.h>
#include <google/protobuf/unittest_lite.pb.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/stubs/strutil.h>
using namespace std;
@@ -84,6 +88,12 @@ void SetSomeTypesInEmptyMessageUnknownFields(
} // namespace
+#define EXPECT_TRUE GOOGLE_CHECK
+#define ASSERT_TRUE GOOGLE_CHECK
+#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND))
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+#define ASSERT_EQ GOOGLE_CHECK_EQ
+
int main(int argc, char* argv[]) {
string data, data2, packed_data;
@@ -345,6 +355,374 @@ int main(int argc, char* argv[]) {
GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size());
}
+ // Tests for map lite =============================================
+
+ {
+ // Accessors
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+
+ google::protobuf::MapLiteTestUtil::ModifyMapFields(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message);
+ }
+
+ {
+ // SetMapFieldsInitialized
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFieldsInitialized(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSetInitialized(message);
+ }
+
+ {
+ // Proto2SetMapFieldsInitialized
+ protobuf_unittest::TestEnumStartWithNonZeroMapLite message;
+ EXPECT_EQ(protobuf_unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE,
+ (*message.mutable_map_field())[0]);
+ }
+
+ {
+ // Clear
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+ message.Clear();
+ google::protobuf::MapLiteTestUtil::ExpectClear(message);
+ }
+
+ {
+ // ClearMessageMap
+ protobuf_unittest::TestMessageMapLite message;
+
+ // Creates a TestAllTypes with default value
+ google::protobuf::TestUtilLite::ExpectClear(
+ (*message.mutable_map_int32_message())[0]);
+ }
+
+ {
+ // CopyFrom
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ message2.CopyFrom(message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+
+ // Copying from self should be a no-op.
+ message2.CopyFrom(message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // CopyFromMessageMap
+ protobuf_unittest::TestMessageMapLite message1, message2;
+
+ (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+ (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+ message1.CopyFrom(message2);
+
+ // Checks repeated field is overwritten.
+ EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+ EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+ }
+
+ {
+ // SwapWithEmpty
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1);
+ google::protobuf::MapLiteTestUtil::ExpectClear(message2);
+
+ message1.Swap(&message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ google::protobuf::MapLiteTestUtil::ExpectClear(message1);
+ }
+
+ {
+ // SwapWithSelf
+ protobuf_unittest::TestMapLite message;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+
+ message.Swap(&message);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message);
+ }
+
+ {
+ // SwapWithOther
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message2);
+ google::protobuf::MapLiteTestUtil::ModifyMapFields(&message2);
+
+ message1.Swap(&message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // CopyConstructor
+ protobuf_unittest::TestMapLite message1;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+ protobuf_unittest::TestMapLite message2(message1);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // CopyAssignmentOperator
+ protobuf_unittest::TestMapLite message1;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+ protobuf_unittest::TestMapLite message2;
+ message2 = message1;
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+
+ // Make sure that self-assignment does something sane.
+ message2.operator=(message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // NonEmptyMergeFrom
+ protobuf_unittest::TestMapLite message1, message2;
+
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+
+ // This field will test merging into an empty spot.
+ (*message2.mutable_map_int32_int32())[1] = 1;
+ message1.mutable_map_int32_int32()->erase(1);
+
+ // This tests overwriting.
+ (*message2.mutable_map_int32_double())[1] = 1;
+ (*message1.mutable_map_int32_double())[1] = 2;
+
+ message1.MergeFrom(message2);
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1);
+ }
+
+ {
+ // MergeFromMessageMap
+ protobuf_unittest::TestMessageMapLite message1, message2;
+
+ (*message1.mutable_map_int32_message())[0].add_repeated_int32(100);
+ (*message2.mutable_map_int32_message())[0].add_repeated_int32(101);
+
+ message1.MergeFrom(message2);
+
+ // Checks repeated field is overwritten.
+ EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size());
+ EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0));
+ }
+
+ {
+ // Test the generated SerializeWithCachedSizesToArray()
+ protobuf_unittest::TestMapLite message1, message2;
+ string data;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ int size = message1.ByteSize();
+ data.resize(size);
+ ::google::protobuf::uint8* start = reinterpret_cast< ::google::protobuf::uint8*>(::google::protobuf::string_as_array(&data));
+ ::google::protobuf::uint8* end = message1.SerializeWithCachedSizesToArray(start);
+ EXPECT_EQ(size, end - start);
+ EXPECT_TRUE(message2.ParseFromString(data));
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+ {
+ // Test the generated SerializeWithCachedSizes()
+ protobuf_unittest::TestMapLite message1, message2;
+ google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
+ int size = message1.ByteSize();
+ string data;
+ data.resize(size);
+ {
+ // Allow the output stream to buffer only one byte at a time.
+ google::protobuf::io::ArrayOutputStream array_stream(
+ ::google::protobuf::string_as_array(&data), size, 1);
+ google::protobuf::io::CodedOutputStream output_stream(&array_stream);
+ message1.SerializeWithCachedSizes(&output_stream);
+ EXPECT_FALSE(output_stream.HadError());
+ EXPECT_EQ(size, output_stream.ByteCount());
+ }
+ EXPECT_TRUE(message2.ParseFromString(data));
+ google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2);
+ }
+
+
+ {
+ // Proto2UnknownEnum
+ protobuf_unittest::TestEnumMapPlusExtraLite from;
+ (*from.mutable_known_map_field())[0] =
+ protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE;
+ (*from.mutable_unknown_map_field())[0] =
+ protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE;
+ string data;
+ from.SerializeToString(&data);
+
+ protobuf_unittest::TestEnumMapLite to;
+ EXPECT_TRUE(to.ParseFromString(data));
+ EXPECT_EQ(0, to.unknown_map_field().size());
+ EXPECT_FALSE(to.mutable_unknown_fields()->empty());
+ EXPECT_EQ(1, to.known_map_field().size());
+ EXPECT_EQ(protobuf_unittest::PROTO2_MAP_ENUM_FOO_LITE,
+ to.known_map_field().at(0));
+
+ data.clear();
+ from.Clear();
+ to.SerializeToString(&data);
+ EXPECT_TRUE(from.ParseFromString(data));
+ EXPECT_EQ(1, from.known_map_field().size());
+ EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE,
+ from.known_map_field().at(0));
+ EXPECT_EQ(1, from.unknown_map_field().size());
+ EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE,
+ from.unknown_map_field().at(0));
+ }
+
+ {
+ // StandardWireFormat
+ protobuf_unittest::TestMapLite message;
+ string data = "\x0A\x04\x08\x01\x10\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(1));
+ }
+
+ {
+ // UnorderedWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // put value before key in wire format
+ string data = "\x0A\x04\x10\x01\x08\x02";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(2));
+ }
+
+ {
+ // DuplicatedKeyWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // Two key fields in wire format
+ string data = "\x0A\x06\x08\x01\x08\x02\x10\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(2));
+ }
+
+ {
+ // DuplicatedValueWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // Two value fields in wire format
+ string data = "\x0A\x06\x08\x01\x10\x01\x10\x02";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int32_int32().at(1));
+ }
+
+ {
+ // MissedKeyWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // No key field in wire format
+ string data = "\x0A\x02\x10\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int32_int32().at(0));
+ }
+
+ {
+ // MissedValueWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // No value field in wire format
+ string data = "\x0A\x02\x08\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(0, message.map_int32_int32().at(1));
+ }
+
+ {
+ // UnknownFieldWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // Unknown field in wire format
+ string data = "\x0A\x06\x08\x02\x10\x03\x18\x01";
+
+ EXPECT_TRUE(message.ParseFromString(data));
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(3, message.map_int32_int32().at(2));
+ }
+
+ {
+ // CorruptedWireFormat
+ protobuf_unittest::TestMapLite message;
+
+ // corrupted data in wire format
+ string data = "\x0A\x06\x08\x02\x11\x03";
+
+ EXPECT_FALSE(message.ParseFromString(data));
+ }
+
+ {
+ // IsInitialized
+ protobuf_unittest::TestRequiredMessageMapLite map_message;
+
+ // Add an uninitialized message.
+ (*map_message.mutable_map_field())[0];
+ EXPECT_FALSE(map_message.IsInitialized());
+
+ // Initialize uninitialized message
+ (*map_message.mutable_map_field())[0].set_a(0);
+ (*map_message.mutable_map_field())[0].set_b(0);
+ (*map_message.mutable_map_field())[0].set_c(0);
+ EXPECT_TRUE(map_message.IsInitialized());
+ }
+
+ // arena support for map =========================================
+
+ {
+ // ParsingAndSerializingNoHeapAllocation
+
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ google::protobuf::ArenaOptions options;
+ options.initial_block = arena_block.data();
+ options.initial_block_size = arena_block.size();
+ google::protobuf::Arena arena(options);
+ string data;
+ data.reserve(128 * 1024);
+
+ {
+ google::protobuf::internal::NoHeapChecker no_heap;
+
+ protobuf_unittest::TestArenaMapLite* from =
+ google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
+ &arena);
+ google::protobuf::MapLiteTestUtil::SetArenaMapFields(from);
+ from->SerializeToString(&data);
+
+ protobuf_unittest::TestArenaMapLite* to =
+ google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
+ &arena);
+ to->ParseFromString(data);
+ google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to);
+ }
+ }
+
std::cout << "PASS" << std::endl;
return 0;
}
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index e56af3fc..1858e2f9 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -422,6 +422,7 @@ class Map {
int default_enum_value_;
friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
template <typename K, typename V,
internal::WireFormatLite::FieldType key_wire_type,
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 304fba88..2d11bea8 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -267,17 +267,18 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
// google::protobuf::Map is enum. We cannot create a reference to int from an enum.
static MapEntryLite* EnumWrap(const Key& key, const Value value,
Arena* arena) {
- return Arena::Create<MapEnumEntryWrapper<
+ return Arena::CreateMessage<MapEnumEntryWrapper<
Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
- arena, key, value, arena);
+ arena, key, value);
}
// Like above, but for all the other types. This avoids value copy to create
// MapEntryLite from google::protobuf::Map in serialization.
static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) {
- return Arena::Create<MapEntryWrapper<Key, Value, kKeyFieldType,
- kValueFieldType, default_enum_value> >(
- arena, key, value, arena);
+ return Arena::CreateMessage<MapEntryWrapper<Key, Value, kKeyFieldType,
+ kValueFieldType,
+ default_enum_value> >(
+ arena, key, value);
}
protected:
@@ -308,7 +309,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
typedef typename Base::ValCppType ValCppType;
public:
- MapEntryWrapper(const K& key, const V& value, Arena* arena)
+ MapEntryWrapper(Arena* arena, const K& key, const V& value)
: MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
key_(key),
value_(value) {
@@ -323,6 +324,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
const Value& value_;
friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
};
@@ -341,7 +343,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
typedef typename Base::ValCppType ValCppType;
public:
- MapEnumEntryWrapper(const K& key, const V& value, Arena* arena)
+ MapEnumEntryWrapper(Arena* arena, const K& key, const V& value)
: MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
key_(key),
value_(value) {
@@ -355,7 +357,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
const KeyCppType& key_;
const ValCppType value_;
- friend class ::google::protobuf::Arena;
+ friend class LIBPROTOBUF_EXPORT google::protobuf::Arena;
typedef void DestructorSkippable_;
};
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index fd40c0d8..6ff1936e 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -104,14 +104,18 @@ void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; }
void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
void MapFieldBase::SyncRepeatedFieldWithMap() const {
- Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
+ // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
+ // executed before state_ is checked.
+ Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
if (state == STATE_MODIFIED_MAP) {
mutex_.Lock();
// Double check state, because another thread may have seen the same state
// and done the synchronization before the current thread.
if (state_ == STATE_MODIFIED_MAP) {
SyncRepeatedFieldWithMapNoLock();
- google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
+ // "Release" insures state_ can only be changed "after"
+ // SyncRepeatedFieldWithMapNoLock is finished.
+ google::protobuf::internal::Release_Store(&state_, CLEAN);
}
mutex_.Unlock();
}
@@ -119,19 +123,23 @@ void MapFieldBase::SyncRepeatedFieldWithMap() const {
void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
if (repeated_field_ == NULL) {
- repeated_field_ = Arena::Create<RepeatedPtrField<Message> >(arena_, arena_);
+ repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
}
}
void MapFieldBase::SyncMapWithRepeatedField() const {
- Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_);
+ // "Acquire" insures the operation after SyncMapWithRepeatedField won't get
+ // executed before state_ is checked.
+ Atomic32 state = google::protobuf::internal::Acquire_Load(&state_);
if (state == STATE_MODIFIED_REPEATED) {
mutex_.Lock();
// Double check state, because another thread may have seen the same state
// and done the synchronization before the current thread.
if (state_ == STATE_MODIFIED_REPEATED) {
SyncMapWithRepeatedFieldNoLock();
- google::protobuf::internal::NoBarrier_Store(&state_, CLEAN);
+ // "Release" insures state_ can only be changed "after"
+ // SyncRepeatedFieldWithMapNoLock is finished.
+ google::protobuf::internal::Release_Store(&state_, CLEAN);
}
mutex_.Unlock();
}
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 6d8b6ec8..f3504f1b 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -208,6 +208,7 @@ class LIBPROTOBUF_EXPORT MapField : public MapFieldBase,
void SetAssignDescriptorCallback(void (*callback)());
private:
+ typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
// MapField needs MapEntry's default instance to create new MapEntry.
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index ae63c721..cbfc0c8f 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -216,7 +216,7 @@ MapField<Key, T, kKeyFieldType, kValueFieldType,
repeated_field_ = new RepeatedPtrField<Message>();
} else {
repeated_field_ =
- Arena::Create<RepeatedPtrField<Message> >(arena_, arena_);
+ Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
}
}
const Map<Key, T>& map = GetInternalMap();
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
index 549ecc08..40322851 100644
--- a/src/google/protobuf/map_field_lite.h
+++ b/src/google/protobuf/map_field_lite.h
@@ -109,7 +109,7 @@ template <typename Key, typename T,
MapFieldLite<Key, T, key_wire_type, value_wire_type,
default_enum_value>::MapFieldLite(Arena* arena)
: arena_(arena) {
- map_ = Arena::Create<Map<Key, T> >(arena, arena);
+ map_ = Arena::CreateMessage<Map<Key, T> >(arena);
SetDefaultEnumValue();
}
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 61344cbb..f4681866 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -56,6 +56,7 @@ using unittest::TestAllTypes;
class MapFieldBaseStub : public MapFieldBase {
public:
+ typedef void InternalArenaConstructable_;
typedef void DestructorSkippable_;
MapFieldBaseStub() {}
explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
@@ -149,10 +150,12 @@ TEST_F(MapFieldBasePrimitiveTest, Arena) {
Arena arena(options);
{
- NoHeapChecker no_heap;
+ // TODO(liujisi): Re-write the test to ensure the memory for the map and
+ // repeated fields are allocated from arenas.
+ // NoHeapChecker no_heap;
MapFieldType* map_field =
- Arena::Create<MapFieldType>(&arena, &arena, default_entry_);
+ Arena::CreateMessage<MapFieldType>(&arena, default_entry_);
// Set content in map
(*map_field->MutableMap())[100] = 101;
@@ -162,10 +165,12 @@ TEST_F(MapFieldBasePrimitiveTest, Arena) {
}
{
- NoHeapChecker no_heap;
+ // TODO(liujisi): Re-write the test to ensure the memory for the map and
+ // repeated fields are allocated from arenas.
+ // NoHeapChecker no_heap;
MapFieldBaseStub* map_field =
- Arena::Create<MapFieldBaseStub>(&arena, &arena);
+ Arena::CreateMessage<MapFieldBaseStub>(&arena);
// Trigger conversion to repeated field.
EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 88cba1f2..447f52d9 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -2258,6 +2258,27 @@ TEST(TextFormatMapTest, SerializeAndParse) {
MapTestUtil::ExpectMapFieldsSet(dest);
}
+TEST(TextFormatMapTest, Sorted) {
+ unittest::TestMap message;
+ MapTestUtil::MapReflectionTester tester(message.GetDescriptor());
+ tester.SetMapFieldsViaReflection(&message);
+
+ string expected_text;
+ GOOGLE_CHECK_OK(File::GetContents(
+ TestSourceDir() +
+ "/google/protobuf/"
+ "testdata/map_test_data.txt",
+ &expected_text, true));
+
+ EXPECT_EQ(message.DebugString(), expected_text);
+
+ // Test again on the reverse order.
+ unittest::TestMap message2;
+ tester.SetMapFieldsViaReflection(&message2);
+ tester.SwapMapsViaReflection(&message2);
+ EXPECT_EQ(message2.DebugString(), expected_text);
+}
+
// arena support =================================================
TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 278b78ae..ffdb6dfb 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -129,11 +129,11 @@ class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
// Return bytes used by value in Map.
static int SpaceUsedInMap(const Type& value) { return value.SpaceUsed(); }
static inline void Clear(Type** value) {
- if (*value != NULL) (*value)->Type::Clear();
+ if (*value != NULL) (*value)->Clear();
}
static inline void ClearMaybeByDefaultEnum(Type** value,
int default_enum_value) {
- if (*value != NULL) (*value)->Type::Clear();
+ if (*value != NULL) (*value)->Clear();
}
static inline void Merge(const Type& from, Type** to) {
(*to)->MergeFrom(from);
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index b6a988b3..cbf747d9 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -62,7 +62,7 @@ message TestMap {
}
message TestMapSubmessage {
- optional TestMap test_map = 1;
+ TestMap test_map = 1;
}
message TestMessageMap {
@@ -104,3 +104,17 @@ message TestArenaMap {
map<int32 , MapEnum > map_int32_enum = 14;
map<int32 , ForeignMessage> map_int32_foreign_message = 15;
}
+
+// Previously, message containing enum called Type cannot be used as value of
+// map field.
+message MessageContainingEnumCalledType {
+ enum Type {
+ TYPE_FOO = 0;
+ }
+ map<int32, MessageContainingEnumCalledType> type = 1;
+}
+
+// Previously, message cannot contain map field called "entry".
+message MessageContainingMapCalledEntry {
+ map<int32, int32> entry = 1;
+}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index f58be848..276d7de5 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -465,10 +465,21 @@ struct ShutdownRepeatedFieldRegister {
} // namespace internal
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);
+template<>
+Message* GenericTypeHandler<Message>::NewFromPrototype(
+ const Message* prototype, google::protobuf::Arena* arena) {
+ return prototype->New(arena);
+}
+template<>
+google::protobuf::Arena* GenericTypeHandler<Message>::GetArena(
+ Message* value) {
+ return value->GetArena();
+}
+template<>
+void* GenericTypeHandler<Message>::GetMaybeArenaPointer(
+ Message* value) {
+ return value->GetMaybeArenaPointer();
+}
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 6e1929e5..18c092d0 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -98,11 +98,11 @@
//
// // Use the reflection interface to examine the contents.
// const Reflection* reflection = foo->GetReflection();
-// assert(reflection->GetString(foo, text_field) == "Hello World!");
-// assert(reflection->FieldSize(foo, numbers_field) == 3);
-// assert(reflection->GetRepeatedInt32(foo, numbers_field, 0) == 1);
-// assert(reflection->GetRepeatedInt32(foo, numbers_field, 1) == 5);
-// assert(reflection->GetRepeatedInt32(foo, numbers_field, 2) == 42);
+// assert(reflection->GetString(*foo, text_field) == "Hello World!");
+// assert(reflection->FieldSize(*foo, numbers_field) == 3);
+// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 0) == 1);
+// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 1) == 5);
+// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 2) == 42);
//
// delete foo;
// }
@@ -229,6 +229,11 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// Computes (an estimate of) the total number of bytes currently used for
// storing the message in memory. The default implementation calls the
// Reflection object's SpaceUsed() method.
+ //
+ // SpaceUsed() is noticeably slower than ByteSize(), as it is implemented
+ // using reflection (rather than the generated code implementation for
+ // ByteSize()). Like ByteSize(), its CPU time is linear in the number of
+ // fields defined for the proto.
virtual int SpaceUsed() const;
// Debugging & Testing----------------------------------------------
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 63be0e9b..4f63ad2b 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -337,7 +337,7 @@ bool MessageLite::SerializePartialToArray(void* data, int size) const {
string MessageLite::SerializeAsString() const {
// If the compiler implements the (Named) Return Value Optimization,
- // the local variable 'result' will not actually reside on the stack
+ // the local variable 'output' will not actually reside on the stack
// of this function, but will be overlaid with the object that the
// caller supplied for the return value to be constructed in.
string output;
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index eab61c14..4c16f4c0 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -238,6 +238,9 @@ class LIBPROTOBUF_EXPORT MessageLite {
// Computes the serialized size of the message. This recursively calls
// ByteSize() on all embedded messages. If a subclass does not override
// this, it MUST override SetCachedSize().
+ //
+ // ByteSize() is generally linear in the number of fields defined for the
+ // proto.
virtual int ByteSize() const = 0;
// Serializes the message without recomputing the size. The message must
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index ebfb4321..75d60b8b 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -45,12 +45,13 @@
#include <sstream>
#include <fstream>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/test_util.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
@@ -205,6 +206,28 @@ TEST(MessageTest, InitializationErrorString) {
EXPECT_EQ("a, b, c", message.InitializationErrorString());
}
+TEST(MessageTest, DynamicCastToGenerated) {
+ unittest::TestAllTypes test_all_types;
+
+ google::protobuf::Message* test_all_types_pointer = &test_all_types;
+ EXPECT_EQ(&test_all_types,
+ google::protobuf::internal::DynamicCastToGenerated<unittest::TestAllTypes>(
+ test_all_types_pointer));
+ EXPECT_EQ(NULL,
+ google::protobuf::internal::DynamicCastToGenerated<unittest::TestRequired>(
+ test_all_types_pointer));
+
+ const google::protobuf::Message* test_all_types_pointer_const = &test_all_types;
+ EXPECT_EQ(
+ &test_all_types,
+ google::protobuf::internal::DynamicCastToGenerated<const unittest::TestAllTypes>(
+ test_all_types_pointer_const));
+ EXPECT_EQ(
+ NULL,
+ google::protobuf::internal::DynamicCastToGenerated<const unittest::TestRequired>(
+ test_all_types_pointer_const));
+}
+
#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet.
TEST(MessageTest, SerializeFailsIfNotInitialized) {
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index c3b5996f..da4be673 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -180,6 +180,16 @@ TEST(ArenaTest, ReleaseMessage) {
EXPECT_EQ(118, nested->bb());
}
+TEST(ArenaTest, MessageFieldClear) {
+ // GitHub issue #310: https://github.com/google/protobuf/issues/310
+ Arena arena;
+ TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+ arena_message->mutable_optional_nested_message()->set_bb(118);
+ // This should not crash, but prior to the bugfix, it tried to use `operator
+ // delete` the nested message (which is on the arena):
+ arena_message->Clear();
+}
+
} // namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index 03c761c1..4ff0f6b4 100755
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -39,6 +39,7 @@
#endif
#include <google/protobuf/message.h>
+#include <google/protobuf/generated_enum_util.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 7bfdc40a..5a2fb409 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -576,26 +576,21 @@ class GenericTypeHandler {
}
};
-// 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)
+template<>
+inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+ const MessageLite* prototype, google::protobuf::Arena* arena) {
+ return prototype->New(arena);
+}
+template<>
+inline google::protobuf::Arena* GenericTypeHandler<MessageLite>::GetArena(
+ MessageLite* value) {
+ return value->GetArena();
+}
+template<>
+inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
+ MessageLite* value) {
+ return value->GetMaybeArenaPointer();
+}
// Implements GenericTypeHandler specialization required by RepeatedPtrFields
// to work with MessageLite type.
@@ -605,8 +600,6 @@ inline void GenericTypeHandler<MessageLite>::Merge(
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) \
@@ -1235,6 +1228,7 @@ void RepeatedField<Element>::Reserve(int new_size) {
kRepHeaderSize + sizeof(Element)*new_size));
}
rep_->arena = arena;
+ int old_total_size = total_size_;
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
@@ -1253,15 +1247,17 @@ void RepeatedField<Element>::Reserve(int new_size) {
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);
+ if (old_rep) {
+ // 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[old_total_size];
+ for (; e < limit; e++) {
+ e->Element::~Element();
+ }
+ if (arena == NULL) {
+ delete[] reinterpret_cast<char*>(old_rep);
+ }
}
}
@@ -1418,7 +1414,7 @@ void RepeatedPtrFieldBase::Clear() {
const int n = current_size_;
GOOGLE_DCHECK_GE(n, 0);
if (n > 0) {
- void* const* elements = raw_data();
+ void* const* elements = rep_->elements;
int i = 0;
do {
TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 66e74523..af397932 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -456,6 +456,28 @@ TEST(RepeatedField, ExtractSubrange) {
}
}
+TEST(RepeatedField, ClearThenReserveMore) {
+ // Test that Reserve properly destroys the old internal array when it's forced
+ // to allocate a new one, even when cleared-but-not-deleted objects are
+ // present. Use a 'string' and > 16 bytes length so that the elements are
+ // non-POD and allocate -- the leak checker will catch any skipped destructor
+ // calls here.
+ RepeatedField<string> field;
+ for (int i = 0; i < 32; i++) {
+ field.Add(string("abcdefghijklmnopqrstuvwxyz0123456789"));
+ }
+ EXPECT_EQ(32, field.size());
+ field.Clear();
+ EXPECT_EQ(0, field.size());
+ EXPECT_EQ(32, field.Capacity());
+
+ field.Reserve(1024);
+ EXPECT_EQ(0, field.size());
+ EXPECT_EQ(1024, field.Capacity());
+ // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed
+ // strings.
+}
+
// ===================================================================
// RepeatedPtrField tests. These pretty much just mirror the RepeatedField
// tests above.
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 0926e747..3b3799a9 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -114,7 +114,7 @@ const int SourceContext::kFileNameFieldNumber;
#endif // !_MSC_VER
SourceContext::SourceContext()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.SourceContext)
}
@@ -277,9 +277,9 @@ int SourceContext::ByteSize() const {
void SourceContext::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const SourceContext* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const SourceContext*>(
- &from);
+ const SourceContext* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -334,7 +334,7 @@ void SourceContext::InternalSwap(SourceContext* other) {
// SourceContext
// optional string file_name = 1;
- void SourceContext::clear_file_name() {
+void SourceContext::clear_file_name() {
file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& SourceContext::file_name() const {
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 4405a5bf..30113cdb 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -217,7 +217,7 @@ const int Struct::kFieldsFieldNumber;
#endif // !_MSC_VER
Struct::Struct()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Struct)
}
@@ -295,7 +295,8 @@ bool Struct::MergePartialFromCodedStream(
// map<string, .google.protobuf.Value> fields = 1;
case 1: {
if (tag == 10) {
- parse_fields:
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_fields:
::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry(fields_.NewEntry());
DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
input, entry.get()));
@@ -303,7 +304,8 @@ bool Struct::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
- if (input->ExpectTag(10)) goto parse_fields;
+ if (input->ExpectTag(10)) goto parse_loop_fields;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -336,7 +338,8 @@ void Struct::SerializeWithCachedSizes(
{
::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
- it = fields().begin(); it != fields().end(); ++it) {
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
entry.reset(fields_.NewEntryWrapper(it->first, it->second));
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
1, *entry, output);
@@ -353,7 +356,8 @@ void Struct::SerializeWithCachedSizes(
{
::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
- it = fields().begin(); it != fields().end(); ++it) {
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
entry.reset(fields_.NewEntryWrapper(it->first, it->second));
target = ::google::protobuf::internal::WireFormatLite::
WriteMessageNoVirtualToArray(
@@ -373,7 +377,8 @@ int Struct::ByteSize() const {
{
::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
- it = fields().begin(); it != fields().end(); ++it) {
+ it = this->fields().begin();
+ it != this->fields().end(); ++it) {
entry.reset(fields_.NewEntryWrapper(it->first, it->second));
total_size += ::google::protobuf::internal::WireFormatLite::
MessageSizeNoVirtual(*entry);
@@ -388,9 +393,9 @@ int Struct::ByteSize() const {
void Struct::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Struct* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Struct*>(
- &from);
+ const Struct* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Struct>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -442,10 +447,10 @@ void Struct::InternalSwap(Struct* other) {
// Struct
// map<string, .google.protobuf.Value> fields = 1;
- int Struct::fields_size() const {
+int Struct::fields_size() const {
return fields_.size();
}
- void Struct::clear_fields() {
+void Struct::clear_fields() {
fields_.Clear();
}
const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >&
@@ -473,7 +478,7 @@ const int Value::kListValueFieldNumber;
#endif // !_MSC_VER
Value::Value()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Value)
}
@@ -845,9 +850,9 @@ int Value::ByteSize() const {
void Value::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Value* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Value*>(
- &from);
+ const Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Value>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -928,13 +933,13 @@ void Value::InternalSwap(Value* other) {
// Value
// optional .google.protobuf.NullValue null_value = 1;
- bool Value::has_null_value() const {
+bool Value::has_null_value() const {
return kind_case() == kNullValue;
}
- void Value::set_has_null_value() {
+void Value::set_has_null_value() {
_oneof_case_[0] = kNullValue;
}
- void Value::clear_null_value() {
+void Value::clear_null_value() {
if (has_null_value()) {
kind_.null_value_ = 0;
clear_has_kind();
@@ -957,13 +962,13 @@ void Value::InternalSwap(Value* other) {
}
// optional double number_value = 2;
- bool Value::has_number_value() const {
+bool Value::has_number_value() const {
return kind_case() == kNumberValue;
}
- void Value::set_has_number_value() {
+void Value::set_has_number_value() {
_oneof_case_[0] = kNumberValue;
}
- void Value::clear_number_value() {
+void Value::clear_number_value() {
if (has_number_value()) {
kind_.number_value_ = 0;
clear_has_kind();
@@ -986,13 +991,13 @@ void Value::InternalSwap(Value* other) {
}
// optional string string_value = 3;
- bool Value::has_string_value() const {
+bool Value::has_string_value() const {
return kind_case() == kStringValue;
}
- void Value::set_has_string_value() {
+void Value::set_has_string_value() {
_oneof_case_[0] = kStringValue;
}
- void Value::clear_string_value() {
+void Value::clear_string_value() {
if (has_string_value()) {
kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_kind();
@@ -1066,13 +1071,13 @@ void Value::InternalSwap(Value* other) {
}
// optional bool bool_value = 4;
- bool Value::has_bool_value() const {
+bool Value::has_bool_value() const {
return kind_case() == kBoolValue;
}
- void Value::set_has_bool_value() {
+void Value::set_has_bool_value() {
_oneof_case_[0] = kBoolValue;
}
- void Value::clear_bool_value() {
+void Value::clear_bool_value() {
if (has_bool_value()) {
kind_.bool_value_ = false;
clear_has_kind();
@@ -1095,13 +1100,13 @@ void Value::InternalSwap(Value* other) {
}
// optional .google.protobuf.Struct struct_value = 5;
- bool Value::has_struct_value() const {
+bool Value::has_struct_value() const {
return kind_case() == kStructValue;
}
- void Value::set_has_struct_value() {
+void Value::set_has_struct_value() {
_oneof_case_[0] = kStructValue;
}
- void Value::clear_struct_value() {
+void Value::clear_struct_value() {
if (has_struct_value()) {
delete kind_.struct_value_;
clear_has_kind();
@@ -1141,13 +1146,13 @@ void Value::InternalSwap(Value* other) {
}
// optional .google.protobuf.ListValue list_value = 6;
- bool Value::has_list_value() const {
+bool Value::has_list_value() const {
return kind_case() == kListValue;
}
- void Value::set_has_list_value() {
+void Value::set_has_list_value() {
_oneof_case_[0] = kListValue;
}
- void Value::clear_list_value() {
+void Value::clear_list_value() {
if (has_list_value()) {
delete kind_.list_value_;
clear_has_kind();
@@ -1186,10 +1191,10 @@ void Value::InternalSwap(Value* other) {
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value)
}
- bool Value::has_kind() const {
+bool Value::has_kind() const {
return kind_case() != KIND_NOT_SET;
}
- void Value::clear_has_kind() {
+void Value::clear_has_kind() {
_oneof_case_[0] = KIND_NOT_SET;
}
Value::KindCase Value::kind_case() const {
@@ -1204,7 +1209,7 @@ const int ListValue::kValuesFieldNumber;
#endif // !_MSC_VER
ListValue::ListValue()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.ListValue)
}
@@ -1278,13 +1283,15 @@ bool ListValue::MergePartialFromCodedStream(
// repeated .google.protobuf.Value values = 1;
case 1: {
if (tag == 10) {
- parse_values:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_values:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_values()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(10)) goto parse_values;
+ if (input->ExpectTag(10)) goto parse_loop_values;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1355,9 +1362,9 @@ int ListValue::ByteSize() const {
void ListValue::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const ListValue* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const ListValue*>(
- &from);
+ const ListValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const ListValue>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1409,10 +1416,10 @@ void ListValue::InternalSwap(ListValue* other) {
// ListValue
// repeated .google.protobuf.Value values = 1;
- int ListValue::values_size() const {
+int ListValue::values_size() const {
return values_.size();
}
- void ListValue::clear_values() {
+void ListValue::clear_values() {
values_.Clear();
}
const ::google::protobuf::Value& ListValue::values(int index) const {
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 46482142..2889c8fe 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -735,6 +735,10 @@ ListValue::mutable_values() {
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 37123c7b..3acaeba1 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -1141,6 +1141,14 @@ class LIBPROTOBUF_EXPORT Mutex {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
};
+// Undefine the macros to workaround the conflicts with Google internal
+// MutexLock implementation.
+// TODO(liujisi): Remove the undef once internal macros are removed.
+#undef MutexLock
+#undef ReaderMutexLock
+#undef WriterMutexLock
+#undef MutexLockMaybe
+
// MutexLock(mu) acquires mu when constructed and releases it when destroyed.
class LIBPROTOBUF_EXPORT MutexLock {
public:
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 7955d261..7ecc17ee 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -1285,24 +1285,6 @@ char* FloatToBuffer(float value, char* buffer) {
return buffer;
}
-string ToHex(uint64 num) {
- if (num == 0) {
- return string("0");
- }
-
- // Compute hex bytes in reverse order, writing to the back of the
- // buffer.
- char buf[16]; // No more than 16 hex digits needed.
- char* bufptr = buf + 16;
- static const char kHexChars[] = "0123456789abcdef";
- while (num != 0) {
- *--bufptr = kHexChars[num & 0xf];
- num >>= 4;
- }
-
- return string(bufptr, buf + 16 - bufptr);
-}
-
namespace strings {
AlphaNum::AlphaNum(strings::Hex hex) {
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 920701eb..5faa81e0 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -683,12 +683,6 @@ string Join(const Range& components,
}
// ----------------------------------------------------------------------
-// ToHex()
-// Return a lower-case hex string representation of the given integer.
-// ----------------------------------------------------------------------
-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.
diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3
index 934f36fa..bd646a0d 100644
--- a/src/google/protobuf/testdata/golden_message_proto3
+++ b/src/google/protobuf/testdata/golden_message_proto3
Binary files differ
diff --git a/src/google/protobuf/testdata/map_test_data.txt b/src/google/protobuf/testdata/map_test_data.txt
new file mode 100644
index 00000000..bc272321
--- /dev/null
+++ b/src/google/protobuf/testdata/map_test_data.txt
@@ -0,0 +1,140 @@
+map_int32_int32 {
+ key: 0
+ value: 0
+}
+map_int32_int32 {
+ key: 1
+ value: 1
+}
+map_int64_int64 {
+ key: 0
+ value: 0
+}
+map_int64_int64 {
+ key: 1
+ value: 1
+}
+map_uint32_uint32 {
+ key: 0
+ value: 0
+}
+map_uint32_uint32 {
+ key: 1
+ value: 1
+}
+map_uint64_uint64 {
+ key: 0
+ value: 0
+}
+map_uint64_uint64 {
+ key: 1
+ value: 1
+}
+map_sint32_sint32 {
+ key: 0
+ value: 0
+}
+map_sint32_sint32 {
+ key: 1
+ value: 1
+}
+map_sint64_sint64 {
+ key: 0
+ value: 0
+}
+map_sint64_sint64 {
+ key: 1
+ value: 1
+}
+map_fixed32_fixed32 {
+ key: 0
+ value: 0
+}
+map_fixed32_fixed32 {
+ key: 1
+ value: 1
+}
+map_fixed64_fixed64 {
+ key: 0
+ value: 0
+}
+map_fixed64_fixed64 {
+ key: 1
+ value: 1
+}
+map_sfixed32_sfixed32 {
+ key: 0
+ value: 0
+}
+map_sfixed32_sfixed32 {
+ key: 1
+ value: 1
+}
+map_sfixed64_sfixed64 {
+ key: 0
+ value: 0
+}
+map_sfixed64_sfixed64 {
+ key: 1
+ value: 1
+}
+map_int32_float {
+ key: 0
+ value: 0
+}
+map_int32_float {
+ key: 1
+ value: 1
+}
+map_int32_double {
+ key: 0
+ value: 0
+}
+map_int32_double {
+ key: 1
+ value: 1
+}
+map_bool_bool {
+ key: false
+ value: false
+}
+map_bool_bool {
+ key: true
+ value: true
+}
+map_string_string {
+ key: "0"
+ value: "0"
+}
+map_string_string {
+ key: "1"
+ value: "1"
+}
+map_int32_bytes {
+ key: 0
+ value: "0"
+}
+map_int32_bytes {
+ key: 1
+ value: "1"
+}
+map_int32_enum {
+ key: 0
+ value: MAP_ENUM_BAR
+}
+map_int32_enum {
+ key: 1
+ value: MAP_ENUM_BAZ
+}
+map_int32_foreign_message {
+ key: 0
+ value {
+ c: 0
+ }
+}
+map_int32_foreign_message {
+ key: 1
+ value {
+ c: 1
+ }
+}
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index ec070c51..61dfa5d6 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -43,6 +43,8 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -50,6 +52,7 @@
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/any.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
@@ -70,6 +73,18 @@ inline bool IsOctNumber(const string& str) {
(str[1] >= '0' && str[1] < '8'));
}
+inline bool GetAnyFieldDescriptors(const Message& message,
+ const FieldDescriptor** type_url_field,
+ const FieldDescriptor** value_field) {
+ const Descriptor* descriptor = message.GetDescriptor();
+ *type_url_field = descriptor->FindFieldByNumber(1);
+ *value_field = descriptor->FindFieldByNumber(2);
+ return (*type_url_field != NULL &&
+ (*type_url_field)->type() == FieldDescriptor::TYPE_STRING &&
+ *value_field != NULL &&
+ (*value_field)->type() == FieldDescriptor::TYPE_BYTES);
+}
+
} // namespace
string Message::DebugString() const {
@@ -330,7 +345,17 @@ class TextFormat::Parser::ParserImpl {
// Confirm that we have a valid ending delimiter.
DO(Consume(delimiter));
+ return true;
+ }
+ // Consume either "<" or "{".
+ bool ConsumeMessageDelimiter(string* delimiter) {
+ if (TryConsume("<")) {
+ *delimiter = ">";
+ } else {
+ DO(Consume("{"));
+ *delimiter = "}";
+ }
return true;
}
@@ -347,15 +372,28 @@ class TextFormat::Parser::ParserImpl {
int start_line = tokenizer_.current().line;
int start_column = tokenizer_.current().column;
+ const FieldDescriptor* any_type_url_field;
+ const FieldDescriptor* any_value_field;
+ if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field,
+ &any_value_field) &&
+ TryConsume("[")) {
+ string full_type_name;
+ DO(ConsumeAnyTypeUrl(&full_type_name));
+ DO(Consume("]"));
+ string serialized_value;
+ DO(ConsumeAnyValue(full_type_name,
+ message->GetDescriptor()->file()->pool(),
+ &serialized_value));
+ reflection->SetString(
+ message, any_type_url_field,
+ string(internal::kTypeGoogleApisComPrefix) + full_type_name);
+ reflection->SetString(message, any_value_field, serialized_value);
+ return true;
+ // Fall through.
+ }
if (TryConsume("[")) {
// Extension.
- DO(ConsumeIdentifier(&field_name));
- while (TryConsume(".")) {
- string part;
- DO(ConsumeIdentifier(&part));
- field_name += ".";
- field_name += part;
- }
+ DO(ConsumeFullTypeName(&field_name));
DO(Consume("]"));
field = (finder_ != NULL
@@ -512,13 +550,7 @@ class TextFormat::Parser::ParserImpl {
string field_name;
if (TryConsume("[")) {
// Extension name.
- DO(ConsumeIdentifier(&field_name));
- while (TryConsume(".")) {
- string part;
- DO(ConsumeIdentifier(&part));
- field_name += ".";
- field_name += part;
- }
+ DO(ConsumeFullTypeName(&field_name));
DO(Consume("]"));
} else {
DO(ConsumeIdentifier(&field_name));
@@ -553,13 +585,7 @@ class TextFormat::Parser::ParserImpl {
}
string delimiter;
- if (TryConsume("<")) {
- delimiter = ">";
- } else {
- DO(Consume("{"));
- delimiter = "}";
- }
-
+ DO(ConsumeMessageDelimiter(&delimiter));
if (field->is_repeated()) {
DO(ConsumeMessage(reflection->AddMessage(message, field), delimiter));
} else {
@@ -576,12 +602,7 @@ class TextFormat::Parser::ParserImpl {
// the ending delimiter.
bool SkipFieldMessage() {
string delimiter;
- if (TryConsume("<")) {
- delimiter = ">";
- } else {
- DO(Consume("{"));
- delimiter = "}";
- }
+ DO(ConsumeMessageDelimiter(&delimiter));
while (!LookingAt(">") && !LookingAt("}")) {
DO(SkipField());
}
@@ -808,6 +829,18 @@ class TextFormat::Parser::ParserImpl {
return false;
}
+ // Consume a string of form "<id1>.<id2>....<idN>".
+ bool ConsumeFullTypeName(string* name) {
+ DO(ConsumeIdentifier(name));
+ while (TryConsume(".")) {
+ string part;
+ DO(ConsumeIdentifier(&part));
+ *name += ".";
+ *name += part;
+ }
+ return true;
+ }
+
// Consumes a string and saves its value in the text parameter.
// Returns false if the token is not of type STRING.
bool ConsumeString(string* text) {
@@ -947,6 +980,54 @@ class TextFormat::Parser::ParserImpl {
return true;
}
+ // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name"
+ bool ConsumeAnyTypeUrl(string* full_type_name) {
+ // TODO(saito) Extend Consume() to consume multiple tokens at once, so that
+ // this code can be written as just DO(Consume(kGoogleApisTypePrefix)).
+ string url1, url2, url3;
+ DO(ConsumeIdentifier(&url1)); // type
+ DO(Consume("."));
+ DO(ConsumeIdentifier(&url2)); // googleapis
+ DO(Consume("."));
+ DO(ConsumeIdentifier(&url3)); // com
+ DO(Consume("/"));
+ DO(ConsumeFullTypeName(full_type_name));
+
+ const string prefix = url1 + "." + url2 + "." + url3 + "/";
+ if (prefix != internal::kTypeGoogleApisComPrefix) {
+ ReportError("TextFormat::Parser for Any supports only "
+ "type.googleapi.com, but found \"" + prefix + "\"");
+ return false;
+ }
+ return true;
+ }
+
+ // A helper function for reconstructing Any::value. Consumes a text of
+ // full_type_name, then serializes it into serialized_value. "pool" is used to
+ // look up and create a temporary object with full_type_name.
+ bool ConsumeAnyValue(const string& full_type_name, const DescriptorPool* pool,
+ string* serialized_value) {
+ const Descriptor* value_descriptor =
+ pool->FindMessageTypeByName(full_type_name);
+ if (value_descriptor == NULL) {
+ ReportError("Could not find type \"" + full_type_name +
+ "\" stored in google.protobuf.Any.");
+ return false;
+ }
+ DynamicMessageFactory factory;
+ const Message* value_prototype = factory.GetPrototype(value_descriptor);
+ if (value_prototype == NULL) {
+ return false;
+ }
+ google::protobuf::scoped_ptr<Message> value(value_prototype->New());
+ string sub_delimiter;
+ DO(ConsumeMessageDelimiter(&sub_delimiter));
+ DO(ConsumeMessage(value.get(), sub_delimiter));
+
+ value->AppendToString(serialized_value);
+ return true;
+ }
+
// Consumes a token and confirms that it matches that specified in the
// value parameter. Returns false if the token found does not match that
// which was specified.
@@ -1338,7 +1419,8 @@ TextFormat::Printer::Printer()
use_field_number_(false),
use_short_repeated_primitives_(false),
hide_unknown_fields_(false),
- print_message_fields_in_index_order_(false) {
+ print_message_fields_in_index_order_(false),
+ expand_any_(false) {
SetUseUtf8StringEscaping(false);
}
@@ -1413,11 +1495,63 @@ struct FieldIndexSorter {
return left->index() < right->index();
}
};
+
} // namespace
+bool TextFormat::Printer::PrintAny(const Message& message,
+ TextGenerator& generator) const {
+ const FieldDescriptor* type_url_field;
+ const FieldDescriptor* value_field;
+ if (!internal::GetAnyFieldDescriptors(message, &type_url_field,
+ &value_field)) {
+ return false;
+ }
+
+ const Reflection* reflection = message.GetReflection();
+
+ // Extract the full type name from the type_url field.
+ const string& type_url = reflection->GetString(message, type_url_field);
+ string full_type_name;
+ if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) {
+ return false;
+ }
+
+ // Print the "value" in text.
+ const google::protobuf::Descriptor* value_descriptor =
+ message.GetDescriptor()->file()->pool()->FindMessageTypeByName(
+ full_type_name);
+ if (value_descriptor == NULL) {
+ GOOGLE_LOG(WARNING) << "Proto type " << type_url << " not found";
+ return false;
+ }
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<google::protobuf::Message> value_message(
+ factory.GetPrototype(value_descriptor)->New());
+ string serialized_value = reflection->GetString(message, value_field);
+ if (!value_message->ParseFromString(serialized_value)) {
+ GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents";
+ return false;
+ }
+ generator.Print(StrCat("[", type_url, "]"));
+ const FieldValuePrinter* printer = FindWithDefault(
+ custom_printers_, value_field, default_field_value_printer_.get());
+ generator.Print(
+ printer->PrintMessageStart(message, -1, 0, single_line_mode_));
+ generator.Indent();
+ Print(*value_message, generator);
+ generator.Outdent();
+ generator.Print(printer->PrintMessageEnd(message, -1, 0, single_line_mode_));
+ return true;
+}
+
void TextFormat::Printer::Print(const Message& message,
TextGenerator& generator) const {
+ const Descriptor* descriptor = message.GetDescriptor();
const Reflection* reflection = message.GetReflection();
+ if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ &&
+ PrintAny(message, generator)) {
+ return;
+ }
vector<const FieldDescriptor*> fields;
reflection->ListFields(message, &fields);
if (print_message_fields_in_index_order_) {
@@ -1446,6 +1580,54 @@ void TextFormat::Printer::PrintFieldValueToString(
PrintFieldValue(message, message.GetReflection(), field, index, generator);
}
+class MapEntryMessageComparator {
+ public:
+ explicit MapEntryMessageComparator(const Descriptor* descriptor)
+ : field_(descriptor->field(0)) {}
+
+ bool operator()(const Message* a, const Message* b) {
+ const Reflection* reflection = a->GetReflection();
+ switch (field_->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_BOOL: {
+ bool first = reflection->GetBool(*a, field_);
+ bool second = reflection->GetBool(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_INT32: {
+ int32 first = reflection->GetInt32(*a, field_);
+ int32 second = reflection->GetInt32(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_INT64: {
+ int64 first = reflection->GetInt64(*a, field_);
+ int64 second = reflection->GetInt64(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_UINT32: {
+ uint32 first = reflection->GetUInt32(*a, field_);
+ uint32 second = reflection->GetUInt32(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_UINT64: {
+ uint64 first = reflection->GetUInt64(*a, field_);
+ uint64 second = reflection->GetUInt64(*b, field_);
+ return first < second;
+ }
+ case FieldDescriptor::CPPTYPE_STRING: {
+ string first = reflection->GetString(*a, field_);
+ string second = reflection->GetString(*b, field_);
+ return first < second;
+ }
+ default:
+ GOOGLE_LOG(DFATAL) << "Invalid key for map field.";
+ return true;
+ }
+ }
+
+ private:
+ const FieldDescriptor* field_;
+};
+
void TextFormat::Printer::PrintField(const Message& message,
const Reflection* reflection,
const FieldDescriptor* field,
@@ -1466,6 +1648,21 @@ void TextFormat::Printer::PrintField(const Message& message,
count = 1;
}
+ std::vector<const Message*> sorted_map_field;
+ if (field->is_map()) {
+ const RepeatedPtrField<Message>& map_field =
+ reflection->GetRepeatedPtrField<Message>(message, field);
+ for (RepeatedPtrField<Message>::const_pointer_iterator it =
+ map_field.pointer_begin();
+ it != map_field.pointer_end(); ++it) {
+ sorted_map_field.push_back(*it);
+ }
+
+ MapEntryMessageComparator comparator(field->message_type());
+ std::stable_sort(sorted_map_field.begin(), sorted_map_field.end(),
+ comparator);
+ }
+
for (int j = 0; j < count; ++j) {
const int field_index = field->is_repeated() ? j : -1;
@@ -1475,8 +1672,10 @@ void TextFormat::Printer::PrintField(const Message& message,
const FieldValuePrinter* printer = FindWithDefault(
custom_printers_, field, default_field_value_printer_.get());
const Message& sub_message =
- field->is_repeated()
- ? reflection->GetRepeatedMessage(message, field, j)
+ field->is_repeated()
+ ? (field->is_map()
+ ? *sorted_map_field[j]
+ : reflection->GetRepeatedMessage(message, field, j))
: reflection->GetMessage(message, field);
generator.Print(
printer->PrintMessageStart(
@@ -1680,8 +1879,8 @@ void TextFormat::Printer::PrintUnknownFields(
case UnknownField::TYPE_FIXED32: {
generator.Print(field_number);
generator.Print(": 0x");
- char buffer[kFastToBufferSize];
- generator.Print(FastHex32ToBuffer(field.fixed32(), buffer));
+ generator.Print(
+ StrCat(strings::Hex(field.fixed32(), strings::Hex::ZERO_PAD_8)));
if (single_line_mode_) {
generator.Print(" ");
} else {
@@ -1692,8 +1891,8 @@ void TextFormat::Printer::PrintUnknownFields(
case UnknownField::TYPE_FIXED64: {
generator.Print(field_number);
generator.Print(": 0x");
- char buffer[kFastToBufferSize];
- generator.Print(FastHex64ToBuffer(field.fixed64(), buffer));
+ generator.Print(
+ StrCat(strings::Hex(field.fixed64(), strings::Hex::ZERO_PAD_16)));
if (single_line_mode_) {
generator.Print(" ");
} else {
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 9e2cb070..6717aecd 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -208,6 +208,17 @@ class LIBPROTOBUF_EXPORT TextFormat {
print_message_fields_in_index_order;
}
+ // If expand==true, expand google.protobuf.Any payloads. The output
+ // will be of form
+ // [type_url] { <value_printed_in_text> }
+ //
+ // If expand==false, print Any using the default printer. The output will
+ // look like
+ // type_url: "<type_url>" value: "serialized_content"
+ void SetExpandAny(bool expand) {
+ expand_any_ = expand;
+ }
+
// Register a custom field-specific FieldValuePrinter for fields
// with a particular FieldDescriptor.
// Returns "true" if the registration succeeded, or "false", if there is
@@ -259,6 +270,8 @@ class LIBPROTOBUF_EXPORT TextFormat {
void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
TextGenerator& generator) const;
+ bool PrintAny(const Message& message, TextGenerator& generator) const;
+
int initial_indent_level_;
bool single_line_mode_;
@@ -271,6 +284,8 @@ class LIBPROTOBUF_EXPORT TextFormat {
bool print_message_fields_in_index_order_;
+ bool expand_any_;
+
google::protobuf::scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
typedef map<const FieldDescriptor*,
const FieldValuePrinter*> CustomPrinterMap;
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 477fdcbd..1b18c5ed 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -32,23 +32,24 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <google/protobuf/text_format.h>
+
#include <math.h>
#include <stdlib.h>
#include <limits>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_mset.pb.h>
-#include <google/protobuf/test_util.h>
-
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_mset.pb.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
namespace google {
namespace protobuf {
@@ -451,7 +452,7 @@ TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) {
class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter {
public:
virtual string PrintInt32(int32 v) const {
- return StrCat(FieldValuePrinter::PrintInt32(v), " # x", ToHex(v));
+ return StrCat(FieldValuePrinter::PrintInt32(v), " # x", strings::Hex(v));
}
virtual string PrintMessageStart(const Message& message,
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 6edfe056..877dc8f3 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -117,7 +117,7 @@ const int Timestamp::kNanosFieldNumber;
#endif // !_MSC_VER
Timestamp::Timestamp()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Timestamp)
}
@@ -310,9 +310,9 @@ int Timestamp::ByteSize() const {
void Timestamp::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Timestamp* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Timestamp*>(
- &from);
+ const Timestamp* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -370,7 +370,7 @@ void Timestamp::InternalSwap(Timestamp* other) {
// Timestamp
// optional int64 seconds = 1;
- void Timestamp::clear_seconds() {
+void Timestamp::clear_seconds() {
seconds_ = GOOGLE_LONGLONG(0);
}
::google::protobuf::int64 Timestamp::seconds() const {
@@ -384,7 +384,7 @@ void Timestamp::InternalSwap(Timestamp* other) {
}
// optional int32 nanos = 2;
- void Timestamp::clear_nanos() {
+void Timestamp::clear_nanos() {
nanos_ = 0;
}
::google::protobuf::int32 Timestamp::nanos() const {
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index d77bc6ce..8b08909e 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -267,7 +267,7 @@ const int Type::kSourceContextFieldNumber;
#endif // !_MSC_VER
Type::Type()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Type)
}
@@ -332,7 +332,7 @@ Type* Type::New(::google::protobuf::Arena* arena) const {
void Type::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- if (source_context_ != NULL) delete source_context_;
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
fields_.Clear();
oneofs_.Clear();
@@ -369,12 +369,15 @@ bool Type::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_fields:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_fields:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_fields()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_fields;
+ if (input->ExpectTag(18)) goto parse_loop_fields;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(26)) goto parse_oneofs;
break;
}
@@ -402,12 +405,15 @@ bool Type::MergePartialFromCodedStream(
case 4: {
if (tag == 34) {
parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_options()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(34)) goto parse_options;
+ if (input->ExpectTag(34)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(42)) goto parse_source_context;
break;
}
@@ -587,9 +593,9 @@ int Type::ByteSize() const {
void Type::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Type* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Type*>(
- &from);
+ const Type* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Type>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -654,7 +660,7 @@ void Type::InternalSwap(Type* other) {
// Type
// optional string name = 1;
- void Type::clear_name() {
+void Type::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Type::name() const {
@@ -697,10 +703,10 @@ void Type::InternalSwap(Type* other) {
}
// repeated .google.protobuf.Field fields = 2;
- int Type::fields_size() const {
+int Type::fields_size() const {
return fields_.size();
}
- void Type::clear_fields() {
+void Type::clear_fields() {
fields_.Clear();
}
const ::google::protobuf::Field& Type::fields(int index) const {
@@ -727,10 +733,10 @@ Type::mutable_fields() {
}
// repeated string oneofs = 3;
- int Type::oneofs_size() const {
+int Type::oneofs_size() const {
return oneofs_.size();
}
- void Type::clear_oneofs() {
+void Type::clear_oneofs() {
oneofs_.Clear();
}
const ::std::string& Type::oneofs(int index) const {
@@ -781,10 +787,10 @@ Type::mutable_oneofs() {
}
// repeated .google.protobuf.Option options = 4;
- int Type::options_size() const {
+int Type::options_size() const {
return options_.size();
}
- void Type::clear_options() {
+void Type::clear_options() {
options_.Clear();
}
const ::google::protobuf::Option& Type::options(int index) const {
@@ -811,11 +817,11 @@ Type::mutable_options() {
}
// optional .google.protobuf.SourceContext source_context = 5;
- bool Type::has_source_context() const {
+bool Type::has_source_context() const {
return !_is_default_instance_ && source_context_ != NULL;
}
- void Type::clear_source_context() {
- if (source_context_ != NULL) delete source_context_;
+void Type::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
const ::google::protobuf::SourceContext& Type::source_context() const {
@@ -941,7 +947,7 @@ const int Field::kOptionsFieldNumber;
#endif // !_MSC_VER
Field::Field()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Field)
}
@@ -1153,12 +1159,15 @@ bool Field::MergePartialFromCodedStream(
case 9: {
if (tag == 74) {
parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_options()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(74)) goto parse_options;
+ if (input->ExpectTag(74)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -1370,9 +1379,9 @@ int Field::ByteSize() const {
void Field::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Field* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Field*>(
- &from);
+ const Field* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Field>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1454,7 +1463,7 @@ void Field::InternalSwap(Field* other) {
// Field
// optional .google.protobuf.Field.Kind kind = 1;
- void Field::clear_kind() {
+void Field::clear_kind() {
kind_ = 0;
}
::google::protobuf::Field_Kind Field::kind() const {
@@ -1468,7 +1477,7 @@ void Field::InternalSwap(Field* other) {
}
// optional .google.protobuf.Field.Cardinality cardinality = 2;
- void Field::clear_cardinality() {
+void Field::clear_cardinality() {
cardinality_ = 0;
}
::google::protobuf::Field_Cardinality Field::cardinality() const {
@@ -1482,7 +1491,7 @@ void Field::InternalSwap(Field* other) {
}
// optional int32 number = 3;
- void Field::clear_number() {
+void Field::clear_number() {
number_ = 0;
}
::google::protobuf::int32 Field::number() const {
@@ -1496,7 +1505,7 @@ void Field::InternalSwap(Field* other) {
}
// optional string name = 4;
- void Field::clear_name() {
+void Field::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Field::name() const {
@@ -1539,7 +1548,7 @@ void Field::InternalSwap(Field* other) {
}
// optional string type_url = 6;
- void Field::clear_type_url() {
+void Field::clear_type_url() {
type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Field::type_url() const {
@@ -1582,7 +1591,7 @@ void Field::InternalSwap(Field* other) {
}
// optional int32 oneof_index = 7;
- void Field::clear_oneof_index() {
+void Field::clear_oneof_index() {
oneof_index_ = 0;
}
::google::protobuf::int32 Field::oneof_index() const {
@@ -1596,7 +1605,7 @@ void Field::InternalSwap(Field* other) {
}
// optional bool packed = 8;
- void Field::clear_packed() {
+void Field::clear_packed() {
packed_ = false;
}
bool Field::packed() const {
@@ -1610,10 +1619,10 @@ void Field::InternalSwap(Field* other) {
}
// repeated .google.protobuf.Option options = 9;
- int Field::options_size() const {
+int Field::options_size() const {
return options_.size();
}
- void Field::clear_options() {
+void Field::clear_options() {
options_.Clear();
}
const ::google::protobuf::Option& Field::options(int index) const {
@@ -1651,7 +1660,7 @@ const int Enum::kSourceContextFieldNumber;
#endif // !_MSC_VER
Enum::Enum()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Enum)
}
@@ -1716,7 +1725,7 @@ Enum* Enum::New(::google::protobuf::Arena* arena) const {
void Enum::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- if (source_context_ != NULL) delete source_context_;
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
enumvalue_.Clear();
options_.Clear();
@@ -1752,26 +1761,31 @@ bool Enum::MergePartialFromCodedStream(
case 2: {
if (tag == 18) {
parse_enumvalue:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_enumvalue:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_enumvalue()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(18)) goto parse_enumvalue;
- if (input->ExpectTag(26)) goto parse_options;
+ if (input->ExpectTag(18)) goto parse_loop_enumvalue;
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
break;
}
// repeated .google.protobuf.Option options = 3;
case 3: {
if (tag == 26) {
- parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_options()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(26)) goto parse_options;
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectTag(34)) goto parse_source_context;
break;
}
@@ -1924,9 +1938,9 @@ int Enum::ByteSize() const {
void Enum::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Enum* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Enum*>(
- &from);
+ const Enum* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Enum>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1989,7 +2003,7 @@ void Enum::InternalSwap(Enum* other) {
// Enum
// optional string name = 1;
- void Enum::clear_name() {
+void Enum::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Enum::name() const {
@@ -2032,10 +2046,10 @@ void Enum::InternalSwap(Enum* other) {
}
// repeated .google.protobuf.EnumValue enumvalue = 2;
- int Enum::enumvalue_size() const {
+int Enum::enumvalue_size() const {
return enumvalue_.size();
}
- void Enum::clear_enumvalue() {
+void Enum::clear_enumvalue() {
enumvalue_.Clear();
}
const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const {
@@ -2062,10 +2076,10 @@ Enum::mutable_enumvalue() {
}
// repeated .google.protobuf.Option options = 3;
- int Enum::options_size() const {
+int Enum::options_size() const {
return options_.size();
}
- void Enum::clear_options() {
+void Enum::clear_options() {
options_.Clear();
}
const ::google::protobuf::Option& Enum::options(int index) const {
@@ -2092,11 +2106,11 @@ Enum::mutable_options() {
}
// optional .google.protobuf.SourceContext source_context = 4;
- bool Enum::has_source_context() const {
+bool Enum::has_source_context() const {
return !_is_default_instance_ && source_context_ != NULL;
}
- void Enum::clear_source_context() {
- if (source_context_ != NULL) delete source_context_;
+void Enum::clear_source_context() {
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
const ::google::protobuf::SourceContext& Enum::source_context() const {
@@ -2139,7 +2153,7 @@ const int EnumValue::kOptionsFieldNumber;
#endif // !_MSC_VER
EnumValue::EnumValue()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.EnumValue)
}
@@ -2251,12 +2265,15 @@ bool EnumValue::MergePartialFromCodedStream(
case 3: {
if (tag == 26) {
parse_options:
- DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+ DO_(input->IncrementRecursionDepth());
+ parse_loop_options:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
input, add_options()));
} else {
goto handle_unusual;
}
- if (input->ExpectTag(26)) goto parse_options;
+ if (input->ExpectTag(26)) goto parse_loop_options;
+ input->UnsafeDecrementRecursionDepth();
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -2372,9 +2389,9 @@ int EnumValue::ByteSize() const {
void EnumValue::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const EnumValue* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const EnumValue*>(
- &from);
+ const EnumValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -2435,7 +2452,7 @@ void EnumValue::InternalSwap(EnumValue* other) {
// EnumValue
// optional string name = 1;
- void EnumValue::clear_name() {
+void EnumValue::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& EnumValue::name() const {
@@ -2478,7 +2495,7 @@ void EnumValue::InternalSwap(EnumValue* other) {
}
// optional int32 number = 2;
- void EnumValue::clear_number() {
+void EnumValue::clear_number() {
number_ = 0;
}
::google::protobuf::int32 EnumValue::number() const {
@@ -2492,10 +2509,10 @@ void EnumValue::InternalSwap(EnumValue* other) {
}
// repeated .google.protobuf.Option options = 3;
- int EnumValue::options_size() const {
+int EnumValue::options_size() const {
return options_.size();
}
- void EnumValue::clear_options() {
+void EnumValue::clear_options() {
options_.Clear();
}
const ::google::protobuf::Option& EnumValue::options(int index) const {
@@ -2531,7 +2548,7 @@ const int Option::kValueFieldNumber;
#endif // !_MSC_VER
Option::Option()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Option)
}
@@ -2596,7 +2613,7 @@ Option* Option::New(::google::protobuf::Arena* arena) const {
void Option::Clear() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- if (value_ != NULL) delete value_;
+ if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
value_ = NULL;
}
@@ -2732,9 +2749,9 @@ int Option::ByteSize() const {
void Option::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Option* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Option*>(
- &from);
+ const Option* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Option>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -2793,7 +2810,7 @@ void Option::InternalSwap(Option* other) {
// Option
// optional string name = 1;
- void Option::clear_name() {
+void Option::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& Option::name() const {
@@ -2836,11 +2853,11 @@ void Option::InternalSwap(Option* other) {
}
// optional .google.protobuf.Any value = 2;
- bool Option::has_value() const {
+bool Option::has_value() const {
return !_is_default_instance_ && value_ != NULL;
}
- void Option::clear_value() {
- if (value_ != NULL) delete value_;
+void Option::clear_value() {
+ if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
value_ = NULL;
}
const ::google::protobuf::Any& Option::value() const {
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index a14edd4a..c9952efa 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -936,7 +936,7 @@ inline bool Type::has_source_context() const {
return !_is_default_instance_ && source_context_ != NULL;
}
inline void Type::clear_source_context() {
- if (source_context_ != NULL) delete source_context_;
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
inline const ::google::protobuf::SourceContext& Type::source_context() const {
@@ -1270,7 +1270,7 @@ inline bool Enum::has_source_context() const {
return !_is_default_instance_ && source_context_ != NULL;
}
inline void Enum::clear_source_context() {
- if (source_context_ != NULL) delete source_context_;
+ if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_;
source_context_ = NULL;
}
inline const ::google::protobuf::SourceContext& Enum::source_context() const {
@@ -1445,7 +1445,7 @@ inline bool Option::has_value() const {
return !_is_default_instance_ && value_ != NULL;
}
inline void Option::clear_value() {
- if (value_ != NULL) delete value_;
+ if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_;
value_ = NULL;
}
inline const ::google::protobuf::Any& Option::value() const {
@@ -1478,6 +1478,14 @@ inline void Option::set_allocated_value(::google::protobuf::Any* value) {
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index a32291e0..834c9b56 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -185,6 +185,7 @@ message TestAllTypes {
message NestedTestAllTypes {
optional NestedTestAllTypes child = 1;
optional TestAllTypes payload = 2;
+ repeated NestedTestAllTypes repeated_child = 3;
}
message TestDeprecatedFields {
@@ -203,6 +204,11 @@ enum ForeignEnum {
FOREIGN_BAZ = 6;
}
+message TestReservedFields {
+ reserved 2, 15, 9 to 11;
+ reserved "bar", "baz";
+}
+
message TestAllExtensions {
extensions 1 to max;
}
diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto
index 1b35fad0..faaddc6e 100644
--- a/src/google/protobuf/unittest_drop_unknown_fields.proto
+++ b/src/google/protobuf/unittest_drop_unknown_fields.proto
@@ -41,8 +41,8 @@ message Foo {
BAR = 1;
BAZ = 2;
}
- optional int32 int32_value = 1;
- optional NestedEnum enum_value = 2;
+ int32 int32_value = 1;
+ NestedEnum enum_value = 2;
}
message FooWithExtraFields {
@@ -52,7 +52,7 @@ message FooWithExtraFields {
BAZ = 2;
QUX = 3;
}
- optional int32 int32_value = 1;
- optional NestedEnum enum_value = 2;
- optional int32 extra_int32_value = 3;
+ int32 int32_value = 1;
+ NestedEnum enum_value = 2;
+ int32 extra_int32_value = 3;
}
diff --git a/src/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto
index f261b58e..f5cc4cc3 100644
--- a/src/google/protobuf/unittest_no_field_presence.proto
+++ b/src/google/protobuf/unittest_no_field_presence.proto
@@ -43,7 +43,7 @@ option csharp_namespace = "Google.ProtocolBuffers.TestProtos.Proto3";
// forms.
message TestAllTypes {
message NestedMessage {
- optional int32 bb = 1;
+ int32 bb = 1;
}
enum NestedEnum {
@@ -55,36 +55,36 @@ message TestAllTypes {
// 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;
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+
+ NestedMessage optional_nested_message = 18;
+ ForeignMessage optional_foreign_message = 19;
+ protobuf_unittest.TestAllTypes optional_proto2_message = 20;
+
+ NestedEnum optional_nested_enum = 21;
+ 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];
+ string optional_string_piece = 24 [ctype=STRING_PIECE];
+ string optional_cord = 25 [ctype=CORD];
- optional NestedMessage optional_lazy_message = 30 [lazy=true];
+ NestedMessage optional_lazy_message = 30 [lazy=true];
// Repeated
repeated int32 repeated_int32 = 31;
@@ -124,13 +124,13 @@ message TestAllTypes {
}
message TestProto2Required {
- optional protobuf_unittest.TestRequired proto2 = 1;
+ protobuf_unittest.TestRequired proto2 = 1;
}
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
- optional int32 c = 1;
+ int32 c = 1;
}
enum ForeignEnum {
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
index 24e6828f..abc3de28 100644
--- a/src/google/protobuf/unittest_preserve_unknown_enum.proto
+++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -49,7 +49,7 @@ enum MyEnumPlusExtra {
}
message MyMessage {
- optional MyEnum e = 1;
+ MyEnum e = 1;
repeated MyEnum repeated_e = 2;
repeated MyEnum repeated_packed_e = 3 [packed=true];
repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4; // not packed
@@ -60,7 +60,7 @@ message MyMessage {
}
message MyMessagePlusExtra {
- optional MyEnumPlusExtra e = 1;
+ MyEnumPlusExtra e = 1;
repeated MyEnumPlusExtra repeated_e = 2;
repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true];
repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true];
diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
index 6d7bada8..b835a6ba 100644
--- a/src/google/protobuf/unittest_proto3_arena.proto
+++ b/src/google/protobuf/unittest_proto3_arena.proto
@@ -43,7 +43,7 @@ message TestAllTypes {
// 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;
+ int32 bb = 1;
}
enum NestedEnum {
@@ -55,46 +55,47 @@ message TestAllTypes {
}
// 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;
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+
+ // Groups are not allowed in proto3.
+ // optional group OptionalGroup = 16 {
+ // optional int32 a = 17;
+ // }
+
+ NestedMessage optional_nested_message = 18;
+ ForeignMessage optional_foreign_message = 19;
+ protobuf_unittest_import.ImportMessage optional_import_message = 20;
+
+ NestedEnum optional_nested_enum = 21;
+ ForeignEnum optional_foreign_enum = 22;
// Omitted (compared to unittest.proto) because proto2 enums are not allowed
// inside proto2 messages.
//
// 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];
+ string optional_string_piece = 24 [ctype=STRING_PIECE];
+ string optional_cord = 25 [ctype=CORD];
// Defined in unittest_import_public.proto
- optional protobuf_unittest_import.PublicImportMessage
+ protobuf_unittest_import.PublicImportMessage
optional_public_import_message = 26;
- optional NestedMessage optional_lazy_message = 27 [lazy=true];
+ NestedMessage optional_lazy_message = 27 [lazy=true];
// Repeated
repeated int32 repeated_int32 = 31;
@@ -113,9 +114,10 @@ message TestAllTypes {
repeated string repeated_string = 44;
repeated bytes repeated_bytes = 45;
- repeated group RepeatedGroup = 46 {
- optional int32 a = 47;
- }
+ // Groups are not allowed in proto3.
+ // repeated group RepeatedGroup = 46 {
+ // optional int32 a = 47;
+ // }
repeated NestedMessage repeated_nested_message = 48;
repeated ForeignMessage repeated_foreign_message = 49;
@@ -161,6 +163,24 @@ message TestPackedTypes {
repeated ForeignEnum packed_enum = 103 [packed = true];
}
+// Explicitly set packed to false
+message TestUnpackedTypes {
+ repeated int32 repeated_int32 = 1 [packed = false];
+ repeated int64 repeated_int64 = 2 [packed = false];
+ repeated uint32 repeated_uint32 = 3 [packed = false];
+ repeated uint64 repeated_uint64 = 4 [packed = false];
+ repeated sint32 repeated_sint32 = 5 [packed = false];
+ repeated sint64 repeated_sint64 = 6 [packed = false];
+ repeated fixed32 repeated_fixed32 = 7 [packed = false];
+ repeated fixed64 repeated_fixed64 = 8 [packed = false];
+ repeated sfixed32 repeated_sfixed32 = 9 [packed = false];
+ repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+ repeated float repeated_float = 11 [packed = false];
+ repeated double repeated_double = 12 [packed = false];
+ repeated bool repeated_bool = 13 [packed = false];
+ repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
+
// This proto includes a recusively nested message.
message NestedTestAllTypes {
NestedTestAllTypes child = 1;
@@ -170,7 +190,7 @@ message NestedTestAllTypes {
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
- optional int32 c = 1;
+ int32 c = 1;
}
enum ForeignEnum {
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index e15280c8..76644900 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -93,7 +93,7 @@ void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) {
fields_ = new vector<UnknownField>();
for (int i = 0; i < other_field_count; i++) {
fields_->push_back((*other.fields_)[i]);
- fields_->back().DeepCopy();
+ fields_->back().DeepCopy((*other.fields_)[i]);
}
}
}
@@ -104,7 +104,7 @@ void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) {
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();
+ fields_->back().DeepCopy((*other.fields_)[i]);
}
}
}
@@ -202,7 +202,7 @@ UnknownFieldSet* UnknownFieldSet::AddGroup(int number) {
void UnknownFieldSet::AddField(const UnknownField& field) {
if (fields_ == NULL) fields_ = new vector<UnknownField>();
fields_->push_back(field);
- fields_->back().DeepCopy();
+ fields_->back().DeepCopy(field);
}
void UnknownFieldSet::DeleteSubrange(int start, int num) {
@@ -303,7 +303,7 @@ void UnknownField::Reset() {
}
}
-void UnknownField::DeepCopy() {
+void UnknownField::DeepCopy(const UnknownField& other) {
switch (type()) {
case UnknownField::TYPE_LENGTH_DELIMITED:
length_delimited_.string_value_ = new string(
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 987b1979..6781cd0f 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -216,7 +216,7 @@ class LIBPROTOBUF_EXPORT UnknownField {
void Reset();
// Make a deep copy of any pointers in this UnknownField.
- void DeepCopy();
+ void DeepCopy(const UnknownField& other);
// Set the wire type of this UnknownField. Should only be used when this
// UnknownField is being created.
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index c5bbbf2e..54cd653a 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -829,7 +829,7 @@ void WireFormat::SerializeFieldWithCachedSizes(
count = 1;
}
- const bool is_packed = field->options().packed();
+ const bool is_packed = field->is_packed();
if (is_packed && count > 0) {
WireFormatLite::WriteTag(field->number(),
WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
@@ -996,7 +996,7 @@ int WireFormat::FieldByteSize(
const int data_size = FieldDataOnlyByteSize(field, message);
int our_size = data_size;
- if (field->options().packed()) {
+ if (field->is_packed()) {
if (data_size > 0) {
// Packed fields get serialized like a string, not their native type.
// Technically this doesn't really matter; the size only changes if it's
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index 76bc75a1..ac83abdc 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -330,6 +330,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
template<typename MessageType>
static inline bool ReadMessageNoVirtual(input, MessageType* value);
+ // The same, but do not modify input's recursion depth. This is useful
+ // when reading a bunch of groups or messages in a loop, because then the
+ // recursion depth can be incremented before the loop and decremented after.
+ template<typename MessageType>
+ static inline bool ReadGroupNoVirtualNoRecursionDepth(field_number, input,
+ MessageType* value);
+
+ template<typename MessageType>
+ static inline bool ReadMessageNoVirtualNoRecursionDepth(input,
+ MessageType* value);
+
// Write a tag. The Write*() functions typically include the tag, so
// normally there's no need to call this unless using the Write*NoTag()
// variants.
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index 129fc63f..d073ff92 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -470,7 +470,7 @@ inline bool WireFormatLite::ReadGroupNoVirtual(
if (!value->
MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
return false;
- input->DecrementRecursionDepth();
+ input->UnsafeDecrementRecursionDepth();
// Make sure the last thing read was an end tag for this group.
if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) {
return false;
@@ -478,6 +478,14 @@ inline bool WireFormatLite::ReadGroupNoVirtual(
return true;
}
template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadGroupNoVirtualNoRecursionDepth(
+ int field_number, io::CodedInputStream* input,
+ MessageType_WorkAroundCppLookupDefect* value) {
+ return value->MessageType_WorkAroundCppLookupDefect::
+ MergePartialFromCodedStream(input) &&
+ input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP));
+}
+template<typename MessageType_WorkAroundCppLookupDefect>
inline bool WireFormatLite::ReadMessageNoVirtual(
io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
uint32 length;
@@ -491,6 +499,17 @@ inline bool WireFormatLite::ReadMessageNoVirtual(
// tag.
return input->DecrementRecursionDepthAndPopLimit(p.first);
}
+template<typename MessageType_WorkAroundCppLookupDefect>
+inline bool WireFormatLite::ReadMessageNoVirtualNoRecursionDepth(
+ io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) {
+ io::CodedInputStream::Limit old_limit = input->ReadLengthAndPushLimit();
+ if (!value->
+ MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input))
+ return false;
+ // Make sure that parsing stopped when the limit was hit, not at an endgroup
+ // tag.
+ return input->CheckEntireMessageConsumedAndPopLimit(old_limit);
+}
// ===================================================================
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index a3062a6a..e80c5a71 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_proto3_arena.pb.h>
#include <google/protobuf/unittest_mset.pb.h>
#include <google/protobuf/test_util.h>
@@ -794,6 +795,137 @@ TEST(WireFormatTest, CompatibleTypes) {
ASSERT_EQ(static_cast<uint32>(data), msg5.data());
}
+class Proto3PrimitiveRepeatedWireFormatTest
+ : public ::testing::TestWithParam<bool> {
+ protected:
+ template <class Proto>
+ void SetProto3PrimitiveRepeatedFields(Proto* message) {
+ message->add_repeated_int32(1);
+ message->add_repeated_int64(1);
+ message->add_repeated_uint32(1);
+ message->add_repeated_uint64(1);
+ message->add_repeated_sint32(1);
+ message->add_repeated_sint64(1);
+ message->add_repeated_fixed32(1);
+ message->add_repeated_fixed64(1);
+ message->add_repeated_sfixed32(1);
+ message->add_repeated_sfixed64(1);
+ message->add_repeated_float(1.0);
+ message->add_repeated_double(1.0);
+ message->add_repeated_bool(true);
+ message->add_repeated_nested_enum(
+ proto3_arena_unittest::TestAllTypes_NestedEnum_FOO);
+ }
+
+ template <class Proto>
+ void ExpectProto3PrimitiveRepeatedFieldsSet(const Proto& message) {
+ EXPECT_EQ(1, message.repeated_int32(0));
+ EXPECT_EQ(1, message.repeated_int64(0));
+ EXPECT_EQ(1, message.repeated_uint32(0));
+ EXPECT_EQ(1, message.repeated_uint64(0));
+ EXPECT_EQ(1, message.repeated_sint32(0));
+ EXPECT_EQ(1, message.repeated_sint64(0));
+ EXPECT_EQ(1, message.repeated_fixed32(0));
+ EXPECT_EQ(1, message.repeated_fixed64(0));
+ EXPECT_EQ(1, message.repeated_sfixed32(0));
+ EXPECT_EQ(1, message.repeated_sfixed64(0));
+ EXPECT_EQ(1.0, message.repeated_float(0));
+ EXPECT_EQ(1.0, message.repeated_double(0));
+ EXPECT_EQ(true, message.repeated_bool(0));
+ EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_FOO,
+ message.repeated_nested_enum(0));
+ }
+
+ template <class Proto>
+ void TestProto3PrimitiveRepeatedFields(Proto* message,
+ const string& expected) {
+ SetProto3PrimitiveRepeatedFields(message);
+
+ int size = message->ByteSize();
+
+ // Serialize using the generated code.
+ string generated_data;
+ {
+ io::StringOutputStream raw_output(&generated_data);
+ io::CodedOutputStream output(&raw_output);
+ message->SerializeWithCachedSizes(&output);
+ ASSERT_FALSE(output.HadError());
+ }
+
+ EXPECT_TRUE(expected == generated_data);
+
+ message->Clear();
+ message->ParseFromString(generated_data);
+ ExpectProto3PrimitiveRepeatedFieldsSet(*message);
+
+ // Serialize using the dynamic code.
+ string dynamic_data;
+ {
+ io::StringOutputStream raw_output(&dynamic_data);
+ io::CodedOutputStream output(&raw_output);
+ WireFormat::SerializeWithCachedSizes(*message, size, &output);
+ ASSERT_FALSE(output.HadError());
+ }
+
+ EXPECT_TRUE(expected == dynamic_data);
+
+ message->Clear();
+ io::CodedInputStream input(
+ reinterpret_cast<const uint8*>(dynamic_data.data()),
+ dynamic_data.size());
+ WireFormat::ParseAndMergePartial(&input, message);
+ ExpectProto3PrimitiveRepeatedFieldsSet(*message);
+ }
+};
+INSTANTIATE_TEST_CASE_P(SetPacked,
+ Proto3PrimitiveRepeatedWireFormatTest,
+ ::testing::Values(false, true));
+
+TEST_P(Proto3PrimitiveRepeatedWireFormatTest, Proto3PrimitiveRepeated) {
+ proto3_arena_unittest::TestAllTypes packed_message;
+ proto3_arena_unittest::TestUnpackedTypes unpacked_message;
+
+ const string packedExpected(
+ "\xFA\x01\x01\x01"
+ "\x82\x02\x01\x01"
+ "\x8A\x02\x01\x01"
+ "\x92\x02\x01\x01"
+ "\x9A\x02\x01\x02"
+ "\xA2\x02\x01\x02"
+ "\xAA\x02\x04\x01\x00\x00\x00"
+ "\xB2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\xBA\x02\x04\x01\x00\x00\x00"
+ "\xC2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\xCA\x02\x04\x00\x00\x80\x3f"
+ "\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xf0\x3f"
+ "\xDA\x02\x01\x01"
+ "\x9A\x03\x01\x01",
+ 86);
+
+ const string unpackedExpected(
+ "\x08\x01"
+ "\x10\x01"
+ "\x18\x01"
+ "\x20\x01"
+ "\x28\x02"
+ "\x30\x02"
+ "\x3D\x01\x00\x00\x00"
+ "\x41\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x4D\x01\x00\x00\x00"
+ "\x51\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x5D\x00\x00\x80\x3f"
+ "\x61\x00\x00\x00\x00\x00\x00\xf0\x3f"
+ "\x68\x01"
+ "\x70\x01",
+ 58);
+
+ if (GetParam()) {
+ TestProto3PrimitiveRepeatedFields(&packed_message, packedExpected);
+ } else {
+ TestProto3PrimitiveRepeatedFields(&unpacked_message, unpackedExpected);
+ }
+}
+
class WireFormatInvalidInputTest : public testing::Test {
protected:
// Make a serialized TestAllTypes in which the field optional_nested_message
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index 4d91ed56..ffc77f1c 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -312,7 +312,7 @@ const int DoubleValue::kValueFieldNumber;
#endif // !_MSC_VER
DoubleValue::DoubleValue()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.DoubleValue)
}
@@ -458,9 +458,9 @@ int DoubleValue::ByteSize() const {
void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const DoubleValue* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const DoubleValue*>(
- &from);
+ const DoubleValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -514,7 +514,7 @@ void DoubleValue::InternalSwap(DoubleValue* other) {
// DoubleValue
// optional double value = 1;
- void DoubleValue::clear_value() {
+void DoubleValue::clear_value() {
value_ = 0;
}
double DoubleValue::value() const {
@@ -536,7 +536,7 @@ const int FloatValue::kValueFieldNumber;
#endif // !_MSC_VER
FloatValue::FloatValue()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.FloatValue)
}
@@ -682,9 +682,9 @@ int FloatValue::ByteSize() const {
void FloatValue::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const FloatValue* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const FloatValue*>(
- &from);
+ const FloatValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -738,7 +738,7 @@ void FloatValue::InternalSwap(FloatValue* other) {
// FloatValue
// optional float value = 1;
- void FloatValue::clear_value() {
+void FloatValue::clear_value() {
value_ = 0;
}
float FloatValue::value() const {
@@ -760,7 +760,7 @@ const int Int64Value::kValueFieldNumber;
#endif // !_MSC_VER
Int64Value::Int64Value()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Int64Value)
}
@@ -908,9 +908,9 @@ int Int64Value::ByteSize() const {
void Int64Value::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Int64Value* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Int64Value*>(
- &from);
+ const Int64Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -964,7 +964,7 @@ void Int64Value::InternalSwap(Int64Value* other) {
// Int64Value
// optional int64 value = 1;
- void Int64Value::clear_value() {
+void Int64Value::clear_value() {
value_ = GOOGLE_LONGLONG(0);
}
::google::protobuf::int64 Int64Value::value() const {
@@ -986,7 +986,7 @@ const int UInt64Value::kValueFieldNumber;
#endif // !_MSC_VER
UInt64Value::UInt64Value()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UInt64Value)
}
@@ -1134,9 +1134,9 @@ int UInt64Value::ByteSize() const {
void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const UInt64Value* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const UInt64Value*>(
- &from);
+ const UInt64Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1190,7 +1190,7 @@ void UInt64Value::InternalSwap(UInt64Value* other) {
// UInt64Value
// optional uint64 value = 1;
- void UInt64Value::clear_value() {
+void UInt64Value::clear_value() {
value_ = GOOGLE_ULONGLONG(0);
}
::google::protobuf::uint64 UInt64Value::value() const {
@@ -1212,7 +1212,7 @@ const int Int32Value::kValueFieldNumber;
#endif // !_MSC_VER
Int32Value::Int32Value()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.Int32Value)
}
@@ -1360,9 +1360,9 @@ int Int32Value::ByteSize() const {
void Int32Value::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const Int32Value* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const Int32Value*>(
- &from);
+ const Int32Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1416,7 +1416,7 @@ void Int32Value::InternalSwap(Int32Value* other) {
// Int32Value
// optional int32 value = 1;
- void Int32Value::clear_value() {
+void Int32Value::clear_value() {
value_ = 0;
}
::google::protobuf::int32 Int32Value::value() const {
@@ -1438,7 +1438,7 @@ const int UInt32Value::kValueFieldNumber;
#endif // !_MSC_VER
UInt32Value::UInt32Value()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.UInt32Value)
}
@@ -1586,9 +1586,9 @@ int UInt32Value::ByteSize() const {
void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const UInt32Value* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const UInt32Value*>(
- &from);
+ const UInt32Value* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1642,7 +1642,7 @@ void UInt32Value::InternalSwap(UInt32Value* other) {
// UInt32Value
// optional uint32 value = 1;
- void UInt32Value::clear_value() {
+void UInt32Value::clear_value() {
value_ = 0u;
}
::google::protobuf::uint32 UInt32Value::value() const {
@@ -1664,7 +1664,7 @@ const int BoolValue::kValueFieldNumber;
#endif // !_MSC_VER
BoolValue::BoolValue()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.BoolValue)
}
@@ -1810,9 +1810,9 @@ int BoolValue::ByteSize() const {
void BoolValue::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const BoolValue* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const BoolValue*>(
- &from);
+ const BoolValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -1866,7 +1866,7 @@ void BoolValue::InternalSwap(BoolValue* other) {
// BoolValue
// optional bool value = 1;
- void BoolValue::clear_value() {
+void BoolValue::clear_value() {
value_ = false;
}
bool BoolValue::value() const {
@@ -1888,7 +1888,7 @@ const int StringValue::kValueFieldNumber;
#endif // !_MSC_VER
StringValue::StringValue()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.StringValue)
}
@@ -2051,9 +2051,9 @@ int StringValue::ByteSize() const {
void StringValue::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const StringValue* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const StringValue*>(
- &from);
+ const StringValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const StringValue>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -2108,7 +2108,7 @@ void StringValue::InternalSwap(StringValue* other) {
// StringValue
// optional string value = 1;
- void StringValue::clear_value() {
+void StringValue::clear_value() {
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& StringValue::value() const {
@@ -2159,7 +2159,7 @@ const int BytesValue::kValueFieldNumber;
#endif // !_MSC_VER
BytesValue::BytesValue()
- : ::google::protobuf::Message() , _internal_metadata_(NULL) {
+ : ::google::protobuf::Message(), _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.BytesValue)
}
@@ -2310,9 +2310,9 @@ int BytesValue::ByteSize() const {
void BytesValue::MergeFrom(const ::google::protobuf::Message& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
- const BytesValue* source =
- ::google::protobuf::internal::dynamic_cast_if_available<const BytesValue*>(
- &from);
+ const BytesValue* source =
+ ::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>(
+ &from);
if (source == NULL) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
@@ -2367,7 +2367,7 @@ void BytesValue::InternalSwap(BytesValue* other) {
// BytesValue
// optional bytes value = 1;
- void BytesValue::clear_value() {
+void BytesValue::clear_value() {
value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
const ::std::string& BytesValue::value() const {
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index c318f950..387ebd7c 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -984,6 +984,22 @@ inline void BytesValue::set_allocated_value(::std::string* value) {
}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
// @@protoc_insertion_point(namespace_scope)
diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj
index d1f065e2..3474d21f 100644
--- a/vsprojects/libprotoc.vcproj
+++ b/vsprojects/libprotoc.vcproj
@@ -296,6 +296,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_enum_field_lite.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_extension.h"
>
</File>
@@ -324,14 +328,34 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field_lite.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_message.h"
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_lite.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_builder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_builder_lite.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_message_field.h"
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_field_lite.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.h"
>
</File>
@@ -340,6 +364,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field_lite.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_service.h"
>
</File>
@@ -352,6 +380,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_string_field_lite.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.h"
>
</File>
@@ -608,18 +640,42 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field_lite.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_map_field.cc"
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_map_field_lite.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_message.cc"
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_lite.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_builder.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_builder_lite.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_message_field.cc"
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_field_lite.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.cc"
>
</File>
@@ -628,6 +684,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field_lite.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_service.cc"
>
</File>
@@ -640,6 +700,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_string_field_lite.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.cc"
>
</File>