aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore15
-rw-r--r--.travis.yml6
-rw-r--r--CHANGES.txt82
-rw-r--r--Makefile.am57
-rw-r--r--README.md16
-rw-r--r--config.h.include7
-rw-r--r--configure.ac6
-rwxr-xr-xgenerate_descriptor_proto.sh38
-rw-r--r--java/README.md (renamed from java/README.txt)8
-rw-r--r--java/pom.xml62
-rw-r--r--java/src/main/java/com/google/protobuf/AbstractMessage.java6
-rw-r--r--java/src/main/java/com/google/protobuf/BoundedByteString.java2
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java7
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java2
-rw-r--r--java/src/main/java/com/google/protobuf/DynamicMessage.java11
-rw-r--r--java/src/main/java/com/google/protobuf/FieldSet.java56
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java256
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java145
-rw-r--r--java/src/main/java/com/google/protobuf/LazyFieldLite.java249
-rw-r--r--java/src/main/java/com/google/protobuf/LiteralByteString.java6
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java4
-rw-r--r--java/src/main/java/com/google/protobuf/MessageReflection.java60
-rw-r--r--java/src/main/java/com/google/protobuf/Parser.java4
-rw-r--r--java/src/main/java/com/google/protobuf/RopeByteString.java8
-rw-r--r--java/src/main/java/com/google/protobuf/TextFormat.java119
-rw-r--r--java/src/main/java/com/google/protobuf/WireFormat.java82
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java12
-rw-r--r--java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java139
-rw-r--r--java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java19
-rw-r--r--java/src/test/java/com/google/protobuf/LiteralByteStringTest.java24
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2Test.java14
-rw-r--r--java/src/test/java/com/google/protobuf/MapTest.java170
-rw-r--r--java/src/test/java/com/google/protobuf/RopeByteStringTest.java28
-rw-r--r--java/src/test/java/com/google/protobuf/lazy_fields_lite.proto9
-rw-r--r--java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto7
-rw-r--r--java/src/test/java/com/google/protobuf/map_for_proto2_test.proto7
-rw-r--r--java/src/test/java/com/google/protobuf/map_test.proto1
-rw-r--r--java/src/test/java/com/google/protobuf/test_bad_identifiers.proto1
-rw-r--r--javanano/README.md (renamed from javanano/README.txt)85
-rw-r--r--javanano/pom.xml65
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java40
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java124
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/Extension.java73
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/InternalNano.java222
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/MapFactories.java67
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java14
-rw-r--r--javanano/src/test/java/com/google/protobuf/nano/NanoTest.java635
-rw-r--r--javanano/src/test/java/com/google/protobuf/nano/map_test.proto70
-rw-r--r--javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto9
-rwxr-xr-xpost_process_dist.sh2
-rw-r--r--python/README.md (renamed from python/README.txt)22
-rwxr-xr-xpython/google/protobuf/__init__.py2
-rwxr-xr-xpython/google/protobuf/descriptor.py158
-rw-r--r--python/google/protobuf/descriptor_pool.py114
-rwxr-xr-xpython/google/protobuf/internal/_parameterized.py438
-rw-r--r--python/google/protobuf/internal/api_implementation.cc14
-rwxr-xr-xpython/google/protobuf/internal/api_implementation.py38
-rw-r--r--python/google/protobuf/internal/api_implementation_default_test.py63
-rwxr-xr-xpython/google/protobuf/internal/containers.py37
-rwxr-xr-xpython/google/protobuf/internal/decoder.py3
-rwxr-xr-xpython/google/protobuf/internal/descriptor_test.py176
-rwxr-xr-xpython/google/protobuf/internal/message_test.py782
-rwxr-xr-xpython/google/protobuf/internal/python_message.py81
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py11
-rwxr-xr-xpython/google/protobuf/internal/test_util.py170
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py557
-rwxr-xr-xpython/google/protobuf/internal/type_checkers.py8
-rwxr-xr-xpython/google/protobuf/internal/unknown_fields_test.py120
-rwxr-xr-xpython/google/protobuf/message.py1
-rw-r--r--python/google/protobuf/pyext/descriptor.cc1514
-rw-r--r--python/google/protobuf/pyext/descriptor.h122
-rw-r--r--python/google/protobuf/pyext/descriptor_containers.cc1564
-rw-r--r--python/google/protobuf/pyext/descriptor_containers.h95
-rw-r--r--python/google/protobuf/pyext/descriptor_cpp2_test.py58
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.cc370
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.h152
-rw-r--r--python/google/protobuf/pyext/extension_dict.cc25
-rw-r--r--python/google/protobuf/pyext/extension_dict.h3
-rw-r--r--python/google/protobuf/pyext/message.cc1071
-rw-r--r--python/google/protobuf/pyext/message.h50
-rw-r--r--python/google/protobuf/pyext/message_factory_cpp2_test.py56
-rwxr-xr-xpython/google/protobuf/pyext/reflection_cpp2_generated_test.py94
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc60
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.h8
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.cc188
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.h4
-rwxr-xr-xpython/google/protobuf/reflection.py18
-rwxr-xr-xpython/google/protobuf/text_format.py5
-rwxr-xr-xpython/setup.py36
-rw-r--r--ruby/.gitignore6
-rw-r--r--ruby/Gemfile3
-rw-r--r--ruby/Gemfile.lock25
-rw-r--r--ruby/README.md89
-rw-r--r--ruby/Rakefile26
-rw-r--r--ruby/ext/google/protobuf_c/encode_decode.c27
-rw-r--r--ruby/ext/google/protobuf_c/map.c2
-rw-r--r--ruby/google-protobuf.gemspec29
-rw-r--r--ruby/lib/google/protobuf.rb7
-rw-r--r--ruby/pom.xml84
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java167
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java267
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java169
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java86
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java82
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java185
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java248
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java434
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java744
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java217
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java84
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java124
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java118
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java391
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java776
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/Utils.java300
-rw-r--r--ruby/src/main/java/google/ProtobufJavaService.java60
-rw-r--r--ruby/src/main/sentinel.proto15
-rw-r--r--ruby/tests/basic.rb4
-rw-r--r--ruby/tests/generated_code.rb70
-rw-r--r--ruby/tests/stress.rb2
-rw-r--r--src/Makefile.am70
-rw-r--r--src/google/protobuf/SEBS240
-rw-r--r--src/google/protobuf/any.proto98
-rwxr-xr-x[-rw-r--r--]src/google/protobuf/arena.cc65
-rw-r--r--src/google/protobuf/arena.h156
-rw-r--r--src/google/protobuf/arena_test_util.cc49
-rw-r--r--src/google/protobuf/arena_test_util.h59
-rw-r--r--src/google/protobuf/arena_unittest.cc236
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc317
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h12
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc89
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc20
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc113
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc42
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc19
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h7
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc144
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc99
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h4
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc270
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h11
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc52
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc168
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto18
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto43
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc15
-rw-r--r--src/google/protobuf/compiler/java/java_field.h1
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc4
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h10
-rw-r--r--src/google/protobuf/compiler/java/java_lazy_message_field.cc10
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc101
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.h1
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc284
-rw-r--r--src/google/protobuf/compiler/java/java_message.h2
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc2
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.cc68
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.h10
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.cc19
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_helpers.h10
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_map_field.cc186
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_map_field.h70
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc60
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc81
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.h22
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc98
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.h27
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc8
-rw-r--r--src/google/protobuf/compiler/parser.cc94
-rw-r--r--src/google/protobuf/compiler/parser.h37
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc234
-rw-r--r--src/google/protobuf/compiler/plugin.cc13
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc395
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h155
-rw-r--r--src/google/protobuf/compiler/plugin.proto2
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc30
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h3
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator.cc78
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator.h3
-rw-r--r--src/google/protobuf/descriptor.cc88
-rw-r--r--src/google/protobuf/descriptor.h24
-rw-r--r--src/google/protobuf/descriptor.pb.cc3827
-rw-r--r--src/google/protobuf/descriptor.pb.h1347
-rw-r--r--src/google/protobuf/descriptor.proto23
-rw-r--r--src/google/protobuf/descriptor_database.cc28
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc6
-rw-r--r--src/google/protobuf/descriptor_pb2_test.py54
-rw-r--r--src/google/protobuf/descriptor_unittest.cc4
-rw-r--r--src/google/protobuf/duration.proto93
-rw-r--r--src/google/protobuf/extension_set.cc16
-rw-r--r--src/google/protobuf/extension_set_heavy.cc7
-rw-r--r--src/google/protobuf/field_mask.proto161
-rw-r--r--src/google/protobuf/generated_enum_reflection.h5
-rw-r--r--src/google/protobuf/generated_enum_util.h46
-rw-r--r--src/google/protobuf/generated_message_reflection.cc47
-rw-r--r--src/google/protobuf/io/coded_stream.cc77
-rw-r--r--src/google/protobuf/io/coded_stream.h56
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc4
-rw-r--r--src/google/protobuf/io/gzip_stream.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h2
-rw-r--r--src/google/protobuf/lite_unittest.cc2
-rw-r--r--src/google/protobuf/map.h181
-rw-r--r--src/google/protobuf/map_entry.h331
-rw-r--r--src/google/protobuf/map_entry_lite.h409
-rw-r--r--src/google/protobuf/map_field.cc8
-rw-r--r--src/google/protobuf/map_field.h88
-rw-r--r--src/google/protobuf/map_field_inl.h298
-rw-r--r--src/google/protobuf/map_field_lite.h278
-rw-r--r--src/google/protobuf/map_field_test.cc67
-rw-r--r--src/google/protobuf/map_lite_test_util.cc93
-rw-r--r--src/google/protobuf/map_lite_test_util.h80
-rw-r--r--src/google/protobuf/map_lite_unittest.proto98
-rw-r--r--src/google/protobuf/map_test.cc84
-rw-r--r--src/google/protobuf/map_test_util.cc272
-rw-r--r--src/google/protobuf/map_test_util.h9
-rw-r--r--src/google/protobuf/map_test_util_impl.h474
-rw-r--r--src/google/protobuf/map_type_handler.h200
-rw-r--r--src/google/protobuf/map_unittest.proto23
-rw-r--r--src/google/protobuf/message.cc24
-rw-r--r--src/google/protobuf/message.h26
-rw-r--r--src/google/protobuf/message_lite.h14
-rw-r--r--src/google/protobuf/new_delete_capture.cc121
-rw-r--r--src/google/protobuf/new_delete_capture.h175
-rw-r--r--src/google/protobuf/preserve_unknown_enum_test.cc107
-rwxr-xr-x[-rw-r--r--]src/google/protobuf/reflection.h301
-rw-r--r--src/google/protobuf/repeated_field.h2
-rw-r--r--src/google/protobuf/repeated_field_reflection_unittest.cc2
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc29
-rw-r--r--src/google/protobuf/struct.proto83
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_mips_gcc.h4
-rwxr-xr-x[-rw-r--r--]src/google/protobuf/stubs/hash.h74
-rw-r--r--src/google/protobuf/stubs/singleton.h6
-rw-r--r--src/google/protobuf/stubs/strutil.cc205
-rw-r--r--src/google/protobuf/stubs/strutil.h203
-rw-r--r--src/google/protobuf/testdata/golden_message_proto3bin0 -> 398 bytes
-rw-r--r--src/google/protobuf/testing/file.cc4
-rw-r--r--src/google/protobuf/testing/file.h3
-rw-r--r--src/google/protobuf/text_format.cc7
-rw-r--r--src/google/protobuf/text_format.h16
-rw-r--r--src/google/protobuf/timestamp.proto103
-rw-r--r--src/google/protobuf/unittest_no_arena.proto3
-rw-r--r--src/google/protobuf/unittest_preserve_unknown_enum.proto12
-rw-r--r--src/google/protobuf/unittest_preserve_unknown_enum2.proto50
-rw-r--r--src/google/protobuf/unittest_proto3_arena.proto54
-rw-r--r--src/google/protobuf/unknown_enum_impl.h23
-rw-r--r--src/google/protobuf/unknown_field_set.h5
-rw-r--r--src/google/protobuf/wire_format.cc35
-rw-r--r--src/google/protobuf/wire_format.h8
-rw-r--r--src/google/protobuf/wire_format_lite.cc28
-rw-r--r--src/google/protobuf/wire_format_lite.h19
-rw-r--r--src/google/protobuf/wrappers.proto97
-rwxr-xr-x[-rw-r--r--]vsprojects/config.h29
-rwxr-xr-xvsprojects/extract_includes.bat9
-rwxr-xr-xvsprojects/google/protobuf/stubs/pbconfig.h39
-rw-r--r--vsprojects/libprotobuf-lite.vcproj7
-rw-r--r--vsprojects/libprotobuf.vcproj7
-rw-r--r--vsprojects/libprotoc.vcproj1054
-rw-r--r--vsprojects/lite-test.vcproj28
-rw-r--r--vsprojects/tests.vcproj20
267 files changed, 26250 insertions, 6552 deletions
diff --git a/.gitignore b/.gitignore
index 3938196c..b8ba4892 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@ m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
+autom4te.cache
# downloaded files
gtest
@@ -23,9 +24,10 @@ gtest
# in-tree configure-generated files
Makefile
src/Makefile
-config.h
+/config.h
config.log
config.status
+pbconfig.h
libtool
protobuf-lite.pc
@@ -38,6 +40,7 @@ stamp-h1
*.lo
*.la
src/.libs
+*.so
.dirstamp
@@ -61,3 +64,13 @@ src/test_plugin
src/testzip.*
src/zcg*zip
ar-lib
+
+test-driver
+compile
+
+src/**/*.log
+src/**/*.trs
+
+# JavaBuild output.
+java/target
+javanano/target
diff --git a/.travis.yml b/.travis.yml
index 93013b8b..18114878 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,8 @@
+sudo: false
language: cpp
-script: ./autogen.sh && ./configure && make distcheck
+os:
+ - linux
+ - osx
+script: ./autogen.sh && ./configure && make distcheck -j2
notifications:
email: false
diff --git a/CHANGES.txt b/CHANGES.txt
index 0d4ce0ec..ac42aa5a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,85 @@
+2015-02-26 version 3.0.0-alpha-2 (Python/Ruby/JavaNano):
+ General
+ * Introduced three new language implementations (Ruby, JavaNano, and
+ Python) to proto3.
+ * Various bug fixes since 3.0.0-alpha-1
+
+ Python:
+ Python has received several updates, most notably support for proto3
+ semantics in any .proto file that declares syntax="proto3".
+ Messages declared in proto3 files no longer represent field presence
+ for scalar fields (number, enums, booleans, or strings). You can
+ no longer call HasField() for such fields, and they are serialized
+ based on whether they have a non-zero/empty/false value.
+
+ One other notable change is in the C++-accelerated implementation.
+ Descriptor objects (which describe the protobuf schema and allow
+ reflection over it) are no longer duplicated between the Python
+ and C++ layers. The Python descriptors are now simple wrappers
+ around the C++ descriptors. This change should significantly
+ reduce the memory usage of programs that use a lot of message
+ types.
+
+ Ruby:
+ We have added proto3 support for Ruby via a native C extension.
+
+ The Ruby extension itself is included in the ruby/ directory, and details on
+ building and installing the extension are in ruby/README.md. The extension
+ will also be published as a Ruby gem. Code generator support is included as
+ part of `protoc` with the `--ruby_out` flag.
+
+ The Ruby extension implements a user-friendly DSL to define message types
+ (also generated by the code generator from `.proto` files). Once a message
+ type is defined, the user may create instances of the message that behave in
+ ways idiomatic to Ruby. For example:
+
+ - Message fields are present as ordinary Ruby properties (getter method
+ `foo` and setter method `foo=`).
+ - Repeated field elements are stored in a container that acts like a native
+ Ruby array, and map elements are stored in a container that acts like a
+ native Ruby hashmap.
+ - The usual well-known methods, such as `#to_s`, `#dup`, and the like, are
+ present.
+
+ Unlike several existing third-party Ruby extensions for protobuf, this
+ extension is built on a "strongly-typed" philosophy: message fields and
+ array/map containers will throw exceptions eagerly when values of the
+ incorrect type are inserted.
+
+ See ruby/README.md for details.
+
+ JavaNano:
+ JavaNano is a special code generator and runtime library designed especially
+ for resource-restricted systems, like Android. It is very resource-friendly
+ in both the amount of code and the runtime overhead. Here is an an overview
+ of JavaNano features compared with the official Java protobuf:
+
+ - No descriptors or message builders.
+ - All messages are mutable; fields are public Java fields.
+ - For optional fields only, encapsulation behind setter/getter/hazzer/
+ clearer functions is opt-in, which provide proper 'has' state support.
+ - For proto2, if not opted in, has state (field presence) is not available.
+ Serialization outputs all fields not equal to their defaults.
+ The behavior is consistent with proto3 semantics.
+ - Required fields (proto2 only) are always serialized.
+ - Enum constants are integers; protection against invalid values only
+ when parsing from the wire.
+ - Enum constants can be generated into container interfaces bearing
+ the enum's name (so the referencing code is in Java style).
+ - CodedInputByteBufferNano can only take byte[] (not InputStream).
+ - Similarly CodedOutputByteBufferNano can only write to byte[].
+ - Repeated fields are in arrays, not ArrayList or Vector. Null array
+ elements are allowed and silently ignored.
+ - Full support for serializing/deserializing repeated packed fields.
+ - Support extensions (in proto2).
+ - Unset messages/groups are null, not an immutable empty default
+ instance.
+ - toByteArray(...) and mergeFrom(...) are now static functions of
+ MessageNano.
+ - The 'bytes' type translates to the Java type byte[].
+
+ See javanano/README.txt for details.
+
2014-12-01 version 3.0.0-alpha-1 (C++/Java):
General
diff --git a/Makefile.am b/Makefile.am
index 95316eb5..e7820f2a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -152,12 +152,51 @@ java_EXTRA_DIST= \
java/src/test/java/com/google/protobuf/test_check_utf8_size.proto \
java/src/test/java/com/google/protobuf/test_custom_options.proto \
java/pom.xml \
- java/README.txt
+ java/README.md
+
+javanano_EXTRA_DIST= \
+ javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java \
+ javanano/src/main/java/com/google/protobuf/nano/FieldData.java \
+ javanano/src/main/java/com/google/protobuf/nano/FieldArray.java \
+ javanano/src/main/java/com/google/protobuf/nano/WireFormatNano.java \
+ javanano/src/main/java/com/google/protobuf/nano/Extension.java \
+ javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java \
+ javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java \
+ javanano/src/main/java/com/google/protobuf/nano/MessageNano.java \
+ javanano/src/main/java/com/google/protobuf/nano/InternalNano.java \
+ javanano/src/main/java/com/google/protobuf/nano/InvalidProtocolBufferNanoException.java \
+ javanano/src/main/java/com/google/protobuf/nano/MapFactories.java \
+ javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java \
+ javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_accessors_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_has_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_single_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/NanoTest.java \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_simple_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_import_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_repeated_packables_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_recursive_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_enum_validity_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_stringutf8_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_multiple_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/unittest_enum_class_multiple_nano.proto \
+ javanano/src/test/java/com/google/protobuf/nano/map_test.proto \
+ javanano/README.md \
+ javanano/pom.xml
+
python_EXTRA_DIST= \
python/google/protobuf/internal/api_implementation.cc \
python/google/protobuf/internal/api_implementation.py \
- python/google/protobuf/internal/api_implementation_default_test.py \
python/google/protobuf/internal/containers.py \
python/google/protobuf/internal/cpp_message.py \
python/google/protobuf/internal/decoder.py \
@@ -181,6 +220,7 @@ python_EXTRA_DIST= \
python/google/protobuf/internal/more_extensions.proto \
python/google/protobuf/internal/more_extensions_dynamic.proto \
python/google/protobuf/internal/more_messages.proto \
+ python/google/protobuf/internal/_parameterized.py \
python/google/protobuf/internal/proto_builder_test.py \
python/google/protobuf/internal/python_message.py \
python/google/protobuf/internal/reflection_test.py \
@@ -202,16 +242,17 @@ python_EXTRA_DIST= \
python/google/protobuf/pyext/cpp_message.py \
python/google/protobuf/pyext/descriptor.h \
python/google/protobuf/pyext/descriptor.cc \
- python/google/protobuf/pyext/descriptor_cpp2_test.py \
+ python/google/protobuf/pyext/descriptor_pool.h \
+ python/google/protobuf/pyext/descriptor_pool.cc \
+ python/google/protobuf/pyext/descriptor_containers.h \
+ python/google/protobuf/pyext/descriptor_containers.cc \
python/google/protobuf/pyext/extension_dict.h \
python/google/protobuf/pyext/extension_dict.cc \
python/google/protobuf/pyext/message.h \
python/google/protobuf/pyext/message.cc \
- python/google/protobuf/pyext/message_factory_cpp2_test.py \
python/google/protobuf/pyext/proto2_api_test.proto \
python/google/protobuf/pyext/python.proto \
python/google/protobuf/pyext/python_protobuf.h \
- python/google/protobuf/pyext/reflection_cpp2_generated_test.py \
python/google/protobuf/pyext/repeated_composite_container.h \
python/google/protobuf/pyext/repeated_composite_container.cc \
python/google/protobuf/pyext/repeated_scalar_container.h \
@@ -236,7 +277,7 @@ python_EXTRA_DIST= \
python/setup.py \
python/mox.py \
python/stubout.py \
- python/README.txt
+ python/README.md
ruby_EXTRA_DIST= \
ruby/README.md \
@@ -260,7 +301,7 @@ ruby_EXTRA_DIST= \
ruby/tests/generated_code.rb \
ruby/tests/generated_code_test.rb
-all_EXTRA_DIST=$(java_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
+all_EXTRA_DIST=$(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
autogen.sh \
@@ -270,10 +311,12 @@ EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
LICENSE \
CONTRIBUTORS.txt \
CHANGES.txt \
+ config.h.include \
editors/README.txt \
editors/proto.vim \
editors/protobuf-mode.el \
vsprojects/config.h \
+ vsprojects/google/protobuf/stubs/pbconfig.h \
vsprojects/extract_includes.bat \
vsprojects/libprotobuf.vcproj \
vsprojects/libprotobuf-lite.vcproj \
diff --git a/README.md b/README.md
index ae406792..5ea6aff6 100644
--- a/README.md
+++ b/README.md
@@ -88,6 +88,22 @@ For advanced usage information on configure and make, see INSTALL.txt.
If you only want protobuf-lite, substitute "protobuf-lite" in place
of "protobuf" in these examples.
+**Note for Mac users**
+
+ For a Mac system, Unix tools are not available by default. You will first need
+ to install Xcode from the Mac AppStore and then run the following command from
+ a terminal:
+
+ $ sudo xcode-select --install
+
+ To install Unix tools, you can install "port" following the instructions at
+ https://www.macports.org . This will reside in /opt/local/bin/port for most
+ Mac installations.
+
+ $ sudo /opt/local/bin/port install autoconf automake libtool
+
+ Then follow the Unix instructions above.
+
**Note for cross-compiling**
The makefiles normally invoke the protoc executable that they just
diff --git a/config.h.include b/config.h.include
new file mode 100644
index 00000000..0c557fbe
--- /dev/null
+++ b/config.h.include
@@ -0,0 +1,7 @@
+HASH_MAP_CLASS
+HASH_MAP_H
+HASH_NAMESPACE
+HASH_SET_CLASS
+HASH_SET_H
+HAVE_HASH_MAP
+HAVE_HASH_SET
diff --git a/configure.ac b/configure.ac
index d1fde9d5..14351a8b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,7 +12,7 @@ AC_PREREQ(2.59)
# In the SVN trunk, the version should always be the next anticipated release
# version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed
# the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.0.0-pre],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.0.0-alpha-3-pre],[protobuf@googlegroups.com],[protobuf])
AM_MAINTAINER_MODE([enable])
@@ -37,7 +37,7 @@ AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],
AC_CANONICAL_TARGET
-AM_INIT_AUTOMAKE([subdir-objects])
+AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects])
AC_ARG_WITH([zlib],
[AS_HELP_STRING([--with-zlib],
@@ -54,7 +54,7 @@ AC_PROG_CC
AC_PROG_CXX
AC_LANG([C++])
ACX_USE_SYSTEM_EXTENSIONS
-AM_PROG_AR
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AM_CONDITIONAL(GCC, test "$GCC" = yes) # let the Makefile know if we're gcc
# test_util.cc takes forever to compile with GCC and optimization turned on.
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index 07219dc1..b25a3c6a 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -27,7 +27,39 @@ __EOF__
fi
cd src
-make $@ protoc &&
- ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto && \
- ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto
+CORE_PROTO_IS_CORRECT=0
+while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
+do
+ CORE_PROTO_IS_CORRECT=1
+ cp google/protobuf/descriptor.pb.h google/protobuf/descriptor.pb.h.tmp
+ cp google/protobuf/descriptor.pb.cc google/protobuf/descriptor.pb.cc.tmp
+ cp google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp
+ cp google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp
+
+ make $@ protoc &&
+ ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto && \
+ ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto
+
+ diff google/protobuf/descriptor.pb.h google/protobuf/descriptor.pb.h.tmp > /dev/null
+ if test $? -ne 0; then
+ CORE_PROTO_IS_CORRECT=0
+ fi
+ diff google/protobuf/descriptor.pb.cc google/protobuf/descriptor.pb.cc.tmp > /dev/null
+ if test $? -ne 0; then
+ CORE_PROTO_IS_CORRECT=0
+ fi
+ diff google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp > /dev/null
+ if test $? -ne 0; then
+ CORE_PROTO_IS_CORRECT=0
+ fi
+ diff google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp > /dev/null
+ if test $? -ne 0; then
+ CORE_PROTO_IS_CORRECT=0
+ fi
+
+ rm google/protobuf/descriptor.pb.h.tmp
+ rm google/protobuf/descriptor.pb.cc.tmp
+ rm google/protobuf/compiler/plugin.pb.h.tmp
+ rm google/protobuf/compiler/plugin.pb.cc.tmp
+done
cd ..
diff --git a/java/README.txt b/java/README.md
index 57e26a96..060d9ac6 100644
--- a/java/README.txt
+++ b/java/README.md
@@ -1,4 +1,8 @@
Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
Copyright 2008 Google Inc.
This directory contains the Java Protocol Buffers runtime library.
@@ -50,17 +54,19 @@ http://maven.apache.org/guides/introduction/introduction-to-profiles.html)
E.g. to install the lite version of the jar, you would run:
- $ mvn install -P lite
+ $ mvn install -P lite
The resulting artifact has the 'lite' classifier. To reference it
for dependency resolution, you would specify it as:
+```
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>${version}</version>
<classifier>lite</classifier>
</dependency>
+```
Installation - Without Maven
============================
diff --git a/java/pom.xml b/java/pom.xml
index bbadc656..3eb7a703 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
- <version>3.0.0-pre</version>
+ <version>3.0.0-alpha-3-pre</version>
<packaging>bundle</packaging>
<name>Protocol Buffer Java API</name>
<description>
@@ -152,7 +152,7 @@
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
- <Export-Package>com.google.protobuf;version=3.0.0-pre</Export-Package>
+ <Export-Package>com.google.protobuf;version=3.0.0-alpha-3-pre</Export-Package>
</instructions>
</configuration>
</plugin>
@@ -160,6 +160,64 @@
</build>
<profiles>
<profile>
+ <id>release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <version>1.6.3</version>
+ <extensions>true</extensions>
+ <configuration>
+ <serverId>sonatype-nexus-staging</serverId>
+ <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+ <autoReleaseAfterClose>false</autoReleaseAfterClose>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
<id>lite</id>
<build>
<plugins>
diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java
index 6de4cae3..cc89173a 100644
--- a/java/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -83,10 +83,10 @@ public abstract class AbstractMessage extends AbstractMessageLite
}
public void writeTo(final CodedOutputStream output) throws IOException {
- MessageReflection.writeMessageTo(this, output, false);
+ MessageReflection.writeMessageTo(this, getAllFields(), output, false);
}
- private int memoizedSize = -1;
+ protected int memoizedSize = -1;
public int getSerializedSize() {
int size = memoizedSize;
@@ -94,7 +94,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
return size;
}
- memoizedSize = MessageReflection.getSerializedSize(this);
+ memoizedSize = MessageReflection.getSerializedSize(this, getAllFields());
return memoizedSize;
}
diff --git a/java/src/main/java/com/google/protobuf/BoundedByteString.java b/java/src/main/java/com/google/protobuf/BoundedByteString.java
index 8cb6f463..b4c3fb1b 100644
--- a/java/src/main/java/com/google/protobuf/BoundedByteString.java
+++ b/java/src/main/java/com/google/protobuf/BoundedByteString.java
@@ -30,8 +30,8 @@
package com.google.protobuf;
-import java.io.InvalidObjectException;
import java.io.IOException;
+import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.util.NoSuchElementException;
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index cff1ee51..9b0a524b 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -76,6 +76,9 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b
static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k
+ // Defined by java.nio.charset.Charset
+ protected static final String UTF_8 = "UTF-8";
+
/**
* Empty {@code ByteString}.
*/
@@ -267,7 +270,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
*/
public static ByteString copyFromUtf8(String text) {
try {
- return new LiteralByteString(text.getBytes("UTF-8"));
+ return new LiteralByteString(text.getBytes(UTF_8));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported?", e);
}
@@ -622,7 +625,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
*/
public String toStringUtf8() {
try {
- return toString("UTF-8");
+ return toString(UTF_8);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 not supported?", e);
}
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index d65e8b49..806f46c1 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -897,7 +897,7 @@ public final class Descriptors {
return (type == Type.STRING) && (getFile().getOptions().getJavaStringCheckUtf8());
}
- boolean isMapField() {
+ public boolean isMapField() {
return getType() == Type.MESSAGE && isRepeated()
&& getMessageType().getOptions().getMapEntry();
}
diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java
index 9c5e6c61..3ea1b688 100644
--- a/java/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -35,8 +35,8 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
-import java.io.InputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -600,9 +600,12 @@ public final class DynamicMessage extends AbstractMessage {
}
// TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not
// set incorrect EnumValueDescriptors.
- // if (field.getEnumType() != ((EnumValueDescriptor) value).getType()) {
- // throw new IllegalArgumentException(
- // "EnumValueDescriptor doesn't match Enum Field.");
+ // EnumDescriptor fieldType = field.getEnumType();
+ // EnumDescriptor fieldValueType = ((EnumValueDescriptor) value).getType();
+ // if (fieldType != fieldValueType) {
+ // throw new IllegalArgumentException(String.format(
+ // "EnumDescriptor %s of field doesn't match EnumDescriptor %s of field value",
+ // fieldType.getFullName(), fieldValueType.getFullName()));
// }
}
diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java
index ff9b5bc0..47924b65 100644
--- a/java/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/src/main/java/com/google/protobuf/FieldSet.java
@@ -553,42 +553,13 @@ final class FieldSet<FieldDescriptorType extends
CodedInputStream input,
final WireFormat.FieldType type,
boolean checkUtf8) throws IOException {
- switch (type) {
- case DOUBLE : return input.readDouble ();
- case FLOAT : return input.readFloat ();
- case INT64 : return input.readInt64 ();
- case UINT64 : return input.readUInt64 ();
- case INT32 : return input.readInt32 ();
- case FIXED64 : return input.readFixed64 ();
- case FIXED32 : return input.readFixed32 ();
- case BOOL : return input.readBool ();
- case STRING : if (checkUtf8) {
- return input.readStringRequireUtf8();
- } else {
- return input.readString();
- }
- case BYTES : return input.readBytes ();
- case UINT32 : return input.readUInt32 ();
- case SFIXED32: return input.readSFixed32();
- case SFIXED64: return input.readSFixed64();
- case SINT32 : return input.readSInt32 ();
- case SINT64 : return input.readSInt64 ();
-
- case GROUP:
- throw new IllegalArgumentException(
- "readPrimitiveField() cannot handle nested groups.");
- case MESSAGE:
- throw new IllegalArgumentException(
- "readPrimitiveField() cannot handle embedded messages.");
- case ENUM:
- // We don't handle enums because we don't know what to do if the
- // value is not recognized.
- throw new IllegalArgumentException(
- "readPrimitiveField() cannot handle enums.");
+ if (checkUtf8) {
+ return WireFormat.readPrimitiveField(input, type,
+ WireFormat.Utf8Validation.STRICT);
+ } else {
+ return WireFormat.readPrimitiveField(input, type,
+ WireFormat.Utf8Validation.LOOSE);
}
-
- throw new RuntimeException(
- "There is no way to get here, but the compiler thinks otherwise.");
}
@@ -685,9 +656,15 @@ final class FieldSet<FieldDescriptorType extends
case FIXED64 : output.writeFixed64NoTag ((Long ) value); break;
case FIXED32 : output.writeFixed32NoTag ((Integer ) value); break;
case BOOL : output.writeBoolNoTag ((Boolean ) value); break;
- case STRING : output.writeStringNoTag ((String ) value); break;
case GROUP : output.writeGroupNoTag ((MessageLite) value); break;
case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break;
+ case STRING:
+ if (value instanceof ByteString) {
+ output.writeBytesNoTag((ByteString) value);
+ } else {
+ output.writeStringNoTag((String) value);
+ }
+ break;
case BYTES:
if (value instanceof ByteString) {
output.writeBytesNoTag((ByteString) value);
@@ -843,7 +820,6 @@ final class FieldSet<FieldDescriptorType extends
case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long )value);
case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer )value);
case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value);
- case STRING : return CodedOutputStream.computeStringSizeNoTag ((String )value);
case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value);
case BYTES :
if (value instanceof ByteString) {
@@ -851,6 +827,12 @@ final class FieldSet<FieldDescriptorType extends
} else {
return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value);
}
+ case STRING :
+ if (value instanceof ByteString) {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ } else {
+ return CodedOutputStream.computeStringSizeNoTag((String) value);
+ }
case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value);
case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value);
case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value);
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 156d1633..9457d999 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -73,7 +73,7 @@ public abstract class GeneratedMessage extends AbstractMessage
/** For use by generated code only. */
protected UnknownFieldSet unknownFields;
-
+
protected GeneratedMessage() {
unknownFields = UnknownFieldSet.getDefaultInstance();
}
@@ -109,8 +109,15 @@ public abstract class GeneratedMessage extends AbstractMessage
return internalGetFieldAccessorTable().descriptor;
}
- /** Internal helper which returns a mutable map. */
- private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+ /**
+ * Internal helper to return a modifiable map containing all the fields.
+ * The returned Map is modifialbe so that the caller can add additional
+ * extension fields to implement {@link #getAllFields()}.
+ *
+ * @param getBytesForString whether to generate ByteString for string fields
+ */
+ private Map<FieldDescriptor, Object> getAllFieldsMutable(
+ boolean getBytesForString) {
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
@@ -122,7 +129,12 @@ public abstract class GeneratedMessage extends AbstractMessage
}
} else {
if (hasField(field)) {
- result.put(field, getField(field));
+ if (getBytesForString
+ && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ result.put(field, getFieldRaw(field));
+ } else {
+ result.put(field, getField(field));
+ }
}
}
}
@@ -161,7 +173,23 @@ public abstract class GeneratedMessage extends AbstractMessage
//@Override (Java 1.6 override semantics, but we must support 1.5)
public Map<FieldDescriptor, Object> getAllFields() {
- return Collections.unmodifiableMap(getAllFieldsMutable());
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ false));
+ }
+
+ /**
+ * Returns a collection of all the fields in this message which are set
+ * and their corresponding values. A singular ("required" or "optional")
+ * field is set iff hasField() returns true for that field. A "repeated"
+ * field is set iff getRepeatedFieldCount() is greater than zero. The
+ * values are exactly what would be returned by calling
+ * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map
+ * is guaranteed to be a sorted map, so iterating over it will return fields
+ * in order by field number.
+ */
+ Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ true));
}
//@Override (Java 1.6 override semantics, but we must support 1.5)
@@ -184,6 +212,18 @@ public abstract class GeneratedMessage extends AbstractMessage
return internalGetFieldAccessorTable().getField(field).get(this);
}
+ /**
+ * Obtains the value of the given field, or the default value if it is
+ * not set. For primitive fields, the boxed primitive value is returned.
+ * For enum fields, the EnumValueDescriptor for the value is returned. For
+ * embedded message fields, the sub-message is returned. For repeated
+ * fields, a java.util.List is returned. For present string fields, a
+ * ByteString is returned representing the bytes that the field contains.
+ */
+ Object getFieldRaw(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getRaw(this);
+ }
+
//@Override (Java 1.6 override semantics, but we must support 1.5)
public int getRepeatedFieldCount(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field)
@@ -214,6 +254,24 @@ public abstract class GeneratedMessage extends AbstractMessage
return unknownFields.mergeFieldFrom(tag, input);
}
+ @Override
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
+ }
+
+ @Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ memoizedSize = MessageReflection.getSerializedSize(
+ this, getAllFieldsRaw());
+ return memoizedSize;
+ }
+
+
/**
* Used by parsing constructors in generated classes.
@@ -549,12 +607,12 @@ public abstract class GeneratedMessage extends AbstractMessage
* Gets the map field with the given field number. This method should be
* overridden in the generated message class if the message contains map
* fields.
- *
+ *
* Unlike other field types, reflection support for map fields can't be
* implemented based on generated public API because we need to access a
* map field as a list in reflection API but the generated API only allows
* us to access it as a map. This method returns the underlying map field
- * directly and thus enables us to access the map field as a list.
+ * directly and thus enables us to access the map field as a list.
*/
@SuppressWarnings({"unused", "rawtypes"})
protected MapField internalGetMapField(int fieldNumber) {
@@ -563,6 +621,15 @@ public abstract class GeneratedMessage extends AbstractMessage
throw new RuntimeException(
"No map fields found in " + getClass().getName());
}
+
+ /** Like {@link internalGetMapField} but return a mutable version. */
+ @SuppressWarnings({"unused", "rawtypes"})
+ protected MapField internalGetMutableMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
}
// =================================================================
@@ -683,7 +750,7 @@ public abstract class GeneratedMessage extends AbstractMessage
public final <Type> Type getExtension(
final ExtensionLite<MessageType, Type> extensionLite) {
Extension<MessageType, Type> extension = checkNotLite(extensionLite);
-
+
verifyExtensionContainingType(extension);
FieldDescriptor descriptor = extension.getDescriptor();
final Object value = extensions.getField(descriptor);
@@ -825,7 +892,16 @@ public abstract class GeneratedMessage extends AbstractMessage
@Override
public Map<FieldDescriptor, Object> getAllFields() {
- final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
+ result.putAll(getExtensionFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
result.putAll(getExtensionFields());
return Collections.unmodifiableMap(result);
}
@@ -1313,7 +1389,7 @@ public abstract class GeneratedMessage extends AbstractMessage
implements ExtensionDescriptorRetriever {
private volatile FieldDescriptor descriptor;
protected abstract FieldDescriptor loadDescriptor();
-
+
public FieldDescriptor getDescriptor() {
if (descriptor == null) {
synchronized (this) {
@@ -1651,17 +1727,17 @@ public abstract class GeneratedMessage extends AbstractMessage
}
}
}
-
+
/**
* Gets the map field with the given field number. This method should be
* overridden in the generated message class if the message contains map
* fields.
- *
+ *
* Unlike other field types, reflection support for map fields can't be
* implemented based on generated public API because we need to access a
* map field as a list in reflection API but the generated API only allows
* us to access it as a map. This method returns the underlying map field
- * directly and thus enables us to access the map field as a list.
+ * directly and thus enables us to access the map field as a list.
*/
@SuppressWarnings({"rawtypes", "unused"})
protected MapField internalGetMapField(int fieldNumber) {
@@ -1709,7 +1785,7 @@ public abstract class GeneratedMessage extends AbstractMessage
oneofs = new OneofAccessor[descriptor.getOneofs().size()];
initialized = false;
}
-
+
private boolean isMapFieldEnabled(FieldDescriptor field) {
boolean result = true;
return result;
@@ -1761,6 +1837,10 @@ public abstract class GeneratedMessage extends AbstractMessage
fields[i] = new SingularEnumFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass,
containingOneofCamelCaseName);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ fields[i] = new SingularStringFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
} else {
fields[i] = new SingularFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass,
@@ -1817,9 +1897,13 @@ public abstract class GeneratedMessage extends AbstractMessage
private interface FieldAccessor {
Object get(GeneratedMessage message);
Object get(GeneratedMessage.Builder builder);
+ Object getRaw(GeneratedMessage message);
+ Object getRaw(GeneratedMessage.Builder builder);
void set(Builder builder, Object value);
Object getRepeated(GeneratedMessage message, int index);
Object getRepeated(GeneratedMessage.Builder builder, int index);
+ Object getRepeatedRaw(GeneratedMessage message, int index);
+ Object getRepeatedRaw(GeneratedMessage.Builder builder, int index);
void setRepeated(Builder builder,
int index, Object value);
void addRepeated(Builder builder, Object value);
@@ -1934,11 +2018,11 @@ public abstract class GeneratedMessage extends AbstractMessage
protected final FieldDescriptor field;
protected final boolean isOneofField;
protected final boolean hasHasMethod;
-
+
private int getOneofFieldNumber(final GeneratedMessage message) {
return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
}
-
+
private int getOneofFieldNumber(final GeneratedMessage.Builder builder) {
return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
}
@@ -1949,6 +2033,12 @@ public abstract class GeneratedMessage extends AbstractMessage
public Object get(GeneratedMessage.Builder builder) {
return invokeOrDie(getMethodBuilder, builder);
}
+ public Object getRaw(final GeneratedMessage message) {
+ return get(message);
+ }
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return get(builder);
+ }
public void set(final Builder builder, final Object value) {
invokeOrDie(setMethod, builder, value);
}
@@ -1957,12 +2047,22 @@ public abstract class GeneratedMessage extends AbstractMessage
throw new UnsupportedOperationException(
"getRepeatedField() called on a singular field.");
}
+ public Object getRepeatedRaw(final GeneratedMessage message,
+ final int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
public Object getRepeated(GeneratedMessage.Builder builder, int index) {
throw new UnsupportedOperationException(
"getRepeatedField() called on a singular field.");
}
- public void setRepeated(final Builder builder,
- final int index, final Object value) {
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder,
+ int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
+ public void setRepeated(final Builder builder, final int index,
+ final Object value) {
throw new UnsupportedOperationException(
"setRepeatedField() called on a singular field.");
}
@@ -2058,6 +2158,12 @@ public abstract class GeneratedMessage extends AbstractMessage
public Object get(GeneratedMessage.Builder builder) {
return invokeOrDie(getMethodBuilder, builder);
}
+ public Object getRaw(final GeneratedMessage message) {
+ return get(message);
+ }
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return get(builder);
+ }
public void set(final Builder builder, final Object value) {
// Add all the elements individually. This serves two purposes:
// 1) Verifies that each element has the correct type.
@@ -2075,6 +2181,13 @@ public abstract class GeneratedMessage extends AbstractMessage
public Object getRepeated(GeneratedMessage.Builder builder, int index) {
return invokeOrDie(getRepeatedMethodBuilder, builder, index);
}
+ public Object getRepeatedRaw(GeneratedMessage message, int index) {
+ return getRepeated(message, index);
+ }
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder,
+ int index) {
+ return getRepeated(builder, index);
+ }
public void setRepeated(final Builder builder,
final int index, final Object value) {
invokeOrDie(setRepeatedMethod, builder, index, value);
@@ -2130,15 +2243,21 @@ public abstract class GeneratedMessage extends AbstractMessage
private final FieldDescriptor field;
private final Message mapEntryMessageDefaultInstance;
-
+
private MapField<?, ?> getMapField(GeneratedMessage message) {
return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
}
-
+
private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) {
return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
}
-
+
+ private MapField<?, ?> getMutableMapField(
+ GeneratedMessage.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMutableMapField(
+ field.getNumber());
+ }
+
public Object get(GeneratedMessage message) {
List result = new ArrayList();
for (int i = 0; i < getRepeatedCount(message); i++) {
@@ -2155,6 +2274,14 @@ public abstract class GeneratedMessage extends AbstractMessage
return Collections.unmodifiableList(result);
}
+ public Object getRaw(GeneratedMessage message) {
+ return get(message);
+ }
+
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return get(builder);
+ }
+
public void set(Builder builder, Object value) {
clear(builder);
for (Object entry : (List) value) {
@@ -2170,12 +2297,20 @@ public abstract class GeneratedMessage extends AbstractMessage
return getMapField(builder).getList().get(index);
}
+ public Object getRepeatedRaw(GeneratedMessage message, int index) {
+ return getRepeated(message, index);
+ }
+
+ public Object getRepeatedRaw(Builder builder, int index) {
+ return getRepeated(builder, index);
+ }
+
public void setRepeated(Builder builder, int index, Object value) {
- getMapField(builder).getMutableList().set(index, (Message) value);
+ getMutableMapField(builder).getMutableList().set(index, (Message) value);
}
public void addRepeated(Builder builder, Object value) {
- getMapField(builder).getMutableList().add((Message) value);
+ getMutableMapField(builder).getMutableList().add((Message) value);
}
public boolean has(GeneratedMessage message) {
@@ -2197,7 +2332,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
public void clear(Builder builder) {
- getMapField(builder).getMutableList().clear();
+ getMutableMapField(builder).getMutableList().clear();
}
public com.google.protobuf.Message.Builder newBuilder() {
@@ -2208,7 +2343,7 @@ public abstract class GeneratedMessage extends AbstractMessage
throw new UnsupportedOperationException(
"Nested builder not supported for map fields.");
}
-
+
public com.google.protobuf.Message.Builder getRepeatedBuilder(
Builder builder, int index) {
throw new UnsupportedOperationException(
@@ -2226,7 +2361,7 @@ public abstract class GeneratedMessage extends AbstractMessage
final Class<? extends Builder> builderClass,
final String containingOneofCamelCaseName) {
super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
-
+
enumDescriptor = descriptor.getEnumType();
valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -2244,12 +2379,12 @@ public abstract class GeneratedMessage extends AbstractMessage
getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
}
}
-
+
private EnumDescriptor enumDescriptor;
private Method valueOfMethod;
private Method getValueDescriptorMethod;
-
+
private boolean supportUnknownEnumValue;
private Method getValueMethod;
private Method getValueMethodBuilder;
@@ -2291,7 +2426,7 @@ public abstract class GeneratedMessage extends AbstractMessage
final Class<? extends GeneratedMessage> messageClass,
final Class<? extends Builder> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass);
-
+
enumDescriptor = descriptor.getEnumType();
valueOfMethod = getMethodOrDie(type, "valueOf",
@@ -2315,7 +2450,7 @@ public abstract class GeneratedMessage extends AbstractMessage
private final Method valueOfMethod;
private final Method getValueDescriptorMethod;
-
+
private boolean supportUnknownEnumValue;
private Method getRepeatedValueMethod;
private Method getRepeatedValueMethodBuilder;
@@ -2388,6 +2523,60 @@ public abstract class GeneratedMessage extends AbstractMessage
// ---------------------------------------------------------------
+ /**
+ * Field accessor for string fields.
+ *
+ * <p>This class makes getFooBytes() and setFooBytes() available for
+ * reflection API so that reflection based serialize/parse functions can
+ * access the raw bytes of the field to preserve non-UTF8 bytes in the
+ * string.
+ *
+ * <p>This ensures the serialize/parse round-trip safety, which is important
+ * for servers which forward messages.
+ */
+ private static final class SingularStringFieldAccessor
+ extends SingularFieldAccessor {
+ SingularStringFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
+ getBytesMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "Bytes");
+ getBytesMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Bytes");
+ setBytesMethodBuilder = getMethodOrDie(builderClass,
+ "set" + camelCaseName + "Bytes", ByteString.class);
+ }
+
+ private final Method getBytesMethod;
+ private final Method getBytesMethodBuilder;
+ private final Method setBytesMethodBuilder;
+
+ @Override
+ public Object getRaw(final GeneratedMessage message) {
+ return invokeOrDie(getBytesMethod, message);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return invokeOrDie(getBytesMethodBuilder, builder);
+ }
+
+ @Override
+ public void set(GeneratedMessage.Builder builder, Object value) {
+ if (value instanceof ByteString) {
+ invokeOrDie(setBytesMethodBuilder, builder, value);
+ } else {
+ super.set(builder, value);
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------
+
private static final class SingularMessageFieldAccessor
extends SingularFieldAccessor {
SingularMessageFieldAccessor(
@@ -2395,7 +2584,8 @@ public abstract class GeneratedMessage extends AbstractMessage
final Class<? extends GeneratedMessage> messageClass,
final Class<? extends Builder> builderClass,
final String containingOneofCamelCaseName) {
- super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
newBuilderMethod = getMethodOrDie(type, "newBuilder");
getBuilderMethodBuilder =
@@ -2492,7 +2682,7 @@ public abstract class GeneratedMessage extends AbstractMessage
protected Object writeReplace() throws ObjectStreamException {
return new GeneratedMessageLite.SerializedForm(this);
}
-
+
/**
* Checks that the {@link Extension} is non-Lite and returns it as a
* {@link GeneratedExtension}.
@@ -2503,7 +2693,7 @@ public abstract class GeneratedMessage extends AbstractMessage
if (extension.isLite()) {
throw new IllegalArgumentException("Expected non-lite extension.");
}
-
+
return (Extension<MessageType, T>) extension;
}
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 4d25c077..6839c9dd 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -42,22 +42,58 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Lite version of {@link GeneratedMessage}.
*
* @author kenton@google.com Kenton Varda
*/
-public abstract class GeneratedMessageLite extends AbstractMessageLite
- implements Serializable {
+public abstract class GeneratedMessageLite<
+ MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+ BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
+ extends AbstractMessageLite
+ implements Serializable {
+
+ /**
+ * Holds all the {@link PrototypeHolder}s for loaded classes.
+ */
+ // TODO(dweis): Consider different concurrency values.
+ // TODO(dweis): This will prevent garbage collection of the class loader.
+ // Ideally we'd use something like ClassValue but that's Java 7 only.
+ private static final Map<Class<?>, PrototypeHolder<?, ?>> PROTOTYPE_MAP =
+ new ConcurrentHashMap<Class<?>, PrototypeHolder<?, ?>>();
+
+ // For use by generated code only.
+ protected static <
+ MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+ BuilderType extends GeneratedMessageLite.Builder<
+ MessageType, BuilderType>> void onLoad(Class<MessageType> clazz,
+ PrototypeHolder<MessageType, BuilderType> protoTypeHolder) {
+ PROTOTYPE_MAP.put(clazz, protoTypeHolder);
+ }
+
private static final long serialVersionUID = 1L;
/** For use by generated code only. */
protected UnknownFieldSetLite unknownFields;
- public Parser<? extends MessageLite> getParserForType() {
- throw new UnsupportedOperationException(
- "This is supposed to be overridden by subclasses.");
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ public final Parser<MessageType> getParserForType() {
+ return (Parser<MessageType>) PROTOTYPE_MAP
+ .get(getClass()).getParserForType();
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ public final MessageType getDefaultInstanceForType() {
+ return (MessageType) PROTOTYPE_MAP
+ .get(getClass()).getDefaultInstanceForType();
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ public final BuilderType newBuilderForType() {
+ return (BuilderType) PROTOTYPE_MAP
+ .get(getClass()).newBuilderForType();
}
/**
@@ -73,10 +109,17 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
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;
+ }
+
@SuppressWarnings("unchecked")
- public abstract static class Builder<MessageType extends GeneratedMessageLite,
- BuilderType extends Builder>
- extends AbstractMessageLite.Builder<BuilderType> {
+ public abstract static class Builder<
+ MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+ BuilderType extends Builder<MessageType, BuilderType>>
+ extends AbstractMessageLite.Builder<BuilderType> {
private final MessageType defaultInstance;
@@ -88,6 +131,12 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
this.defaultInstance = defaultInstance;
}
+ // The default behavior. If a message has required fields in its subtree,
+ // the generated code will override.
+ public boolean isInitialized() {
+ return true;
+ }
+
//@Override (Java 1.6 override semantics, but we must support 1.5)
public BuilderType clear() {
unknownFields = UnknownFieldSetLite.getDefaultInstance();
@@ -174,7 +223,9 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
* Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}.
*/
public interface ExtendableMessageOrBuilder<
- MessageType extends ExtendableMessage> extends MessageLiteOrBuilder {
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends MessageLiteOrBuilder {
/** Check if a singular extension is present. */
<Type> boolean hasExtension(
@@ -197,16 +248,30 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
* Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
*/
public abstract static class ExtendableMessage<
- MessageType extends ExtendableMessage<MessageType>>
- extends GeneratedMessageLite
- implements ExtendableMessageOrBuilder<MessageType> {
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends GeneratedMessageLite<MessageType, BuilderType>
+ implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
/**
* Represents the set of extensions on this message. For use by generated
* code only.
*/
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);
+ }
+
+ return memoizedIsInitialized == 1;
+ }
+
private void verifyExtensionContainingType(
final GeneratedExtension<MessageType, ?> extension) {
if (extension.getContainingTypeDefaultInstance() !=
@@ -349,10 +414,10 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
*/
@SuppressWarnings("unchecked")
public abstract static class ExtendableBuilder<
- MessageType extends ExtendableMessage<MessageType>,
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
extends Builder<MessageType, BuilderType>
- implements ExtendableMessageOrBuilder<MessageType> {
+ implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
protected ExtendableBuilder(MessageType defaultInstance) {
super(defaultInstance);
}
@@ -360,6 +425,12 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
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();
+ }
+
// For immutable message conversion.
void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) {
this.extensions = extensions;
@@ -991,7 +1062,10 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
* Checks that the {@link Extension} is Lite and returns it as a
* {@link GeneratedExtension}.
*/
- private static <MessageType extends ExtendableMessage<MessageType>, T>
+ private static <
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>,
+ T>
GeneratedExtension<MessageType, T> checkIsLite(
ExtensionLite<MessageType, T> extension) {
if (!extension.isLite()) {
@@ -1000,4 +1074,43 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite
return (GeneratedExtension<MessageType, T>) extension;
}
+
+ /**
+ * Represents the state needed to implement *ForType methods. Generated code
+ * must provide a static singleton instance by adding it with
+ * {@link GeneratedMessageLite#onLoad(Class, PrototypeHolder)} on class load.
+ * <ul>
+ * <li>{@link #getDefaultInstanceForType()}
+ * <li>{@link #getParserForType()}
+ * <li>{@link #newBuilderForType()}
+ * </ul>
+ * This allows us to trade three generated methods for a static Map.
+ */
+ protected static class PrototypeHolder<
+ MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+ BuilderType extends GeneratedMessageLite.Builder<
+ MessageType, BuilderType>> {
+
+ private final MessageType defaultInstance;
+ private final Parser<MessageType> parser;
+
+ public PrototypeHolder(
+ MessageType defaultInstance, Parser<MessageType> parser) {
+ this.defaultInstance = defaultInstance;
+ this.parser = parser;
+ }
+
+ public MessageType getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ public Parser<MessageType> getParserForType() {
+ return parser;
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ public BuilderType newBuilderForType() {
+ return (BuilderType) defaultInstance.toBuilder();
+ }
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/src/main/java/com/google/protobuf/LazyFieldLite.java
index 1fc80e87..eea1fe3c 100644
--- a/java/src/main/java/com/google/protobuf/LazyFieldLite.java
+++ b/java/src/main/java/com/google/protobuf/LazyFieldLite.java
@@ -30,8 +30,6 @@
package com.google.protobuf;
-import java.io.IOException;
-
/**
* LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores
* the message in a ByteString initially and then parse it on-demand.
@@ -44,40 +42,102 @@ import java.io.IOException;
* @author xiangl@google.com (Xiang Li)
*/
public class LazyFieldLite {
- private ByteString bytes;
+ private static final ExtensionRegistryLite EMPTY_REGISTRY =
+ ExtensionRegistryLite.getEmptyRegistry();
+
+ /**
+ * A delayed-parsed version of the bytes. When this is non-null then {@code extensionRegistry } is
+ * also non-null and {@code value} and {@code memoizedBytes} are null.
+ */
+ private ByteString delayedBytes;
+
+ /**
+ * An {@code ExtensionRegistryLite} for parsing bytes. It is non-null on a best-effort basis. It
+ * is only guaranteed to be non-null if this message was initialized using bytes and an
+ * {@code ExtensionRegistry}. If it directly had a value set then it will be null, unless it has
+ * been merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}.
+ */
private ExtensionRegistryLite extensionRegistry;
- private volatile boolean isDirty = false;
+ /**
+ * The parsed value. When this is non-null then {@code delayedBytes} will be null.
+ */
protected volatile MessageLite value;
+ /**
+ * The memoized bytes for {@code value}. Will be null when {@code value} is null.
+ */
+ private volatile ByteString memoizedBytes;
+
+ /**
+ * Constructs a LazyFieldLite with bytes that will be parsed lazily.
+ */
public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+ checkArguments(extensionRegistry, bytes);
this.extensionRegistry = extensionRegistry;
- this.bytes = bytes;
+ this.delayedBytes = bytes;
}
+ /**
+ * Constructs a LazyFieldLite with no contents, and no ability to parse extensions.
+ */
public LazyFieldLite() {
}
+ /**
+ * Constructs a LazyFieldLite instance with a value. The LazyFieldLite may not be able to parse
+ * the extensions in the value as it has no ExtensionRegistry.
+ */
public static LazyFieldLite fromValue(MessageLite value) {
LazyFieldLite lf = new LazyFieldLite();
lf.setValue(value);
return lf;
}
+ /**
+ * Determines whether this LazyFieldLite instance represents the default instance of this type.
+ */
public boolean containsDefaultInstance() {
- return value == null && bytes == null;
+ return memoizedBytes == ByteString.EMPTY
+ || value == null && (delayedBytes == null || delayedBytes == ByteString.EMPTY);
}
+ /**
+ * Clears the value state of this instance.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
public void clear() {
- bytes = null;
+ // Don't clear the ExtensionRegistry. It might prove useful later on when merging in another
+ // value, but there is no guarantee that it will contain all extensions that were directly set
+ // on the values that need to be merged.
+ delayedBytes = null;
value = null;
- extensionRegistry = null;
- isDirty = true;
+ memoizedBytes = null;
+ }
+
+ /**
+ * Overrides the contents of this LazyField.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public void set(LazyFieldLite other) {
+ this.delayedBytes = other.delayedBytes;
+ this.value = other.value;
+ this.memoizedBytes = other.memoizedBytes;
+ // If the other LazyFieldLite was created by directly setting the value rather than first by
+ // parsing, then it will not have an extensionRegistry. In this case we hold on to the existing
+ // extensionRegistry, which has no guarantees that it has all the extensions that will be
+ // directly set on the value.
+ if (other.extensionRegistry != null) {
+ this.extensionRegistry = other.extensionRegistry;
+ }
}
/**
- * Returns message instance. At first time, serialized data is parsed by
- * {@code defaultInstance.getParserForType()}.
+ * Returns message instance. It may do some thread-safe delayed parsing of bytes.
*
* @param defaultInstance its message's default instance. It's also used to get parser for the
* message type.
@@ -88,38 +148,109 @@ public class LazyFieldLite {
}
/**
- * LazyField is not thread-safe for write access. Synchronizations are needed
+ * Sets the value of the instance and returns the old value without delay parsing anything.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
* under read/write situations.
*/
public MessageLite setValue(MessageLite value) {
MessageLite originalValue = this.value;
+ this.delayedBytes = null;
+ this.memoizedBytes = null;
this.value = value;
- bytes = null;
- isDirty = true;
return originalValue;
}
- public void merge(LazyFieldLite value) {
- if (value.containsDefaultInstance()) {
+ /**
+ * Merges another instance's contents. In some cases may drop some extensions if both fields
+ * contain data. If the other field has an {@code ExtensionRegistry} but this does not, then this
+ * field will copy over that {@code ExtensionRegistry}.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public void merge(LazyFieldLite other) {
+ if (other.containsDefaultInstance()) {
return;
}
- if (bytes == null) {
- this.bytes = value.bytes;
+ if (this.containsDefaultInstance()) {
+ set(other);
+ return;
+ }
+
+ // If the other field has an extension registry but this does not, copy over the other extension
+ // registry.
+ if (this.extensionRegistry == null) {
+ this.extensionRegistry = other.extensionRegistry;
+ }
+
+ // In the case that both of them are not parsed we simply concatenate the bytes to save time. In
+ // the (probably rare) case that they have different extension registries there is a chance that
+ // some of the extensions may be dropped, but the tradeoff of making this operation fast seems
+ // to outway the benefits of combining the extension registries, which is not normally done for
+ // lite protos anyways.
+ if (this.delayedBytes != null && other.delayedBytes != null) {
+ this.delayedBytes = this.delayedBytes.concat(other.delayedBytes);
+ return;
+ }
+
+ // At least one is parsed and both contain data. We won't drop any extensions here directly, but
+ // in the case that the extension registries are not the same then we might in the future if we
+ // need to serialze and parse a message again.
+ if (this.value == null && other.value != null) {
+ setValue(mergeValueAndBytes(other.value, this.delayedBytes, this.extensionRegistry));
+ return;
+ } else if (this.value != null && other.value == null) {
+ setValue(mergeValueAndBytes(this.value, other.delayedBytes, other.extensionRegistry));
+ return;
+ }
+
+ // At this point we have two fully parsed messages. We can't merge directly from one to the
+ // other because only generated builder code contains methods to mergeFrom another parsed
+ // message. We have to serialize one instance and then merge the bytes into the other. This may
+ // drop extensions from one of the messages if one of the values had an extension set on it
+ // directly.
+ //
+ // To mitigate this we prefer serializing a message that has an extension registry, and
+ // therefore a chance that all extensions set on it are in that registry.
+ //
+ // NOTE: The check for other.extensionRegistry not being null must come first because at this
+ // point in time if other.extensionRegistry is not null then this.extensionRegistry will not be
+ // null either.
+ if (other.extensionRegistry != null) {
+ setValue(mergeValueAndBytes(this.value, other.toByteString(), other.extensionRegistry));
+ return;
+ } else if (this.extensionRegistry != null) {
+ setValue(mergeValueAndBytes(other.value, this.toByteString(), this.extensionRegistry));
+ return;
} else {
- this.bytes.concat(value.toByteString());
+ // All extensions from the other message will be dropped because we have no registry.
+ setValue(mergeValueAndBytes(this.value, other.toByteString(), EMPTY_REGISTRY));
+ return;
}
- isDirty = false;
}
- public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) {
- this.bytes = bytes;
- this.extensionRegistry = extensionRegistry;
- isDirty = false;
+ private static MessageLite mergeValueAndBytes(
+ MessageLite value, ByteString otherBytes, ExtensionRegistryLite extensionRegistry) {
+ try {
+ return value.toBuilder().mergeFrom(otherBytes, extensionRegistry).build();
+ } catch (InvalidProtocolBufferException e) {
+ // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto
+ // was invalid.
+ return value;
+ }
}
- public ExtensionRegistryLite getExtensionRegistry() {
- return extensionRegistry;
+ /**
+ * Sets this field with bytes to delay-parse.
+ */
+ public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) {
+ checkArguments(extensionRegistry, bytes);
+ this.delayedBytes = bytes;
+ this.extensionRegistry = extensionRegistry;
+ this.value = null;
+ this.memoizedBytes = null;
}
/**
@@ -128,30 +259,43 @@ public class LazyFieldLite {
* parsed. Be careful when using this method.
*/
public int getSerializedSize() {
- if (isDirty) {
+ if (delayedBytes != null) {
+ return delayedBytes.size();
+ } else if (memoizedBytes != null) {
+ return memoizedBytes.size();
+ } else if (value != null) {
return value.getSerializedSize();
+ } else {
+ return 0;
}
- return bytes.size();
}
+ /**
+ * Returns a BytesString for this field in a thread-safe way.
+ */
public ByteString toByteString() {
- if (!isDirty) {
- return bytes;
+ if (delayedBytes != null) {
+ return delayedBytes;
+ }
+ if (memoizedBytes != null) {
+ return memoizedBytes;
}
synchronized (this) {
- if (!isDirty) {
- return bytes;
+ if (memoizedBytes != null) {
+ return memoizedBytes;
}
if (value == null) {
- bytes = ByteString.EMPTY;
+ memoizedBytes = ByteString.EMPTY;
} else {
- bytes = value.toByteString();
+ memoizedBytes = value.toByteString();
}
- isDirty = false;
- return bytes;
+ return memoizedBytes;
}
}
+ /**
+ * Might lazily parse the bytes that were previously passed in. Is thread-safe.
+ */
protected void ensureInitialized(MessageLite defaultInstance) {
if (value != null) {
return;
@@ -161,16 +305,35 @@ public class LazyFieldLite {
return;
}
try {
- if (bytes != null) {
- value = defaultInstance.getParserForType()
- .parseFrom(bytes, extensionRegistry);
+ if (delayedBytes != null) {
+ // The extensionRegistry shouldn't be null here since we have delayedBytes.
+ MessageLite parsedValue = defaultInstance.getParserForType()
+ .parseFrom(delayedBytes, extensionRegistry);
+ this.value = parsedValue;
+ this.memoizedBytes = delayedBytes;
+ this.delayedBytes = null;
} else {
- value = defaultInstance;
+ this.value = defaultInstance;
+ this.memoizedBytes = ByteString.EMPTY;
+ this.delayedBytes = null;
}
- } catch (IOException e) {
- // TODO(xiangl): Refactory the API to support the exception thrown from
- // lazily load messages.
+ } catch (InvalidProtocolBufferException e) {
+ // Nothing is logged and no exceptions are thrown. Clients will be unaware that this proto
+ // was invalid.
+ this.value = defaultInstance;
+ this.memoizedBytes = ByteString.EMPTY;
+ this.delayedBytes = null;
}
}
}
+
+
+ private static void checkArguments(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+ if (extensionRegistry == null) {
+ throw new NullPointerException("found null ExtensionRegistry");
+ }
+ if (bytes == null) {
+ throw new NullPointerException("found null ByteString");
+ }
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/LiteralByteString.java b/java/src/main/java/com/google/protobuf/LiteralByteString.java
index 767b9f35..6893ddf1 100644
--- a/java/src/main/java/com/google/protobuf/LiteralByteString.java
+++ b/java/src/main/java/com/google/protobuf/LiteralByteString.java
@@ -154,7 +154,11 @@ class LiteralByteString extends ByteString {
@Override
public String toString(String charsetName)
throws UnsupportedEncodingException {
- return new String(bytes, getOffsetIntoBytes(), size(), charsetName);
+ // Optimize for empty strings, but ensure we don't silently ignore invalid
+ // encodings.
+ return size() == 0 && UTF_8.equals(charsetName)
+ ? ""
+ : new String(bytes, getOffsetIntoBytes(), size(), charsetName);
}
// =================================================================
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index 5c75b58b..fa0265e2 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -163,7 +163,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
* field builder, which will then be nested into its parent builder.
* <p>
* NOTE: implementations that do not support nested builders will throw
- * <code>UnsupportedException</code>.
+ * <code>UnsupportedOperationException</code>.
*/
Builder getFieldBuilder(Descriptors.FieldDescriptor field);
@@ -181,7 +181,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
* field builder, which will then be nested into its parent builder.
* <p>
* NOTE: implementations that do not support nested builders will throw
- * <code>UnsupportedException</code>.
+ * <code>UnsupportedOperationException</code>.
*/
Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field,
int index);
diff --git a/java/src/main/java/com/google/protobuf/MessageReflection.java b/java/src/main/java/com/google/protobuf/MessageReflection.java
index 06e3c99b..de4bfd3e 100644
--- a/java/src/main/java/com/google/protobuf/MessageReflection.java
+++ b/java/src/main/java/com/google/protobuf/MessageReflection.java
@@ -45,13 +45,14 @@ import java.util.TreeMap;
*/
class MessageReflection {
- static void writeMessageTo(Message message, CodedOutputStream output,
+ static void writeMessageTo(
+ Message message,
+ Map<FieldDescriptor, Object> fields,
+ CodedOutputStream output,
boolean alwaysWriteRequiredFields)
throws IOException {
final boolean isMessageSet =
message.getDescriptorForType().getOptions().getMessageSetWireFormat();
-
- Map<FieldDescriptor, Object> fields = message.getAllFields();
if (alwaysWriteRequiredFields) {
fields = new TreeMap<FieldDescriptor, Object>(fields);
for (final FieldDescriptor field :
@@ -82,13 +83,15 @@ class MessageReflection {
}
}
- static int getSerializedSize(Message message) {
+ static int getSerializedSize(
+ Message message,
+ Map<FieldDescriptor, Object> fields) {
int size = 0;
final boolean isMessageSet =
message.getDescriptorForType().getOptions().getMessageSetWireFormat();
for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
- message.getAllFields().entrySet()) {
+ fields.entrySet()) {
final Descriptors.FieldDescriptor field = entry.getKey();
final Object value = entry.getValue();
if (isMessageSet && field.isExtension() &&
@@ -340,14 +343,12 @@ class MessageReflection {
ByteString bytes, ExtensionRegistryLite registry,
Descriptors.FieldDescriptor descriptor, Message defaultInstance)
throws IOException;
-
+
/**
- * Read a primitive field from input. Note that builders and mutable
- * messages may use different Java types to represent a primtive field.
+ * Returns the UTF8 validation level for the field.
*/
- Object readPrimitiveField(
- CodedInputStream input, WireFormat.FieldType type,
- boolean checkUtf8) throws IOException;
+ WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor
+ descriptor);
/**
* Returns a new merge target for a sub-field. When defaultInstance is
@@ -513,11 +514,18 @@ class MessageReflection {
return new BuilderAdapter(builder.newBuilderForField(field));
}
}
-
- public Object readPrimitiveField(
- CodedInputStream input, WireFormat.FieldType type,
- boolean checkUtf8) throws IOException {
- return FieldSet.readPrimitiveField(input, type, checkUtf8);
+
+ public WireFormat.Utf8Validation
+ getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+ if (descriptor.needsUtf8Check()) {
+ return WireFormat.Utf8Validation.STRICT;
+ }
+ // TODO(liujisi): support lazy strings for repeated fields.
+ if (!descriptor.isRepeated()
+ && builder instanceof GeneratedMessage.Builder) {
+ return WireFormat.Utf8Validation.LAZY;
+ }
+ return WireFormat.Utf8Validation.LOOSE;
}
public Object finish() {
@@ -651,11 +659,14 @@ class MessageReflection {
throw new UnsupportedOperationException(
"newMergeTargetForField() called on FieldSet object");
}
-
- public Object readPrimitiveField(
- CodedInputStream input, WireFormat.FieldType type,
- boolean checkUtf8) throws IOException {
- return FieldSet.readPrimitiveField(input, type, checkUtf8);
+
+ public WireFormat.Utf8Validation
+ getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+ if (descriptor.needsUtf8Check()) {
+ return WireFormat.Utf8Validation.STRICT;
+ }
+ // TODO(liujisi): support lazy strings for ExtesnsionSet.
+ return WireFormat.Utf8Validation.LOOSE;
}
public Object finish() {
@@ -767,8 +778,8 @@ class MessageReflection {
}
} else {
while (input.getBytesUntilLimit() > 0) {
- final Object value =
- target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
+ final Object value = WireFormat.readPrimitiveField(
+ input, field.getLiteType(), target.getUtf8Validation(field));
target.addRepeatedField(field, value);
}
}
@@ -801,7 +812,8 @@ class MessageReflection {
}
break;
default:
- value = target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check());
+ value = WireFormat.readPrimitiveField(
+ input, field.getLiteType(), target.getUtf8Validation(field));
break;
}
diff --git a/java/src/main/java/com/google/protobuf/Parser.java b/java/src/main/java/com/google/protobuf/Parser.java
index f636014b..227c02b7 100644
--- a/java/src/main/java/com/google/protobuf/Parser.java
+++ b/java/src/main/java/com/google/protobuf/Parser.java
@@ -227,8 +227,8 @@ public interface Parser<MessageType> {
* {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write
* messages in this format.
*
- * @return True if successful, or false if the stream is at EOF when the
- * method starts. Any other error (including reaching EOF during
+ * @return Parsed message if successful, or null if the stream is at EOF when
+ * the method starts. Any other error (including reaching EOF during
* parsing) will cause an exception to be thrown.
*/
public MessageType parseDelimitedFrom(InputStream input)
diff --git a/java/src/main/java/com/google/protobuf/RopeByteString.java b/java/src/main/java/com/google/protobuf/RopeByteString.java
index fa23c9dd..168bcce2 100644
--- a/java/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/src/main/java/com/google/protobuf/RopeByteString.java
@@ -30,9 +30,9 @@
package com.google.protobuf;
-import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
@@ -420,7 +420,11 @@ class RopeByteString extends ByteString {
@Override
public String toString(String charsetName)
throws UnsupportedEncodingException {
- return new String(toByteArray(), charsetName);
+ // Optimize for empty strings, but ensure we don't silently ignore invalid
+ // encodings.
+ return size() == 0 && UTF_8.equals(charsetName)
+ ? ""
+ : new String(toByteArray(), charsetName);
}
// =================================================================
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java
index 4f6756ed..dd2b4600 100644
--- a/java/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/src/main/java/com/google/protobuf/TextFormat.java
@@ -409,9 +409,9 @@ public final class TextFormat {
case STRING:
generator.print("\"");
- generator.print(escapeNonAscii ?
- escapeText((String) value) :
- escapeDoubleQuotesAndBackslashes((String) value)
+ generator.print(escapeNonAscii
+ ? escapeText((String) value)
+ : escapeDoubleQuotesAndBackslashes((String) value)
.replace("\n", "\\n"));
generator.print("\"");
break;
@@ -730,8 +730,8 @@ public final class TextFormat {
}
final char c = currentToken.charAt(0);
- return ('0' <= c && c <= '9') ||
- c == '-' || c == '+';
+ return ('0' <= c && c <= '9')
+ || c == '-' || c == '+';
}
/**
@@ -749,10 +749,10 @@ public final class TextFormat {
public String consumeIdentifier() throws ParseException {
for (int i = 0; i < currentToken.length(); i++) {
final char c = currentToken.charAt(i);
- if (('a' <= c && c <= 'z') ||
- ('A' <= c && c <= 'Z') ||
- ('0' <= c && c <= '9') ||
- (c == '_') || (c == '.')) {
+ if (('a' <= c && c <= 'z')
+ || ('A' <= c && c <= 'Z')
+ || ('0' <= c && c <= '9')
+ || (c == '_') || (c == '.')) {
// OK
} else {
throw parseException(
@@ -941,14 +941,14 @@ public final class TextFormat {
* Otherwise, throw a {@link ParseException}.
*/
public boolean consumeBoolean() throws ParseException {
- if (currentToken.equals("true") ||
- currentToken.equals("t") ||
- currentToken.equals("1")) {
+ if (currentToken.equals("true")
+ || currentToken.equals("t")
+ || currentToken.equals("1")) {
nextToken();
return true;
- } else if (currentToken.equals("false") ||
- currentToken.equals("f") ||
- currentToken.equals("0")) {
+ } else if (currentToken.equals("false")
+ || currentToken.equals("f")
+ || currentToken.equals("0")) {
nextToken();
return false;
} else {
@@ -999,14 +999,15 @@ public final class TextFormat {
*/
private void consumeByteString(List<ByteString> list)
throws ParseException {
- final char quote = currentToken.length() > 0 ? currentToken.charAt(0)
- : '\0';
+ final char quote = currentToken.length() > 0
+ ? currentToken.charAt(0)
+ : '\0';
if (quote != '\"' && quote != '\'') {
throw parseException("Expected string.");
}
- if (currentToken.length() < 2 ||
- currentToken.charAt(currentToken.length() - 1) != quote) {
+ if (currentToken.length() < 2
+ || currentToken.charAt(currentToken.length() - 1) != quote) {
throw parseException("String missing ending quote.");
}
@@ -1340,8 +1341,8 @@ public final class TextFormat {
} else {
if (extension.descriptor.getContainingType() != type) {
throw tokenizer.parseExceptionPreviousToken(
- "Extension \"" + name + "\" does not extend message type \"" +
- type.getFullName() + "\".");
+ "Extension \"" + name + "\" does not extend message type \""
+ + type.getFullName() + "\".");
}
field = extension.descriptor;
}
@@ -1365,20 +1366,20 @@ public final class TextFormat {
}
}
// Again, special-case group names as described above.
- if (field != null && field.getType() == FieldDescriptor.Type.GROUP &&
- !field.getMessageType().getName().equals(name)) {
+ if (field != null && field.getType() == FieldDescriptor.Type.GROUP
+ && !field.getMessageType().getName().equals(name)) {
field = null;
}
if (field == null) {
if (!allowUnknownFields) {
throw tokenizer.parseExceptionPreviousToken(
- "Message type \"" + type.getFullName() +
- "\" has no field named \"" + name + "\".");
+ "Message type \"" + type.getFullName()
+ + "\" has no field named \"" + name + "\".");
} else {
logger.warning(
- "Message type \"" + type.getFullName() +
- "\" has no field named \"" + name + "\".");
+ "Message type \"" + type.getFullName()
+ + "\" has no field named \"" + name + "\".");
}
}
}
@@ -1391,8 +1392,9 @@ public final class TextFormat {
// start with "{" or "<" which indicates the beginning of a message body.
// If there is no ":" or there is a "{" or "<" after ":", this field has
// to be a message or the input is ill-formed.
- if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("{") &&
- !tokenizer.lookingAt("<")) {
+ if (tokenizer.tryConsume(":")
+ && !tokenizer.lookingAt("{")
+ && !tokenizer.lookingAt("<")) {
skipFieldValue(tokenizer);
} else {
skipFieldMessage(tokenizer);
@@ -1516,16 +1518,16 @@ public final class TextFormat {
value = enumType.findValueByNumber(number);
if (value == null) {
throw tokenizer.parseExceptionPreviousToken(
- "Enum type \"" + enumType.getFullName() +
- "\" has no value with number " + number + '.');
+ "Enum type \"" + enumType.getFullName()
+ + "\" has no value with number " + number + '.');
}
} else {
final String id = tokenizer.consumeIdentifier();
value = enumType.findValueByName(id);
if (value == null) {
throw tokenizer.parseExceptionPreviousToken(
- "Enum type \"" + enumType.getFullName() +
- "\" has no value named \"" + id + "\".");
+ "Enum type \"" + enumType.getFullName()
+ + "\" has no value named \"" + id + "\".");
}
}
@@ -1578,8 +1580,9 @@ public final class TextFormat {
// start with "{" or "<" which indicates the beginning of a message body.
// If there is no ":" or there is a "{" or "<" after ":", this field has
// to be a message or the input is ill-formed.
- if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("<") &&
- !tokenizer.lookingAt("{")) {
+ if (tokenizer.tryConsume(":")
+ && !tokenizer.lookingAt("<")
+ && !tokenizer.lookingAt("{")) {
skipFieldValue(tokenizer);
} else {
skipFieldMessage(tokenizer);
@@ -1617,11 +1620,11 @@ public final class TextFormat {
while (tokenizer.tryConsumeString()) {}
return;
}
- if (!tokenizer.tryConsumeIdentifier() && // includes enum & boolean
- !tokenizer.tryConsumeInt64() && // includes int32
- !tokenizer.tryConsumeUInt64() && // includes uint32
- !tokenizer.tryConsumeDouble() &&
- !tokenizer.tryConsumeFloat()) {
+ if (!tokenizer.tryConsumeIdentifier() // includes enum & boolean
+ && !tokenizer.tryConsumeInt64() // includes int32
+ && !tokenizer.tryConsumeUInt64() // includes uint32
+ && !tokenizer.tryConsumeDouble()
+ && !tokenizer.tryConsumeFloat()) {
throw tokenizer.parseException(
"Invalid field value: " + tokenizer.currentToken);
}
@@ -1647,19 +1650,19 @@ public final class TextFormat {
* which no defined short-hand escape sequence is defined will be escaped
* using 3-digit octal sequences.
*/
- private static String escapeBytes(final ByteSequence input) {
+ public static String escapeBytes(final ByteSequence input) {
final StringBuilder builder = new StringBuilder(input.size());
for (int i = 0; i < input.size(); i++) {
final byte b = input.byteAt(i);
switch (b) {
// Java does not recognize \a or \v, apparently.
- case 0x07: builder.append("\\a" ); break;
- case '\b': builder.append("\\b" ); break;
- case '\f': builder.append("\\f" ); break;
- case '\n': builder.append("\\n" ); break;
- case '\r': builder.append("\\r" ); break;
- case '\t': builder.append("\\t" ); break;
- case 0x0b: builder.append("\\v" ); break;
+ case 0x07: builder.append("\\a"); break;
+ case '\b': builder.append("\\b"); break;
+ case '\f': builder.append("\\f"); break;
+ case '\n': builder.append("\\n"); break;
+ case '\r': builder.append("\\r"); break;
+ case '\t': builder.append("\\t"); break;
+ case 0x0b: builder.append("\\v"); break;
case '\\': builder.append("\\\\"); break;
case '\'': builder.append("\\\'"); break;
case '"' : builder.append("\\\""); break;
@@ -1688,11 +1691,13 @@ public final class TextFormat {
* which no defined short-hand escape sequence is defined will be escaped
* using 3-digit octal sequences.
*/
- static String escapeBytes(final ByteString input) {
+ public static String escapeBytes(final ByteString input) {
return escapeBytes(new ByteSequence() {
+ @Override
public int size() {
return input.size();
}
+ @Override
public byte byteAt(int offset) {
return input.byteAt(offset);
}
@@ -1702,11 +1707,13 @@ public final class TextFormat {
/**
* Like {@link #escapeBytes(ByteString)}, but used for byte array.
*/
- static String escapeBytes(final byte[] input) {
+ public static String escapeBytes(final byte[] input) {
return escapeBytes(new ByteSequence() {
+ @Override
public int size() {
return input.length;
}
+ @Override
public byte byteAt(int offset) {
return input[offset];
}
@@ -1749,7 +1756,7 @@ public final class TextFormat {
code = code * 8 + digitValue(input.byteAt(i));
}
// TODO: Check that 0 <= code && code <= 0xFF.
- result[pos++] = (byte)code;
+ result[pos++] = (byte) code;
} else {
switch (c) {
case 'a' : result[pos++] = 0x07; break;
@@ -1777,12 +1784,12 @@ public final class TextFormat {
++i;
code = code * 16 + digitValue(input.byteAt(i));
}
- result[pos++] = (byte)code;
+ result[pos++] = (byte) code;
break;
default:
throw new InvalidEscapeSequenceException(
- "Invalid escape sequence: '\\" + (char)c + '\'');
+ "Invalid escape sequence: '\\" + (char) c + '\'');
}
}
} else {
@@ -1841,9 +1848,9 @@ public final class TextFormat {
/** Is this a hex digit? */
private static boolean isHex(final byte c) {
- return ('0' <= c && c <= '9') ||
- ('a' <= c && c <= 'f') ||
- ('A' <= c && c <= 'F');
+ return ('0' <= c && c <= '9')
+ || ('a' <= c && c <= 'f')
+ || ('A' <= c && c <= 'F');
}
/**
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index eba2528e..ba83b666 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import java.io.IOException;
+
/**
* This class is used internally by the Protocol Buffer library and generated
* message implementations. It is public only because those generated messages
@@ -160,4 +162,84 @@ public final class WireFormat {
makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT);
static final int MESSAGE_SET_MESSAGE_TAG =
makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED);
+
+ /**
+ * Validation level for handling incoming string field data which potentially
+ * contain non-UTF8 bytes.
+ */
+ enum Utf8Validation {
+ /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */
+ LOOSE {
+ Object readString(CodedInputStream input) throws IOException {
+ return input.readString();
+ }
+ },
+ /** Eagerly parses to String; throws an IOException on invalid bytes. */
+ STRICT {
+ Object readString(CodedInputStream input) throws IOException {
+ return input.readStringRequireUtf8();
+ }
+ },
+ /** Keep data as ByteString; validation/conversion to String is lazy. */
+ LAZY {
+ Object readString(CodedInputStream input) throws IOException {
+ return input.readBytes();
+ }
+ };
+
+ /** Read a string field from the input with the proper UTF8 validation. */
+ abstract Object readString(CodedInputStream input) throws IOException;
+ }
+
+ /**
+ * Read a field of any primitive type for immutable messages from a
+ * CodedInputStream. Enums, groups, and embedded messages are not handled by
+ * this method.
+ *
+ * @param input The stream from which to read.
+ * @param type Declared type of the field.
+ * @param utf8Validation Different string UTF8 validation level for handling
+ * string fields.
+ * @return An object representing the field's value, of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ static Object readPrimitiveField(
+ CodedInputStream input,
+ FieldType type,
+ Utf8Validation utf8Validation) throws IOException {
+ switch (type) {
+ case DOUBLE : return input.readDouble ();
+ case FLOAT : return input.readFloat ();
+ case INT64 : return input.readInt64 ();
+ case UINT64 : return input.readUInt64 ();
+ case INT32 : return input.readInt32 ();
+ case FIXED64 : return input.readFixed64 ();
+ case FIXED32 : return input.readFixed32 ();
+ case BOOL : return input.readBool ();
+ case BYTES : return input.readBytes ();
+ case UINT32 : return input.readUInt32 ();
+ case SFIXED32: return input.readSFixed32();
+ case SFIXED64: return input.readSFixed64();
+ case SINT32 : return input.readSInt32 ();
+ case SINT64 : return input.readSInt64 ();
+
+ case STRING : return utf8Validation.readString(input);
+ case GROUP:
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle nested groups.");
+ case MESSAGE:
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle embedded messages.");
+ case ENUM:
+ // We don't handle enums because we don't know what to do if the
+ // value is not recognized.
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle enums.");
+ }
+
+ throw new RuntimeException(
+ "There is no way to get here, but the compiler thinks otherwise.");
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 41ed7bd0..2bd8d1a9 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -56,6 +56,7 @@ import protobuf_unittest.UnittestProto;
import protobuf_unittest.UnittestProto.ForeignEnum;
import protobuf_unittest.UnittestProto.ForeignMessage;
import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
@@ -1510,6 +1511,17 @@ public class GeneratedMessageTest extends TestCase {
}
}
+ public void testOneofNestedBuilderOnChangePropagation() {
+ NestedTestAllTypes.Builder parentBuilder = NestedTestAllTypes.newBuilder();
+ TestAllTypes.Builder builder = parentBuilder.getPayloadBuilder();
+ builder.getOneofNestedMessageBuilder();
+ assertTrue(builder.hasOneofNestedMessage());
+ assertTrue(parentBuilder.hasPayload());
+ NestedTestAllTypes message = parentBuilder.build();
+ assertTrue(message.hasPayload());
+ assertTrue(message.getPayload().hasOneofNestedMessage());
+ }
+
public void testGetRepeatedFieldBuilder() {
Descriptor descriptor = TestAllTypes.getDescriptor();
diff --git a/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
index e67c6d27..211b5697 100644
--- a/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
@@ -30,6 +30,9 @@
package com.google.protobuf;
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+
import protobuf_unittest.UnittestProto.TestAllExtensions;
import protobuf_unittest.UnittestProto.TestAllTypes;
@@ -111,12 +114,146 @@ public class LazyFieldLiteTest extends TestCase {
assertNotEqual(message.toByteString(), lazyField.toByteString());
}
+ public void testMergeExtensions() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite original = createLazyFieldLiteFromMessage(message);
+ LazyFieldLite merged = new LazyFieldLite();
+ merged.merge(original);
+ TestAllExtensions value = (TestAllExtensions) merged.getValue(
+ TestAllExtensions.getDefaultInstance());
+ assertEquals(message, value);
+ }
+
+ public void testEmptyLazyField() throws Exception {
+ LazyFieldLite field = new LazyFieldLite();
+ assertEquals(0, field.getSerializedSize());
+ assertEquals(ByteString.EMPTY, field.toByteString());
+ }
+
+ public void testInvalidProto() throws Exception {
+ // Silently fails and uses the default instance.
+ LazyFieldLite field = new LazyFieldLite(
+ TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+ assertEquals(
+ TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance()));
+ assertEquals(0, field.getSerializedSize());
+ assertEquals(ByteString.EMPTY, field.toByteString());
+ }
+
+ public void testMergeBeforeParsing() throws Exception {
+ TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ LazyFieldLite field1 = createLazyFieldLiteFromMessage(message1);
+ TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+ LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+
+ field1.merge(field2);
+ TestAllTypes expected =
+ TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeOneNotParsed() throws Exception {
+ // Test a few different paths that involve one message that was not parsed.
+ TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+ TestAllTypes expected =
+ TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+
+ LazyFieldLite field1 = LazyFieldLite.fromValue(message1);
+ field1.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
+ LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+ field1.merge(field2);
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+
+ // Now reverse which one is parsed first.
+ field1 = LazyFieldLite.fromValue(message1);
+ field2 = createLazyFieldLiteFromMessage(message2);
+ field2.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
+ field1.merge(field2);
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeInvalid() throws Exception {
+ // Test a few different paths that involve one message that was not parsed.
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ LazyFieldLite valid = LazyFieldLite.fromValue(message);
+ LazyFieldLite invalid = new LazyFieldLite(
+ TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+ invalid.merge(valid);
+
+ // We swallow the exception and just use the set field.
+ assertEquals(message, invalid.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeKeepsExtensionsWhenPossible() throws Exception {
+ // In this test we attempt to only use the empty registry, which will strip out all extensions
+ // when serializing and then parsing. We verify that each code path will attempt to not
+ // serialize and parse a message that was set directly without going through the
+ // extensionRegistry.
+ TestAllExtensions messageWithExtensions =
+ TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 42).build();
+ TestAllExtensions emptyMessage = TestAllExtensions.newBuilder().build();
+
+ ExtensionRegistryLite emptyRegistry = ExtensionRegistryLite.getEmptyRegistry();
+
+ LazyFieldLite field = LazyFieldLite.fromValue(messageWithExtensions);
+ field.merge(createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage));
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // Now reverse the order of the merging.
+ field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ field.merge(LazyFieldLite.fromValue(messageWithExtensions));
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // Now try parsing the empty field first.
+ field = LazyFieldLite.fromValue(messageWithExtensions);
+ LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ other.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
+ field.merge(other);
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // And again reverse.
+ field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ field.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
+ other = LazyFieldLite.fromValue(messageWithExtensions);
+ field.merge(other);
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+ }
+
+ public void testMergeMightLoseExtensions() throws Exception {
+ // Test that we don't know about the extensions when parsing.
+ TestAllExtensions message1 =
+ TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 1).build();
+ TestAllExtensions message2 =
+ TestAllExtensions.newBuilder().setExtension(optionalInt64Extension, 2L).build();
+
+ LazyFieldLite field = LazyFieldLite.fromValue(message1);
+ field.merge(LazyFieldLite.fromValue(message2));
+
+ // We lose the extensions from message 2 because we have to serialize it and then parse it
+ // again, using the empty registry this time.
+ TestAllExtensions value =
+ (TestAllExtensions) field.getValue(TestAllExtensions.getDefaultInstance());
+ assertTrue(value.hasExtension(optionalInt32Extension));
+ assertEquals(Integer.valueOf(1), value.getExtension(optionalInt32Extension));
+ assertFalse(value.hasExtension(optionalInt64Extension));
+
+ // The field is still there, it is just unknown.
+ assertTrue(value.getUnknownFields()
+ .hasField(optionalInt64Extension.getDescriptor().getNumber()));
+ }
+
// Help methods.
private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) {
+ return createLazyFieldLiteFromMessage(TestUtil.getExtensionRegistry(), message);
+ }
+
+ private LazyFieldLite createLazyFieldLiteFromMessage(
+ ExtensionRegistryLite extensionRegistry, MessageLite message) {
ByteString bytes = message.toByteString();
- return new LazyFieldLite(TestUtil.getExtensionRegistry(), bytes);
+ return new LazyFieldLite(extensionRegistry, bytes);
}
private void changeValue(LazyFieldLite lazyField) {
diff --git a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
index 9de794fe..afe0fffd 100644
--- a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
@@ -30,6 +30,7 @@
package com.google.protobuf;
+import protobuf_unittest.LazyFieldsLite.LazyExtension;
import protobuf_unittest.LazyFieldsLite.LazyInnerMessageLite;
import protobuf_unittest.LazyFieldsLite.LazyMessageLite;
import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite;
@@ -285,4 +286,22 @@ public class LazyMessageLiteTest extends TestCase {
assertEquals(bytes, deserialized.toByteString());
}
+
+ public void testExtensions() throws Exception {
+ LazyInnerMessageLite.Builder innerBuilder = LazyInnerMessageLite.newBuilder();
+ innerBuilder.setExtension(
+ LazyExtension.extension, LazyExtension.newBuilder()
+ .setName("name").build());
+ assertTrue(innerBuilder.hasExtension(LazyExtension.extension));
+ assertEquals("name", innerBuilder.getExtension(LazyExtension.extension).getName());
+
+ LazyInnerMessageLite innerMessage = innerBuilder.build();
+ assertTrue(innerMessage.hasExtension(LazyExtension.extension));
+ assertEquals("name", innerMessage.getExtension(LazyExtension.extension).getName());
+
+ LazyMessageLite lite = LazyMessageLite.newBuilder()
+ .setInner(innerMessage).build();
+ assertTrue(lite.getInner().hasExtension(LazyExtension.extension));
+ assertEquals("name", lite.getInner().getExtension(LazyExtension.extension).getName());
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
index ff39ca3f..046832de 100644
--- a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -289,7 +289,6 @@ public class LiteralByteStringTest extends TestCase {
assertEquals("Output.reset() resets the output", 0, output.size());
assertEquals("Output.reset() resets the output",
ByteString.EMPTY, output.toByteString());
-
}
public void testToString() throws UnsupportedEncodingException {
@@ -299,6 +298,27 @@ public class LiteralByteStringTest extends TestCase {
assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
}
+ public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException{
+ assertSame(classUnderTest + " must be the same string references",
+ ByteString.EMPTY.toString(UTF_8), new LiteralByteString(new byte[]{}).toString(UTF_8));
+ }
+
+ public void testToString_raisesException() throws UnsupportedEncodingException{
+ try {
+ ByteString.EMPTY.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ new LiteralByteString(referenceBytes).toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
public void testEquals() {
assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
@@ -311,7 +331,7 @@ public class LiteralByteStringTest extends TestCase {
byte[] mungedBytes = new byte[referenceBytes.length];
System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length);
- mungedBytes[mungedBytes.length - 5] ^= 0xFF;
+ mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
assertFalse(classUnderTest + " must not equal every string with the same length",
stringUnderTest.equals(new LiteralByteString(mungedBytes)));
}
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
index 33ba7150..78cba1b4 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -34,6 +34,7 @@ import com.google.protobuf.Descriptors.FieldDescriptor;
import map_test.MapForProto2TestProto.TestMap;
import map_test.MapForProto2TestProto.TestMap.MessageValue;
import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields;
+import map_test.MapForProto2TestProto.TestRecursiveMap;
import map_test.MapForProto2TestProto.TestUnknownEnumValue;
import junit.framework.TestCase;
@@ -499,4 +500,17 @@ public class MapForProto2Test extends TestCase {
message = builder.build();
assertTrue(message.isInitialized());
}
+
+ public void testRecursiveMap() throws Exception {
+ TestRecursiveMap.Builder builder = TestRecursiveMap.newBuilder();
+ builder.getMutableRecursiveMapField().put(
+ 1, TestRecursiveMap.newBuilder().setValue(2).build());
+ builder.getMutableRecursiveMapField().put(
+ 3, TestRecursiveMap.newBuilder().setValue(4).build());
+ ByteString data = builder.build().toByteString();
+
+ TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
+ assertEquals(2, message.getRecursiveMapField().get(1).getValue());
+ assertEquals(4, message.getRecursiveMapField().get(3).getValue());
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java
index 9a25e302..b8e67b7c 100644
--- a/java/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/src/test/java/com/google/protobuf/MapTest.java
@@ -57,22 +57,22 @@ public class MapTest extends TestCase {
builder.getMutableInt32ToStringField().put(1, "11");
builder.getMutableInt32ToStringField().put(2, "22");
builder.getMutableInt32ToStringField().put(3, "33");
-
+
builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
-
+
builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
-
+
builder.getMutableInt32ToMessageField().put(
1, MessageValue.newBuilder().setValue(11).build());
builder.getMutableInt32ToMessageField().put(
2, MessageValue.newBuilder().setValue(22).build());
builder.getMutableInt32ToMessageField().put(
3, MessageValue.newBuilder().setValue(33).build());
-
+
builder.getMutableStringToInt32Field().put("1", 11);
builder.getMutableStringToInt32Field().put("2", 22);
builder.getMutableStringToInt32Field().put("3", 33);
@@ -88,22 +88,22 @@ public class MapTest extends TestCase {
assertEquals("11", message.getInt32ToStringField().get(1));
assertEquals("22", message.getInt32ToStringField().get(2));
assertEquals("33", message.getInt32ToStringField().get(3));
-
+
assertEquals(3, message.getInt32ToBytesField().size());
assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
-
+
assertEquals(3, message.getInt32ToEnumField().size());
assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
-
+
assertEquals(3, message.getInt32ToMessageField().size());
assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
-
+
assertEquals(3, message.getStringToInt32Field().size());
assertEquals(11, message.getStringToInt32Field().get("1").intValue());
assertEquals(22, message.getStringToInt32Field().get("2").intValue());
@@ -118,21 +118,21 @@ public class MapTest extends TestCase {
builder.getMutableInt32ToStringField().put(1, "111");
builder.getMutableInt32ToStringField().remove(2);
builder.getMutableInt32ToStringField().put(4, "44");
-
+
builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
builder.getMutableInt32ToBytesField().remove(2);
builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
-
+
builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
builder.getMutableInt32ToEnumField().remove(2);
builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
-
+
builder.getMutableInt32ToMessageField().put(
1, MessageValue.newBuilder().setValue(111).build());
builder.getMutableInt32ToMessageField().remove(2);
builder.getMutableInt32ToMessageField().put(
4, MessageValue.newBuilder().setValue(44).build());
-
+
builder.getMutableStringToInt32Field().put("1", 111);
builder.getMutableStringToInt32Field().remove("2");
builder.getMutableStringToInt32Field().put("4", 44);
@@ -148,22 +148,22 @@ public class MapTest extends TestCase {
assertEquals("111", message.getInt32ToStringField().get(1));
assertEquals("33", message.getInt32ToStringField().get(3));
assertEquals("44", message.getInt32ToStringField().get(4));
-
+
assertEquals(3, message.getInt32ToBytesField().size());
assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
-
+
assertEquals(3, message.getInt32ToEnumField().size());
assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
-
+
assertEquals(3, message.getInt32ToMessageField().size());
assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
-
+
assertEquals(3, message.getStringToInt32Field().size());
assertEquals(111, message.getStringToInt32Field().get("1").intValue());
assertEquals(33, message.getStringToInt32Field().get("3").intValue());
@@ -183,17 +183,17 @@ public class MapTest extends TestCase {
TestMap.Builder builder = TestMap.newBuilder();
TestMap message = builder.build();
assertMapValuesCleared(message);
-
+
builder = message.toBuilder();
setMapValues(builder);
message = builder.build();
assertMapValuesSet(message);
-
+
builder = message.toBuilder();
updateMapValues(builder);
message = builder.build();
assertMapValuesUpdated(message);
-
+
builder = message.toBuilder();
builder.clear();
message = builder.build();
@@ -207,14 +207,14 @@ public class MapTest extends TestCase {
assertEquals(message.getSerializedSize(), message.toByteString().size());
message = TestMap.PARSER.parseFrom(message.toByteString());
assertMapValuesSet(message);
-
+
builder = message.toBuilder();
updateMapValues(builder);
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
message = TestMap.PARSER.parseFrom(message.toByteString());
assertMapValuesUpdated(message);
-
+
builder = message.toBuilder();
builder.clear();
message = builder.build();
@@ -222,12 +222,12 @@ public class MapTest extends TestCase {
message = TestMap.PARSER.parseFrom(message.toByteString());
assertMapValuesCleared(message);
}
-
+
public void testMergeFrom() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
-
+
TestMap.Builder other = TestMap.newBuilder();
other.mergeFrom(message);
assertMapValuesSet(other.build());
@@ -236,7 +236,7 @@ public class MapTest extends TestCase {
public void testEqualsAndHashCode() throws Exception {
// Test that generated equals() and hashCode() will disregard the order
// of map entries when comparing/hashing map fields.
-
+
// We can't control the order of elements in a HashMap. The best we can do
// here is to add elements in different order.
TestMap.Builder b1 = TestMap.newBuilder();
@@ -244,23 +244,23 @@ public class MapTest extends TestCase {
b1.getMutableInt32ToInt32Field().put(3, 4);
b1.getMutableInt32ToInt32Field().put(5, 6);
TestMap m1 = b1.build();
-
+
TestMap.Builder b2 = TestMap.newBuilder();
b2.getMutableInt32ToInt32Field().put(5, 6);
b2.getMutableInt32ToInt32Field().put(1, 2);
b2.getMutableInt32ToInt32Field().put(3, 4);
TestMap m2 = b2.build();
-
+
assertEquals(m1, m2);
assertEquals(m1.hashCode(), m2.hashCode());
-
+
// Make sure we did compare map fields.
b2.getMutableInt32ToInt32Field().put(1, 0);
m2 = b2.build();
assertFalse(m1.equals(m2));
// Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
// to be different.
-
+
// Regression test for b/18549190: if a map is a subset of the other map,
// equals() should return false.
b2.getMutableInt32ToInt32Field().remove(1);
@@ -268,57 +268,95 @@ public class MapTest extends TestCase {
assertFalse(m1.equals(m2));
assertFalse(m2.equals(m1));
}
-
-
+
public void testNestedBuilderOnChangeEventPropagation() {
TestOnChangeEventPropagation.Builder parent =
TestOnChangeEventPropagation.newBuilder();
parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 2);
TestOnChangeEventPropagation message = parent.build();
assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-
+
// Make a change using nested builder.
parent.getOptionalMessageBuilder().getMutableInt32ToInt32Field().put(1, 3);
-
+
// Should be able to observe the change.
message = parent.build();
assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-
+
// Make another change using mergeFrom()
TestMap.Builder other = TestMap.newBuilder();
other.getMutableInt32ToInt32Field().put(1, 4);
parent.getOptionalMessageBuilder().mergeFrom(other.build());
-
+
// Should be able to observe the change.
message = parent.build();
assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
-
+
// Make yet another change by clearing the nested builder.
parent.getOptionalMessageBuilder().clear();
-
+
// Should be able to observe the change.
message = parent.build();
assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
}
-
+
+ public void testNestedBuilderOnChangeEventPropagationReflection() {
+ FieldDescriptor intMapField = f("int32_to_int32_field");
+ // Create an outer message builder with nested builder.
+ TestOnChangeEventPropagation.Builder parentBuilder =
+ TestOnChangeEventPropagation.newBuilder();
+ TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+
+ // Create a map entry message.
+ TestMap.Builder entryBuilder = TestMap.newBuilder();
+ entryBuilder.getMutableInt32ToInt32Field().put(1, 1);
+
+ // Put the entry into the nested builder.
+ testMapBuilder.addRepeatedField(
+ intMapField, entryBuilder.getRepeatedField(intMapField, 0));
+
+ // Should be able to observe the change.
+ TestOnChangeEventPropagation message = parentBuilder.build();
+ assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
+
+ // Change the entry value.
+ entryBuilder.getMutableInt32ToInt32Field().put(1, 4);
+ testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+ testMapBuilder.setRepeatedField(
+ intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
+
+ // Should be able to observe the change.
+ message = parentBuilder.build();
+ assertEquals(4,
+ message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Clear the nested builder.
+ testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+ testMapBuilder.clearField(intMapField);
+
+ // Should be able to observe the change.
+ message = parentBuilder.build();
+ assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+ }
+
// The following methods are used to test reflection API.
-
+
private static FieldDescriptor f(String name) {
return TestMap.getDescriptor().findFieldByName(name);
}
-
+
private static Object getFieldValue(Message mapEntry, String name) {
FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
return mapEntry.getField(field);
}
-
+
private static Message.Builder setFieldValue(
Message.Builder mapEntry, String name, Object value) {
FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
mapEntry.setField(field, value);
return mapEntry;
}
-
+
private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
FieldDescriptor field = f(name);
for (Object entry : (List<?>) message.getField(field)) {
@@ -337,7 +375,7 @@ public class MapTest extends TestCase {
assertEquals(value, values.get(key));
}
}
-
+
private static <KeyType, ValueType>
Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
@@ -348,7 +386,7 @@ public class MapTest extends TestCase {
entryBuilder.setField(valueField, value);
return entryBuilder.build();
}
-
+
private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
List<Message> entryList = new ArrayList<Message>();
for (Map.Entry<?, ?> entry : values.entrySet()) {
@@ -357,7 +395,7 @@ public class MapTest extends TestCase {
FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
builder.setField(field, entryList);
}
-
+
private static <KeyType, ValueType>
Map<KeyType, ValueType> mapForValues(
KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
@@ -385,14 +423,14 @@ public class MapTest extends TestCase {
mapForValues(
11, MessageValue.newBuilder().setValue(22).build(),
33, MessageValue.newBuilder().setValue(44).build()));
-
+
// Test clearField()
builder.clearField(f("int32_to_int32_field"));
builder.clearField(f("int32_to_message_field"));
message = builder.build();
assertEquals(0, message.getInt32ToInt32Field().size());
assertEquals(0, message.getInt32ToMessageField().size());
-
+
// Test setField()
setMapValues(builder, "int32_to_int32_field",
mapForValues(11, 22, 33, 44));
@@ -405,7 +443,7 @@ public class MapTest extends TestCase {
assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
-
+
// Test addRepeatedField
builder.addRepeatedField(f("int32_to_int32_field"),
newMapEntry(builder, "int32_to_int32_field", 55, 66));
@@ -425,7 +463,7 @@ public class MapTest extends TestCase {
message = builder.build();
assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
-
+
// Test setRepeatedField
for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
@@ -442,35 +480,35 @@ public class MapTest extends TestCase {
assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
}
-
+
public void testTextFormat() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
-
+
String textData = TextFormat.printToString(message);
-
+
builder = TestMap.newBuilder();
TextFormat.merge(textData, builder);
message = builder.build();
-
+
assertMapValuesSet(message);
}
-
+
public void testDynamicMessage() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
-
+
Message dynamicDefaultInstance =
DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
Message dynamicMessage = dynamicDefaultInstance
.newBuilderForType().mergeFrom(message.toByteString()).build();
-
+
assertEquals(message, dynamicMessage);
assertEquals(message.hashCode(), dynamicMessage.hashCode());
}
-
+
public void testReflectionEqualsAndHashCode() throws Exception {
// Test that generated equals() and hashCode() will disregard the order
// of map entries when comparing/hashing map fields.
@@ -479,22 +517,22 @@ public class MapTest extends TestCase {
Message dynamicDefaultInstance =
DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
FieldDescriptor field = f("int32_to_int32_field");
-
+
Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
Message m1 = b1.build();
-
+
Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
Message m2 = b2.build();
-
+
assertEquals(m1, m2);
assertEquals(m1.hashCode(), m2.hashCode());
-
+
// Make sure we did compare map fields.
b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
m2 = b2.build();
@@ -502,7 +540,7 @@ public class MapTest extends TestCase {
// Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
// to be different.
}
-
+
public void testUnknownEnumValues() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
builder.getMutableInt32ToEnumFieldValue().put(0, 0);
@@ -517,7 +555,7 @@ public class MapTest extends TestCase {
assertEquals(TestMap.EnumValue.UNRECOGNIZED,
message.getInt32ToEnumField().get(2));
assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
-
+
// Unknown enum values should be preserved after:
// 1. Serialization and parsing.
// 2. toBuild().
@@ -528,7 +566,7 @@ public class MapTest extends TestCase {
assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
builder = TestMap.newBuilder().mergeFrom(message);
assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
-
+
// hashCode()/equals() should take unknown enum values into account.
builder.getMutableInt32ToEnumFieldValue().put(2, 1001);
TestMap message2 = builder.build();
@@ -538,17 +576,17 @@ public class MapTest extends TestCase {
// should be the same.
assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField()));
}
-
+
public void testUnknownEnumValuesInReflectionApi() throws Exception {
Descriptor descriptor = TestMap.getDescriptor();
EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
-
+
Map<Integer, Integer> data = new HashMap<Integer, Integer>();
data.put(0, 0);
data.put(1, 1);
data.put(2, 1000); // unknown value.
-
+
TestMap.Builder builder = TestMap.newBuilder();
for (Map.Entry<Integer, Integer> entry : data.entrySet()) {
builder.getMutableInt32ToEnumFieldValue().put(entry.getKey(), entry.getValue());
diff --git a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
index b3970196..0f2344d6 100644
--- a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -118,6 +118,34 @@ public class RopeByteStringTest extends LiteralByteStringTest {
flatString.hashCode(), unicode.hashCode());
}
+ @Override
+ public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException {
+ RopeByteString ropeByteString =
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+ assertSame(classUnderTest + " must be the same string references",
+ ByteString.EMPTY.toString(UTF_8), ropeByteString.toString(UTF_8));
+ }
+
+ public void testToString_raisesException() throws UnsupportedEncodingException{
+ try {
+ ByteString byteString =
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+ byteString.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ ByteString byteString = RopeByteString.concatenate(ByteString.copyFromUtf8("foo"),
+ ByteString.copyFromUtf8("bar"));
+ byteString.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
public void testJavaSerialization() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
diff --git a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
index 015dc267..5580f72d 100644
--- a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
+++ b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto
@@ -54,6 +54,15 @@ message LazyInnerMessageLite {
optional int32 num = 1;
optional int32 num_with_default = 2 [default = 42];
optional LazyNestedInnerMessageLite nested = 3 [lazy = true];
+
+ extensions 1000 to max;
+}
+
+message LazyExtension {
+ extend LazyInnerMessageLite {
+ optional LazyExtension extension = 1000;
+ }
+ optional string name = 1;
}
message LazyNestedInnerMessageLite {
diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
index a1fe856c..d5418f28 100644
--- a/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
+++ b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto
@@ -63,6 +63,13 @@ message TestUnknownEnumValue {
// parsing behavior of TestMap regarding unknown enum values.
map<int32, int32> int32_to_int32_field = 4;
}
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+ optional int32 value = 1;
+ map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
package map_for_proto2_lite_test;
option java_package = "map_lite_test";
option optimize_for = LITE_RUNTIME;
diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
index a0ec7ac5..a9be5166 100644
--- a/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
+++ b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto
@@ -65,3 +65,10 @@ message TestUnknownEnumValue {
// parsing behavior of TestMap regarding unknown enum values.
map<int32, int32> int32_to_int32_field = 4;
}
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+ optional int32 value = 1;
+ map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
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 105ee3f8..bf692c22 100644
--- a/java/src/test/java/com/google/protobuf/map_test.proto
+++ b/java/src/test/java/com/google/protobuf/map_test.proto
@@ -36,6 +36,7 @@ option java_package = "map_test";
option java_outer_classname = "MapTestProto";
option java_generate_equals_and_hash = true;
+
message TestMap {
message MessageValue {
optional int32 value = 1;
diff --git a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
index 67035fd5..dc082615 100644
--- a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
+++ b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto
@@ -45,6 +45,7 @@ option java_package = "com.google.protobuf";
option java_outer_classname = "TestBadIdentifiersProto";
option java_generate_equals_and_hash = true;
+
message TestMessage {
optional string cached_size = 1;
optional string serialized_size = 2;
diff --git a/javanano/README.txt b/javanano/README.md
index 5a05b865..7d696aa7 100644
--- a/javanano/README.txt
+++ b/javanano/README.md
@@ -1,10 +1,14 @@
Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
Copyright 2008 Google Inc.
This directory contains the Java Protocol Buffers Nano runtime library.
Installation - With Maven
-=========================
+-------------------------
The Protocol Buffers build is managed using Maven. If you would
rather build without Maven, see below.
@@ -41,7 +45,7 @@ rather build without Maven, see below.
The .jar will be placed in the "target" directory.
Installation - Without Maven
-============================
+----------------------------
If you would rather not install Maven to build the library, you may
follow these instructions instead. Note that these instructions skip
@@ -66,20 +70,22 @@ running unit tests.
4) Install the classes wherever you prefer.
Nano version
-============================
+------------
-Nano is a special code generator and runtime library designed specially
-for Android, and is very resource-friendly in both the amount of code
-and the runtime overhead. An overview of Nano features:
+JavaNano is a special code generator and runtime library designed specially for
+resource-restricted systems, like Android. It is very resource-friendly in both
+the amount of code and the runtime overhead. Here is an overview of JavaNano
+features compared with the official Java protobuf:
- No descriptors or message builders.
- All messages are mutable; fields are public Java fields.
- For optional fields only, encapsulation behind setter/getter/hazzer/
clearer functions is opt-in, which provide proper 'has' state support.
-- If not opted in, has state is not available. Serialization outputs
- all fields not equal to their defaults (see important implications
- below).
-- Required fields are always serialized.
+- For proto2, if not opted in, has state (field presence) is not available.
+ Serialization outputs all fields not equal to their defaults
+ (see important implications below).
+ The behavior is consistent with proto3 semantics.
+- Required fields (proto2 only) are always serialized.
- Enum constants are integers; protection against invalid values only
when parsing from the wire.
- Enum constants can be generated into container interfaces bearing
@@ -88,8 +94,8 @@ and the runtime overhead. An overview of Nano features:
- Similarly CodedOutputByteBufferNano can only write to byte[].
- Repeated fields are in arrays, not ArrayList or Vector. Null array
elements are allowed and silently ignored.
-- Full support of serializing/deserializing repeated packed fields.
-- Support of extensions.
+- Full support for serializing/deserializing repeated packed fields.
+- Support extensions (in proto2).
- Unset messages/groups are null, not an immutable empty default
instance.
- toByteArray(...) and mergeFrom(...) are now static functions of
@@ -128,7 +134,9 @@ penalty. This is not a problem if the field has no default or is an
empty default.
Nano Generator options
+----------------------
+```
java_package -> <file-name>|<package-name>
java_outer_classname -> <file-name>|<package-name>
java_multiple_files -> true or false
@@ -137,8 +145,10 @@ optional_field_style -> default or accessors
enum_style -> c or java
ignore_services -> true or false
parcelable_messages -> true or false
+```
+
+**java_package=\<file-name\>|\<package-name\>** (no default)
-java_package=<file-name>|<package-name> (no default)
This allows overriding the 'java_package' option value
for the given file from the command line. Use multiple
java_package options to override the option for multiple
@@ -147,7 +157,8 @@ java_package=<file-name>|<package-name> (no default)
the same option defined in the file if present, or the
proto package if present, or the default Java package.
-java_outer_classname=<file-name>|<outer-classname> (no default)
+**java_outer_classname=\<file-name\>|\<outer-classname\>** (no default)
+
This allows overriding the 'java_outer_classname' option
for the given file from the command line. Use multiple
java_outer_classname options to override the option for
@@ -158,7 +169,8 @@ java_outer_classname=<file-name>|<outer-classname> (no default)
outer class will nest all classes and integer constants
generated from file-scope messages and enums.
-java_multiple_files={true,false} (no default)
+**java_multiple_files={true,false}** (no default)
+
This allows overriding the 'java_multiple_files' option
in all source files and their imported files from the
command line. The final value of this option for each
@@ -176,10 +188,11 @@ java_multiple_files={true,false} (no default)
incorrect references to the imported messages and enum
constants.
-java_nano_generate_has={true,false} (default: false)
+**java_nano_generate_has={true,false}** (default: false)
+
DEPRECATED. Use optional_field_style=accessors.
- If true, generates a public boolean variable has<fieldname>
+ If true, generates a public boolean variable has\<fieldname\>
accompanying each optional or required field (not present for
repeated fields, groups or messages). It is set to false initially
and upon clear(). If parseFrom(...) reads the field from the wire,
@@ -193,20 +206,21 @@ java_nano_generate_has={true,false} (default: false)
many cases reading the default works and determining whether the
field was received over the wire is irrelevant.
-optional_field_style={default,accessors,reftypes} (default: default)
+**optional_field_style={default,accessors,reftypes}** (default: default)
+
Defines the style of the generated code for fields.
- * default *
+ * default
In the default style, optional fields translate into public mutable
Java fields, and the serialization process is as discussed in the
- "IMPORTANT" section above.
+ "IMPORTANT" section above.
- * accessors *
+ * accessors
When set to 'accessors', each optional field is encapsulated behind
- 4 accessors, namely get<fieldname>(), set<fieldname>(), has<fieldname>()
- and clear<fieldname>() methods, with the standard semantics. The hazzer's
+ 4 accessors, namely get\<fieldname\>(), set\<fieldname\>(), has\<fieldname\>()
+ and clear\<fieldname\>() methods, with the standard semantics. The hazzer's
return value determines whether a field is serialized, so this style is
useful when you need to serialize a field with the default value, or check
if a field has been explicitly set to its default value from the wire.
@@ -222,7 +236,7 @@ optional_field_style={default,accessors,reftypes} (default: default)
reducing the final code size.
TODO(maxtroy): find ProGuard config that would work the best.
- * reftypes *
+ * reftypes
When set to 'reftypes', each proto field is generated as a public Java
field. For primitive types, these fields use the Java reference types
@@ -252,10 +266,11 @@ optional_field_style={default,accessors,reftypes} (default: default)
required field (you have no reason to), you can only use
java_nano_generate_has=true.
-enum_style={c,java} (default: c)
+**enum_style={c,java}** (default: c)
+
Defines where to put the int constants generated from enum members.
- * c *
+ * c
Use C-style, so the enum constants are available at the scope where
the enum is defined. A file-scope enum's members are referenced like
@@ -263,7 +278,7 @@ enum_style={c,java} (default: c)
referenced as 'Message.ENUM_VALUE'. The enum name is unavailable.
This complies with the Micro code generator's behavior.
- * java *
+ * java
Use Java-style, so the enum constants are available under the enum
name and referenced like 'EnumName.ENUM_VALUE' (they are still int
@@ -275,18 +290,21 @@ enum_style={c,java} (default: c)
compiler inlines all referenced enum constants into the call sites,
the interface remains unused and can be removed by ProGuard.
-ignore_services={true,false} (default: false)
+**ignore_services={true,false}** (default: false)
+
Skips services definitions.
Nano doesn't support services. By default, if a service is defined
it will generate a compilation error. If this flag is set to true,
services will be silently ignored, instead.
-parcelable_messages={true,false} (default: false)
+**parcelable_messages={true,false}** (default: false)
+
Android-specific option to generate Parcelable messages.
To use nano protobufs within the Android repo:
+----------------------------------------------
- Set 'LOCAL_PROTOC_OPTIMIZE_TYPE := nano' in your local .mk file.
When building a Java library or an app (package) target, the build
@@ -311,17 +329,20 @@ To use nano protobufs within the Android repo:
the two above.
To use nano protobufs outside of Android repo:
+----------------------------------------------
- Link with the generated jar file
- <protobuf-root>java/target/protobuf-java-2.3.0-nano.jar.
+ \<protobuf-root\>java/target/protobuf-java-2.3.0-nano.jar.
- Invoke with --javanano_out, e.g.:
-
+```
./protoc '--javanano_out=\
java_package=src/proto/simple-data.proto|my_package,\
java_outer_classname=src/proto/simple-data.proto|OuterName\
:.' src/proto/simple-data.proto
+```
Contributing to nano:
+---------------------
Please add/edit tests in NanoTest.java.
@@ -346,7 +367,7 @@ Please run the following steps to test:
- "make -j12" and check for build errors
Usage
-=====
+-----
The complete documentation for Protocol Buffers is available via the
web at:
diff --git a/javanano/pom.xml b/javanano/pom.xml
index 3d98a5e0..7a2be9df 100644
--- a/javanano/pom.xml
+++ b/javanano/pom.xml
@@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf.nano</groupId>
<artifactId>protobuf-javanano</artifactId>
- <version>2.6.2-pre</version>
+ <version>3.0.0-alpha-3-pre</version>
<packaging>bundle</packaging>
<name>Protocol Buffer JavaNano API</name>
<description>
@@ -94,6 +94,7 @@
<arg value="src/test/java/com/google/protobuf/nano/unittest_multiple_nameclash_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_enum_class_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_repeated_merge_nano.proto" />
+ <arg value="src/test/java/com/google/protobuf/nano/map_test.proto" />
</exec>
<exec executable="../src/protoc">
<arg value="--javanano_out=store_unknown_fields=true,generate_equals=true:target/generated-test-sources" />
@@ -155,10 +156,70 @@
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
- <Export-Package>com.google.protobuf;version=2.6.2-pre</Export-Package>
+ <Export-Package>com.google.protobuf;version=3.0.0-alpha-3-pre</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
+ <profiles>
+ <profile>
+ <id>release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <version>1.6.3</version>
+ <extensions>true</extensions>
+ <configuration>
+ <serverId>sonatype-nexus-staging</serverId>
+ <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+ <autoReleaseAfterClose>false</autoReleaseAfterClose>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
index b147f69d..b4f20fde 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
@@ -638,4 +638,44 @@ public final class CodedInputByteBufferNano {
throw InvalidProtocolBufferNanoException.truncatedMessage();
}
}
+
+ // Read a primitive type.
+ Object readPrimitiveField(int type) throws IOException {
+ switch (type) {
+ case InternalNano.TYPE_DOUBLE:
+ return readDouble();
+ case InternalNano.TYPE_FLOAT:
+ return readFloat();
+ case InternalNano.TYPE_INT64:
+ return readInt64();
+ case InternalNano.TYPE_UINT64:
+ return readUInt64();
+ case InternalNano.TYPE_INT32:
+ return readInt32();
+ case InternalNano.TYPE_FIXED64:
+ return readFixed64();
+ case InternalNano.TYPE_FIXED32:
+ return readFixed32();
+ case InternalNano.TYPE_BOOL:
+ return readBool();
+ case InternalNano.TYPE_STRING:
+ return readString();
+ case InternalNano.TYPE_BYTES:
+ return readBytes();
+ case InternalNano.TYPE_UINT32:
+ return readUInt32();
+ case InternalNano.TYPE_ENUM:
+ return readEnum();
+ case InternalNano.TYPE_SFIXED32:
+ return readSFixed32();
+ case InternalNano.TYPE_SFIXED64:
+ return readSFixed64();
+ case InternalNano.TYPE_SINT32:
+ return readSInt32();
+ case InternalNano.TYPE_SINT64:
+ return readSInt64();
+ default:
+ throw new IllegalArgumentException("Unknown type " + type);
+ }
+ }
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
index 37982b57..2777f34c 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
@@ -876,4 +876,128 @@ public final class CodedOutputByteBufferNano {
// Note: the right-shift must be arithmetic
return (n << 1) ^ (n >> 63);
}
+
+ static int computeFieldSize(int number, int type, Object object) {
+ switch (type) {
+ case InternalNano.TYPE_BOOL:
+ return computeBoolSize(number, (Boolean) object);
+ case InternalNano.TYPE_BYTES:
+ return computeBytesSize(number, (byte[]) object);
+ case InternalNano.TYPE_STRING:
+ return computeStringSize(number, (String) object);
+ case InternalNano.TYPE_FLOAT:
+ return computeFloatSize(number, (Float) object);
+ case InternalNano.TYPE_DOUBLE:
+ return computeDoubleSize(number, (Double) object);
+ case InternalNano.TYPE_ENUM:
+ return computeEnumSize(number, (Integer) object);
+ case InternalNano.TYPE_FIXED32:
+ return computeFixed32Size(number, (Integer) object);
+ case InternalNano.TYPE_INT32:
+ return computeInt32Size(number, (Integer) object);
+ case InternalNano.TYPE_UINT32:
+ return computeUInt32Size(number, (Integer) object);
+ case InternalNano.TYPE_SINT32:
+ return computeSInt32Size(number, (Integer) object);
+ case InternalNano.TYPE_SFIXED32:
+ return computeSFixed32Size(number, (Integer) object);
+ case InternalNano.TYPE_INT64:
+ return computeInt64Size(number, (Long) object);
+ case InternalNano.TYPE_UINT64:
+ return computeUInt64Size(number, (Long) object);
+ case InternalNano.TYPE_SINT64:
+ return computeSInt64Size(number, (Long) object);
+ case InternalNano.TYPE_FIXED64:
+ return computeFixed64Size(number, (Long) object);
+ case InternalNano.TYPE_SFIXED64:
+ return computeSFixed64Size(number, (Long) object);
+ case InternalNano.TYPE_MESSAGE:
+ return computeMessageSize(number, (MessageNano) object);
+ case InternalNano.TYPE_GROUP:
+ return computeGroupSize(number, (MessageNano) object);
+ default:
+ throw new IllegalArgumentException("Unknown type: " + type);
+ }
+ }
+
+ void writeField(int number, int type, Object value)
+ throws IOException {
+ switch (type) {
+ case InternalNano.TYPE_DOUBLE:
+ Double doubleValue = (Double) value;
+ writeDouble(number, doubleValue);
+ break;
+ case InternalNano.TYPE_FLOAT:
+ Float floatValue = (Float) value;
+ writeFloat(number, floatValue);
+ break;
+ case InternalNano.TYPE_INT64:
+ Long int64Value = (Long) value;
+ writeInt64(number, int64Value);
+ break;
+ case InternalNano.TYPE_UINT64:
+ Long uint64Value = (Long) value;
+ writeUInt64(number, uint64Value);
+ break;
+ case InternalNano.TYPE_INT32:
+ Integer int32Value = (Integer) value;
+ writeInt32(number, int32Value);
+ break;
+ case InternalNano.TYPE_FIXED64:
+ Long fixed64Value = (Long) value;
+ writeFixed64(number, fixed64Value);
+ break;
+ case InternalNano.TYPE_FIXED32:
+ Integer fixed32Value = (Integer) value;
+ writeFixed32(number, fixed32Value);
+ break;
+ case InternalNano.TYPE_BOOL:
+ Boolean boolValue = (Boolean) value;
+ writeBool(number, boolValue);
+ break;
+ case InternalNano.TYPE_STRING:
+ String stringValue = (String) value;
+ writeString(number, stringValue);
+ break;
+ case InternalNano.TYPE_BYTES:
+ byte[] bytesValue = (byte[]) value;
+ writeBytes(number, bytesValue);
+ break;
+ case InternalNano.TYPE_UINT32:
+ Integer uint32Value = (Integer) value;
+ writeUInt32(number, uint32Value);
+ break;
+ case InternalNano.TYPE_ENUM:
+ Integer enumValue = (Integer) value;
+ writeEnum(number, enumValue);
+ break;
+ case InternalNano.TYPE_SFIXED32:
+ Integer sfixed32Value = (Integer) value;
+ writeSFixed32(number, sfixed32Value);
+ break;
+ case InternalNano.TYPE_SFIXED64:
+ Long sfixed64Value = (Long) value;
+ writeSFixed64(number, sfixed64Value);
+ break;
+ case InternalNano.TYPE_SINT32:
+ Integer sint32Value = (Integer) value;
+ writeSInt32(number, sint32Value);
+ break;
+ case InternalNano.TYPE_SINT64:
+ Long sint64Value = (Long) value;
+ writeSInt64(number, sint64Value);
+ break;
+ case InternalNano.TYPE_MESSAGE:
+ MessageNano messageValue = (MessageNano) value;
+ writeMessage(number, messageValue);
+ break;
+ case InternalNano.TYPE_GROUP:
+ MessageNano groupValue = (MessageNano) value;
+ writeGroup(number, groupValue);
+ break;
+ default:
+ throw new IOException("Unknown type: " + type);
+ }
+ }
+
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/javanano/src/main/java/com/google/protobuf/nano/Extension.java
index 5d18ae6e..c29b030f 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/Extension.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/Extension.java
@@ -55,24 +55,24 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* PrimitiveExtension // for primitive/enum typed extensions
*/
- public static final int TYPE_DOUBLE = 1;
- public static final int TYPE_FLOAT = 2;
- public static final int TYPE_INT64 = 3;
- public static final int TYPE_UINT64 = 4;
- public static final int TYPE_INT32 = 5;
- public static final int TYPE_FIXED64 = 6;
- public static final int TYPE_FIXED32 = 7;
- public static final int TYPE_BOOL = 8;
- public static final int TYPE_STRING = 9;
- public static final int TYPE_GROUP = 10;
- public static final int TYPE_MESSAGE = 11;
- public static final int TYPE_BYTES = 12;
- public static final int TYPE_UINT32 = 13;
- public static final int TYPE_ENUM = 14;
- public static final int TYPE_SFIXED32 = 15;
- public static final int TYPE_SFIXED64 = 16;
- public static final int TYPE_SINT32 = 17;
- public static final int TYPE_SINT64 = 18;
+ public static final int TYPE_DOUBLE = InternalNano.TYPE_DOUBLE;
+ public static final int TYPE_FLOAT = InternalNano.TYPE_FLOAT;
+ public static final int TYPE_INT64 = InternalNano.TYPE_INT64;
+ public static final int TYPE_UINT64 = InternalNano.TYPE_UINT64;
+ public static final int TYPE_INT32 = InternalNano.TYPE_INT32;
+ public static final int TYPE_FIXED64 = InternalNano.TYPE_FIXED64;
+ public static final int TYPE_FIXED32 = InternalNano.TYPE_FIXED32;
+ public static final int TYPE_BOOL = InternalNano.TYPE_BOOL;
+ public static final int TYPE_STRING = InternalNano.TYPE_STRING;
+ public static final int TYPE_GROUP = InternalNano.TYPE_GROUP;
+ public static final int TYPE_MESSAGE = InternalNano.TYPE_MESSAGE;
+ public static final int TYPE_BYTES = InternalNano.TYPE_BYTES;
+ public static final int TYPE_UINT32 = InternalNano.TYPE_UINT32;
+ public static final int TYPE_ENUM = InternalNano.TYPE_ENUM;
+ public static final int TYPE_SFIXED32 = InternalNano.TYPE_SFIXED32;
+ public static final int TYPE_SFIXED64 = InternalNano.TYPE_SFIXED64;
+ public static final int TYPE_SINT32 = InternalNano.TYPE_SINT32;
+ public static final int TYPE_SINT64 = InternalNano.TYPE_SINT64;
/**
* Creates an {@code Extension} of the given message type and tag number.
@@ -338,42 +338,7 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
@Override
protected Object readData(CodedInputByteBufferNano input) {
try {
- switch (type) {
- case TYPE_DOUBLE:
- return input.readDouble();
- case TYPE_FLOAT:
- return input.readFloat();
- case TYPE_INT64:
- return input.readInt64();
- case TYPE_UINT64:
- return input.readUInt64();
- case TYPE_INT32:
- return input.readInt32();
- case TYPE_FIXED64:
- return input.readFixed64();
- case TYPE_FIXED32:
- return input.readFixed32();
- case TYPE_BOOL:
- return input.readBool();
- case TYPE_STRING:
- return input.readString();
- case TYPE_BYTES:
- return input.readBytes();
- case TYPE_UINT32:
- return input.readUInt32();
- case TYPE_ENUM:
- return input.readEnum();
- case TYPE_SFIXED32:
- return input.readSFixed32();
- case TYPE_SFIXED64:
- return input.readSFixed64();
- case TYPE_SINT32:
- return input.readSInt32();
- case TYPE_SINT64:
- return input.readSInt64();
- default:
- throw new IllegalArgumentException("Unknown type " + type);
- }
+ return input.readPrimitiveField(type);
} catch (IOException e) {
throw new IllegalArgumentException("Error reading extension field", e);
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
index e08bb4b7..4a08bb58 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
@@ -30,8 +30,13 @@
package com.google.protobuf.nano;
+import com.google.protobuf.nano.MapFactories.MapFactory;
+
+import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
+import java.util.Map;
+import java.util.Map.Entry;
/**
* The classes contained within are used internally by the Protocol Buffer
@@ -43,6 +48,26 @@ import java.util.Arrays;
*/
public final class InternalNano {
+ public static final int TYPE_DOUBLE = 1;
+ public static final int TYPE_FLOAT = 2;
+ public static final int TYPE_INT64 = 3;
+ public static final int TYPE_UINT64 = 4;
+ public static final int TYPE_INT32 = 5;
+ public static final int TYPE_FIXED64 = 6;
+ public static final int TYPE_FIXED32 = 7;
+ public static final int TYPE_BOOL = 8;
+ public static final int TYPE_STRING = 9;
+ public static final int TYPE_GROUP = 10;
+ public static final int TYPE_MESSAGE = 11;
+ public static final int TYPE_BYTES = 12;
+ public static final int TYPE_UINT32 = 13;
+ public static final int TYPE_ENUM = 14;
+ public static final int TYPE_SFIXED32 = 15;
+ public static final int TYPE_SFIXED64 = 16;
+ public static final int TYPE_SINT32 = 17;
+ public static final int TYPE_SINT64 = 18;
+
+
private InternalNano() {}
/**
@@ -329,5 +354,202 @@ public final class InternalNano {
}
return result;
}
+ private static Object primitiveDefaultValue(int type) {
+ switch (type) {
+ case TYPE_BOOL:
+ return Boolean.FALSE;
+ case TYPE_BYTES:
+ return WireFormatNano.EMPTY_BYTES;
+ case TYPE_STRING:
+ return "";
+ case TYPE_FLOAT:
+ return Float.valueOf(0);
+ case TYPE_DOUBLE:
+ return Double.valueOf(0);
+ case TYPE_ENUM:
+ case TYPE_FIXED32:
+ case TYPE_INT32:
+ case TYPE_UINT32:
+ case TYPE_SINT32:
+ case TYPE_SFIXED32:
+ return Integer.valueOf(0);
+ case TYPE_INT64:
+ case TYPE_UINT64:
+ case TYPE_SINT64:
+ case TYPE_FIXED64:
+ case TYPE_SFIXED64:
+ return Long.valueOf(0L);
+ case TYPE_MESSAGE:
+ case TYPE_GROUP:
+ default:
+ throw new IllegalArgumentException(
+ "Type: " + type + " is not a primitive type.");
+ }
+ }
+
+ /**
+ * Merges the map entry into the map field. Note this is only supposed to
+ * be called by generated messages.
+ *
+ * @param map the map field; may be null, in which case a map will be
+ * instantiated using the {@link MapFactories.MapFactory}
+ * @param input the input byte buffer
+ * @param keyType key type, as defined in InternalNano.TYPE_*
+ * @param valueType value type, as defined in InternalNano.TYPE_*
+ * @param value an new instance of the value, if the value is a TYPE_MESSAGE;
+ * otherwise this parameter can be null and will be ignored.
+ * @param keyTag wire tag for the key
+ * @param valueTag wire tag for the value
+ * @return the map field
+ * @throws IOException
+ */
+ @SuppressWarnings("unchecked")
+ public static final <K, V> Map<K, V> mergeMapEntry(
+ CodedInputByteBufferNano input,
+ Map<K, V> map,
+ MapFactory mapFactory,
+ int keyType,
+ int valueType,
+ V value,
+ int keyTag,
+ int valueTag) throws IOException {
+ map = mapFactory.forMap(map);
+ final int length = input.readRawVarint32();
+ final int oldLimit = input.pushLimit(length);
+ K key = null;
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+ if (tag == keyTag) {
+ key = (K) input.readPrimitiveField(keyType);
+ } else if (tag == valueTag) {
+ if (valueType == TYPE_MESSAGE) {
+ input.readMessage((MessageNano) value);
+ } else {
+ value = (V) input.readPrimitiveField(valueType);
+ }
+ } else {
+ if (!input.skipField(tag)) {
+ break;
+ }
+ }
+ }
+ input.checkLastTagWas(0);
+ input.popLimit(oldLimit);
+
+ if (key == null) {
+ // key can only be primitive types.
+ key = (K) primitiveDefaultValue(keyType);
+ }
+
+ if (value == null) {
+ // message type value will be initialized by code-gen.
+ value = (V) primitiveDefaultValue(valueType);
+ }
+
+ map.put(key, value);
+ return map;
+ }
+
+ public static <K, V> void serializeMapField(
+ CodedOutputByteBufferNano output,
+ Map<K, V> map, int number, int keyType, int valueType)
+ throws IOException {
+ for (Entry<K, V> entry: map.entrySet()) {
+ K key = entry.getKey();
+ V value = entry.getValue();
+ if (key == null || value == null) {
+ throw new IllegalStateException(
+ "keys and values in maps cannot be null");
+ }
+ int entrySize =
+ CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
+ CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
+ output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(entrySize);
+ output.writeField(1, keyType, key);
+ output.writeField(2, valueType, value);
+ }
+ }
+
+ public static <K, V> int computeMapFieldSize(
+ Map<K, V> map, int number, int keyType, int valueType) {
+ int size = 0;
+ int tagSize = CodedOutputByteBufferNano.computeTagSize(number);
+ for (Entry<K, V> entry: map.entrySet()) {
+ K key = entry.getKey();
+ V value = entry.getValue();
+ if (key == null || value == null) {
+ throw new IllegalStateException(
+ "keys and values in maps cannot be null");
+ }
+ int entrySize =
+ CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) +
+ CodedOutputByteBufferNano.computeFieldSize(2, valueType, value);
+ size += tagSize + entrySize
+ + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize);
+ }
+ return size;
+ }
+
+ /**
+ * Checks whether two {@link Map} are equal. We don't use the default equals
+ * method of {@link Map} because it compares by identity not by content for
+ * byte arrays.
+ */
+ public static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null) {
+ return b.size() == 0;
+ }
+ if (b == null) {
+ return a.size() == 0;
+ }
+ if (a.size() != b.size()) {
+ return false;
+ }
+ for (Entry<K, V> entry : a.entrySet()) {
+ if (!b.containsKey(entry.getKey())) {
+ return false;
+ }
+ if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean equalsMapValue(Object a, Object b) {
+ if (a == null || b == null) {
+ throw new IllegalStateException(
+ "keys and values in maps cannot be null");
+ }
+ if (a instanceof byte[] && b instanceof byte[]) {
+ return Arrays.equals((byte[]) a, (byte[]) b);
+ }
+ return a.equals(b);
+ }
+
+ public static <K, V> int hashCode(Map<K, V> map) {
+ if (map == null) {
+ return 0;
+ }
+ int result = 0;
+ for (Entry<K, V> entry : map.entrySet()) {
+ result += hashCodeForMap(entry.getKey())
+ ^ hashCodeForMap(entry.getValue());
+ }
+ return result;
+ }
+ private static int hashCodeForMap(Object o) {
+ if (o instanceof byte[]) {
+ return Arrays.hashCode((byte[]) o);
+ }
+ return o.hashCode();
+ }
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java
new file mode 100644
index 00000000..98fa4877
--- /dev/null
+++ b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java
@@ -0,0 +1,67 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.nano;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for maps support.
+ */
+public final class MapFactories {
+ public static interface MapFactory {
+ <K, V> Map<K, V> forMap(Map<K, V> oldMap);
+ }
+
+ // NOTE(liujisi): The factory setter is temporarily marked as package private.
+ // The way to provide customized implementations of maps for different
+ // platforms are still under discussion. Mark it as private to avoid exposing
+ // the API in proto3 alpha release.
+ /* public */ static void setMapFactory(MapFactory newMapFactory) {
+ mapFactory = newMapFactory;
+ }
+
+ public static MapFactory getMapFactory() {
+ return mapFactory;
+ }
+
+ private static class DefaultMapFactory implements MapFactory {
+ public <K, V> Map<K, V> forMap(Map<K, V> oldMap) {
+ if (oldMap == null) {
+ return new HashMap<K, V>();
+ }
+ return oldMap;
+ }
+ }
+ private static volatile MapFactory mapFactory = new DefaultMapFactory();
+
+ private MapFactories() {}
+}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
index dd43cdbb..c4b2ad3d 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
@@ -35,6 +35,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.util.Map;
/**
* Static helper methods for printing nano protos.
@@ -170,6 +171,19 @@ public final class MessageNanoPrinter {
indentBuf.setLength(origIndentBufLength);
buf.append(indentBuf).append(">\n");
}
+ } else if (object instanceof Map) {
+ Map<?,?> map = (Map<?,?>) object;
+ identifier = deCamelCaseify(identifier);
+
+ for (Map.Entry<?,?> entry : map.entrySet()) {
+ buf.append(indentBuf).append(identifier).append(" <\n");
+ int origIndentBufLength = indentBuf.length();
+ indentBuf.append(INDENT);
+ print("key", entry.getKey(), indentBuf, buf);
+ print("value", entry.getValue(), indentBuf, buf);
+ indentBuf.setLength(origIndentBufLength);
+ buf.append(indentBuf).append(">\n");
+ }
} else {
// Non-null primitive value
identifier = deCamelCaseify(identifier);
diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
index 442f0b74..4cc77226 100644
--- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
+++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
@@ -30,31 +30,11 @@
package com.google.protobuf.nano;
-import com.google.protobuf.nano.CodedInputByteBufferNano;
-import com.google.protobuf.nano.EnumClassNanoMultiple;
-import com.google.protobuf.nano.EnumClassNanos;
-import com.google.protobuf.nano.EnumValidity;
-import com.google.protobuf.nano.EnumValidityAccessors;
-import com.google.protobuf.nano.FileScopeEnumMultiple;
-import com.google.protobuf.nano.FileScopeEnumRefNano;
-import com.google.protobuf.nano.InternalNano;
-import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
-import com.google.protobuf.nano.MessageNano;
-import com.google.protobuf.nano.MessageScopeEnumRefNano;
-import com.google.protobuf.nano.MultipleImportingNonMultipleNano1;
-import com.google.protobuf.nano.MultipleImportingNonMultipleNano2;
-import com.google.protobuf.nano.MultipleNameClashNano;
+import com.google.protobuf.nano.MapTestProto.TestMap;
+import com.google.protobuf.nano.MapTestProto.TestMap.MessageValue;
import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors;
import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas;
-import com.google.protobuf.nano.NanoOuterClass;
import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano;
-import com.google.protobuf.nano.NanoReferenceTypes;
-import com.google.protobuf.nano.NanoRepeatedPackables;
-import com.google.protobuf.nano.PackedExtensions;
-import com.google.protobuf.nano.RepeatedExtensions;
-import com.google.protobuf.nano.SingularExtensions;
-import com.google.protobuf.nano.TestRepeatedMergeNano;
-import com.google.protobuf.nano.UnittestMultipleNano;
import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano;
import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano;
import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano;
@@ -67,6 +47,8 @@ import junit.framework.TestCase;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
/**
* Test nano runtime.
@@ -2688,6 +2670,7 @@ public class NanoTest extends TestCase {
msg.repeatedNestedEnum[0] = TestAllTypesNano.BAR;
msg.repeatedNestedEnum[1] = TestAllTypesNano.FOO;
msg.repeatedStringPiece = new String[] {null, "world"};
+ msg.setOneofString("hello");
String protoPrint = msg.toString();
assertTrue(protoPrint.contains("optional_int32: 14"));
@@ -2711,6 +2694,7 @@ public class NanoTest extends TestCase {
assertTrue(protoPrint.contains("default_string: \"hello\""));
assertFalse(protoPrint.contains("repeated_string_piece: \"\"")); // null should be dropped
assertTrue(protoPrint.contains("repeated_string_piece: \"world\""));
+ assertTrue(protoPrint.contains("oneof_string: \"hello\""));
}
public void testMessageNanoPrinterAccessors() throws Exception {
@@ -2749,6 +2733,45 @@ public class NanoTest extends TestCase {
assertTrue(protoPrint.contains("id: 33"));
}
+ public void testMessageNanoPrinterForMaps() throws Exception {
+ TestMap msg = new TestMap();
+ MessageValue msgValues[] = new MessageValue[] {
+ new MessageValue(), new MessageValue()
+ };
+ msgValues[0].value = 1;
+ msgValues[1].value = 2;
+ msg.int32ToBytesField = new HashMap<Integer, byte[]>();
+ msg.int32ToBytesField.put(1, new byte[] {'"', '\0'});
+ msg.int32ToBytesField.put(2, new byte[] {1, 8});
+ msg.stringToInt32Field = new HashMap<String, Integer>();
+ msg.stringToInt32Field.put("hello", 1);
+ msg.stringToInt32Field.put("world", 2);
+ msg.int32ToMessageField = new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ msg.int32ToMessageField.put(0, msgValues[0]);
+ msg.int32ToMessageField.put(1, msgValues[1]);
+ msg.int32ToEnumField = new HashMap<Integer, Integer>();
+ msg.int32ToEnumField.put(1, 2);
+ msg.int32ToEnumField.put(2, 3);
+ String protoPrint = msg.toString();
+
+ assertTrue(protoPrint.contains(
+ "int32_to_bytes_field <\n key: 1\n value: \"\\\"\\000\"\n>"));
+ assertTrue(protoPrint.contains(
+ "int32_to_bytes_field <\n key: 2\n value: \"\\001\\010\"\n>"));
+ assertTrue(protoPrint.contains(
+ "string_to_int32_field <\n key: \"hello\"\n value: 1\n>"));
+ assertTrue(protoPrint.contains(
+ "string_to_int32_field <\n key: \"world\"\n value: 2\n>"));
+ assertTrue(protoPrint.contains(
+ "int32_to_message_field <\n key: 0\n value <\n value: 1\n"));
+ assertTrue(protoPrint.contains(
+ "int32_to_message_field <\n key: 1\n value <\n value: 2\n"));
+ assertTrue(protoPrint.contains(
+ "int32_to_enum_field <\n key: 1\n value: 2\n>"));
+ assertTrue(protoPrint.contains(
+ "int32_to_enum_field <\n key: 2\n value: 3\n>"));
+ }
+
public void testExtensions() throws Exception {
Extensions.ExtendableMessage message = new Extensions.ExtendableMessage();
message.field = 5;
@@ -3340,6 +3363,7 @@ public class NanoTest extends TestCase {
TestAllTypesNano.BAR,
TestAllTypesNano.BAZ
};
+ message.setOneofUint32(3);
return message;
}
@@ -3538,6 +3562,259 @@ public class NanoTest extends TestCase {
new NanoReferenceTypes.TestAllTypesNano(), MessageNano.toByteArray(m7))));
}
+ private static TestAllTypesNano generateMessageForOneof(int caseNumber) {
+ TestAllTypesNano result = new TestAllTypesNano();
+ TestAllTypesNano.NestedMessage nested =
+ new TestAllTypesNano.NestedMessage();
+ nested.bb = 2;
+ switch (caseNumber) {
+ case TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER:
+ result.setOneofUint32(1);
+ break;
+ case TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER:
+ result.setOneofEnum(TestAllTypesNano.BAR);
+ break;
+ case TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER:
+ result.setOneofNestedMessage(nested);
+ break;
+ case TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER:
+ result.setOneofBytes(new byte[] {1, 2});
+ break;
+ case TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER:
+ result.setOneofString("hello");
+ break;
+ case TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER:
+ result.setOneofFixed64(-1L);
+ break;
+ default:
+ throw new RuntimeException("unexpected case number: " + caseNumber);
+ }
+ return result;
+ }
+
+ public void testOneofHashCodeEquals() throws Exception {
+ TestAllTypesNano m1 = generateMessageForOneof(
+ TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+ assertEquals(m1, generateMessageForOneof(
+ TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER));
+ assertFalse(m1.equals(new TestAllTypesNano()));
+
+ TestAllTypesNano m2 = generateMessageForOneof(
+ TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+ assertEquals(m2, generateMessageForOneof(
+ TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER));
+ assertFalse(m2.equals(new TestAllTypesNano()));
+
+ TestAllTypesNano m3 = generateMessageForOneof(
+ TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+ assertEquals(m3, generateMessageForOneof(
+ TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER));
+ assertFalse(m3.equals(new TestAllTypesNano()));
+
+ TestAllTypesNano m4 = generateMessageForOneof(
+ TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+ assertEquals(m4, generateMessageForOneof(
+ TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER));
+ assertFalse(m4.equals(new TestAllTypesNano()));
+
+ TestAllTypesNano m5 = generateMessageForOneof(
+ TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER);
+ assertEquals(m5, generateMessageForOneof(
+ TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER));
+ assertFalse(m5.equals(new TestAllTypesNano()));
+
+ TestAllTypesNano m6 = generateMessageForOneof(
+ TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+ assertEquals(m6, generateMessageForOneof(
+ TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER));
+ assertFalse(m6.equals(new TestAllTypesNano()));
+
+ Map<TestAllTypesNano, Integer> map =
+ new HashMap<TestAllTypesNano, Integer>();
+ map.put(m1, 1);
+ map.put(m2, 2);
+ map.put(m3, 3);
+ map.put(m4, 4);
+ map.put(m5, 5);
+ map.put(m6, 6);
+
+ assertEquals(6, map.size());
+ }
+
+ private void checkOneofCase(TestAllTypesNano nano, int field)
+ throws Exception {
+ assertEquals(field, nano.getOneofFieldCase());
+ assertEquals(
+ field == TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER,
+ nano.hasOneofBytes());
+ assertEquals(
+ field == TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER,
+ nano.hasOneofEnum());
+ assertEquals(
+ field == TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER,
+ nano.hasOneofFixed64());
+ assertEquals(
+ field == TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER,
+ nano.hasOneofNestedMessage());
+ assertEquals(
+ field == TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER,
+ nano.hasOneofString());
+ assertEquals(
+ field == TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER,
+ nano.hasOneofUint32());
+
+ }
+
+ public void testOneofDefault() throws Exception {
+ TestAllTypesNano m1 = new TestAllTypesNano();
+ checkOneofCase(m1, 0);
+ assertEquals(WireFormatNano.EMPTY_BYTES, m1.getOneofBytes());
+ assertEquals(TestAllTypesNano.FOO, m1.getOneofEnum());
+ assertEquals(0L, m1.getOneofFixed64());
+ assertEquals(null, m1.getOneofNestedMessage());
+ assertEquals("", m1.getOneofString());
+ assertEquals(0, m1.getOneofUint32());
+ }
+
+ public void testOneofExclusiveness() throws Exception {
+ TestAllTypesNano m = new TestAllTypesNano();
+ checkOneofCase(m, 0);
+
+ m.setOneofBytes(new byte[]{0, 1});
+ checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+ assertTrue(Arrays.equals(new byte[]{0, 1}, m.getOneofBytes()));
+
+ m.setOneofEnum(TestAllTypesNano.BAZ);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+ assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+ assertEquals(WireFormatNano.EMPTY_BYTES, m.getOneofBytes());
+
+ m.setOneofFixed64(-1L);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+ assertEquals(-1L, m.getOneofFixed64());
+ assertEquals(TestAllTypesNano.FOO, m.getOneofEnum());
+
+ m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+ checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+ assertEquals(
+ new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage());
+ assertEquals(0L, m.getOneofFixed64());
+
+ m.setOneofString("hello");
+ checkOneofCase(m, TestAllTypesNano.ONEOF_STRING_FIELD_NUMBER);
+ assertEquals("hello", m.getOneofString());
+ assertNull(m.getOneofNestedMessage());
+
+ m.setOneofUint32(10);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+ assertEquals(10, m.getOneofUint32());
+ assertEquals("", m.getOneofString());
+
+ m.setOneofBytes(new byte[]{0, 1});
+ checkOneofCase(m, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+ assertTrue(Arrays.equals(new byte[]{0, 1}, m.getOneofBytes()));
+ assertEquals(0, m.getOneofUint32());
+ }
+
+ public void testOneofClear() throws Exception {
+ TestAllTypesNano m = new TestAllTypesNano();
+ m.setOneofBytes(new byte[]{0, 1});
+ m.clearOneofField();
+ checkOneofCase(m, 0);
+
+ m.setOneofEnum(TestAllTypesNano.BAZ);
+ m.clearOneofField();
+ checkOneofCase(m, 0);
+
+ m.setOneofFixed64(-1L);
+ m.clearOneofField();
+ checkOneofCase(m, 0);
+
+ m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+ m.clearOneofField();
+ checkOneofCase(m, 0);
+
+ m.setOneofString("hello");
+ m.clearOneofField();
+ checkOneofCase(m, 0);
+
+ m.setOneofUint32(10);
+ m.clearOneofField();
+ checkOneofCase(m, 0);
+ }
+
+ public void testOneofMarshaling() throws Exception {
+ TestAllTypesNano m = new TestAllTypesNano();
+ TestAllTypesNano parsed = new TestAllTypesNano();
+ {
+ m.setOneofBytes(new byte[]{0, 1});
+ byte[] serialized = MessageNano.toByteArray(m);
+ MessageNano.mergeFrom(parsed, serialized);
+ checkOneofCase(parsed, TestAllTypesNano.ONEOF_BYTES_FIELD_NUMBER);
+ assertTrue(Arrays.equals(new byte[]{0, 1}, parsed.getOneofBytes()));
+ }
+ {
+ m.setOneofEnum(TestAllTypesNano.BAZ);
+ byte[] serialized = MessageNano.toByteArray(m);
+ MessageNano.mergeFrom(parsed, serialized);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+ assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+ }
+ {
+ m.setOneofEnum(TestAllTypesNano.BAZ);
+ byte[] serialized = MessageNano.toByteArray(m);
+ MessageNano.mergeFrom(parsed, serialized);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+ assertEquals(TestAllTypesNano.BAZ, m.getOneofEnum());
+ }
+ {
+ m.setOneofFixed64(-1L);
+ byte[] serialized = MessageNano.toByteArray(m);
+ MessageNano.mergeFrom(parsed, serialized);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_FIXED64_FIELD_NUMBER);
+ assertEquals(-1L, m.getOneofFixed64());
+ }
+ {
+ m.setOneofNestedMessage(new TestAllTypesNano.NestedMessage());
+ byte[] serialized = MessageNano.toByteArray(m);
+ MessageNano.mergeFrom(parsed, serialized);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_NESTED_MESSAGE_FIELD_NUMBER);
+ assertEquals(
+ new TestAllTypesNano.NestedMessage(), m.getOneofNestedMessage());
+ }
+ {
+ m.setOneofString("hello");
+ byte[] serialized = MessageNano.toByteArray(m);
+ MessageNano.mergeFrom(parsed, serialized);
+ assertEquals("hello", m.getOneofString());
+ assertNull(m.getOneofNestedMessage());
+ }
+ {
+ m.setOneofUint32(10);
+ byte[] serialized = MessageNano.toByteArray(m);
+ MessageNano.mergeFrom(parsed, serialized);
+ checkOneofCase(m, TestAllTypesNano.ONEOF_UINT32_FIELD_NUMBER);
+ assertEquals(10, m.getOneofUint32());
+ }
+ }
+
+ public void testOneofSerializedConcat() throws Exception {
+ TestAllTypesNano m1 = new TestAllTypesNano();
+ m1.setOneofBytes(new byte[] {0, 1});
+ byte[] b1 = MessageNano.toByteArray(m1);
+ TestAllTypesNano m2 = new TestAllTypesNano();
+ m2.setOneofEnum(TestAllTypesNano.BAZ);
+ byte[] b2 = MessageNano.toByteArray(m2);
+ byte[] b3 = new byte[b1.length + b2.length];
+ System.arraycopy(b1, 0, b3, 0, b1.length);
+ System.arraycopy(b2, 0, b3, b1.length, b2.length);
+ TestAllTypesNano parsed = new TestAllTypesNano();
+ MessageNano.mergeFrom(parsed, b3);
+ // the last on the wire wins.
+ checkOneofCase(parsed, TestAllTypesNano.ONEOF_ENUM_FIELD_NUMBER);
+ assertEquals(TestAllTypesNano.BAZ, parsed.getOneofEnum());
+ }
+
public void testNullRepeatedFields() throws Exception {
// Check that serialization after explicitly setting a repeated field
// to null doesn't NPE.
@@ -3754,6 +4031,320 @@ public class NanoTest extends TestCase {
assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools));
}
+ public void testMapsSerializeAndParse() throws Exception {
+ TestMap origin = new TestMap();
+ setMapMessage(origin);
+ assertMapMessageSet(origin);
+
+ byte[] output = MessageNano.toByteArray(origin);
+ TestMap parsed = new TestMap();
+ MessageNano.mergeFrom(parsed, output);
+ }
+
+ public void testMapSerializeRejectNull() throws Exception {
+ TestMap primitiveMap = new TestMap();
+ primitiveMap.int32ToInt32Field = new HashMap<Integer, Integer>();
+ primitiveMap.int32ToInt32Field.put(null, 1);
+ try {
+ MessageNano.toByteArray(primitiveMap);
+ fail("should reject null keys");
+ } catch (IllegalStateException e) {
+ // pass.
+ }
+
+ TestMap messageMap = new TestMap();
+ messageMap.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ messageMap.int32ToMessageField.put(0, null);
+ try {
+ MessageNano.toByteArray(messageMap);
+ fail("should reject null values");
+ } catch (IllegalStateException e) {
+ // pass.
+ }
+ }
+
+ /**
+ * Tests that merging bytes containing conflicting keys with override the
+ * message value instead of merging the message value into the existing entry.
+ */
+ public void testMapMergeOverrideMessageValues() throws Exception {
+ TestMap.MessageValue origValue = new TestMap.MessageValue();
+ origValue.value = 1;
+ origValue.value2 = 2;
+ TestMap.MessageValue newValue = new TestMap.MessageValue();
+ newValue.value = 3;
+
+ TestMap origMessage = new TestMap();
+ origMessage.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ origMessage.int32ToMessageField.put(1, origValue);
+
+ TestMap newMessage = new TestMap();
+ newMessage.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ newMessage.int32ToMessageField.put(1, newValue);
+ MessageNano.mergeFrom(origMessage,
+ MessageNano.toByteArray(newMessage));
+ TestMap.MessageValue mergedValue = origMessage.int32ToMessageField.get(1);
+ assertEquals(3, mergedValue.value);
+ assertEquals(0, mergedValue.value2);
+ }
+
+ /**
+ * Tests that when merging with empty entries,
+ * we will use default for the key and value, instead of null.
+ */
+ public void testMapMergeEmptyEntry() throws Exception {
+ TestMap testMap = new TestMap();
+ byte[] buffer = new byte[1024];
+ CodedOutputByteBufferNano output =
+ CodedOutputByteBufferNano.newInstance(buffer);
+ // An empty entry for int32_to_int32 map.
+ output.writeTag(1, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(0);
+ // An empty entry for int32_to_message map.
+ output.writeTag(5, WireFormatNano.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(0);
+
+ CodedInputByteBufferNano input = CodedInputByteBufferNano.newInstance(
+ buffer, 0, buffer.length - output.spaceLeft());
+ testMap.mergeFrom(input);
+ assertNotNull(testMap.int32ToInt32Field);;
+ assertEquals(1, testMap.int32ToInt32Field.size());
+ assertEquals(Integer.valueOf(0), testMap.int32ToInt32Field.get(0));
+ assertNotNull(testMap.int32ToMessageField);
+ assertEquals(1, testMap.int32ToMessageField.size());
+ TestMap.MessageValue messageValue = testMap.int32ToMessageField.get(0);
+ assertNotNull(messageValue);
+ assertEquals(0, messageValue.value);
+ assertEquals(0, messageValue.value2);
+ }
+
+ public void testMapEquals() throws Exception {
+ TestMap a = new TestMap();
+ TestMap b = new TestMap();
+
+ // empty and null map fields are equal.
+ assertTestMapEqual(a, b);
+ a.int32ToBytesField = new HashMap<Integer, byte[]>();
+ assertTestMapEqual(a, b);
+
+ a.int32ToInt32Field = new HashMap<Integer, Integer>();
+ b.int32ToInt32Field = new HashMap<Integer, Integer>();
+ setMap(a.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values));
+ setMap(b.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values));
+ assertTestMapEqual(a, b);
+
+ a.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ b.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ setMap(a.int32ToMessageField,
+ deepCopy(int32Values), deepCopy(messageValues));
+ setMap(b.int32ToMessageField,
+ deepCopy(int32Values), deepCopy(messageValues));
+ assertTestMapEqual(a, b);
+
+ a.stringToInt32Field = new HashMap<String, Integer>();
+ b.stringToInt32Field = new HashMap<String, Integer>();
+ setMap(a.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values));
+ setMap(b.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values));
+ assertTestMapEqual(a, b);
+
+ a.int32ToBytesField = new HashMap<Integer, byte[]>();
+ b.int32ToBytesField = new HashMap<Integer, byte[]>();
+ setMap(a.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues));
+ setMap(b.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues));
+ assertTestMapEqual(a, b);
+
+ // Make sure the map implementation does not matter.
+ a.int32ToStringField = new TreeMap<Integer, String>();
+ b.int32ToStringField = new HashMap<Integer, String>();
+ setMap(a.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues));
+ setMap(b.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues));
+ assertTestMapEqual(a, b);
+
+ a.clear();
+ b.clear();
+
+ // unequal cases: different value
+ a.int32ToInt32Field = new HashMap<Integer, Integer>();
+ b.int32ToInt32Field = new HashMap<Integer, Integer>();
+ a.int32ToInt32Field.put(1, 1);
+ b.int32ToInt32Field.put(1, 2);
+ assertTestMapUnequal(a, b);
+ // unequal case: additional entry
+ b.int32ToInt32Field.put(1, 1);
+ b.int32ToInt32Field.put(2, 1);
+ assertTestMapUnequal(a, b);
+ a.int32ToInt32Field.put(2, 1);
+ assertTestMapEqual(a, b);
+
+ // unequal case: different message value.
+ a.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ b.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ MessageValue va = new MessageValue();
+ va.value = 1;
+ MessageValue vb = new MessageValue();
+ vb.value = 1;
+ a.int32ToMessageField.put(1, va);
+ b.int32ToMessageField.put(1, vb);
+ assertTestMapEqual(a, b);
+ vb.value = 2;
+ assertTestMapUnequal(a, b);
+ }
+
+ private static void assertTestMapEqual(TestMap a, TestMap b)
+ throws Exception {
+ assertEquals(a.hashCode(), b.hashCode());
+ assertTrue(a.equals(b));
+ assertTrue(b.equals(a));
+ }
+
+ private static void assertTestMapUnequal(TestMap a, TestMap b)
+ throws Exception {
+ assertFalse(a.equals(b));
+ assertFalse(b.equals(a));
+ }
+
+ private static final Integer[] int32Values = new Integer[] {
+ 0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE,
+ };
+
+ private static final Long[] int64Values = new Long[] {
+ 0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE,
+ };
+
+ private static final String[] stringValues = new String[] {
+ "", "hello", "world", "foo", "bar",
+ };
+
+ private static final byte[][] bytesValues = new byte[][] {
+ new byte[] {},
+ new byte[] {0},
+ new byte[] {1, -1},
+ new byte[] {127, -128},
+ new byte[] {'a', 'b', '0', '1'},
+ };
+
+ private static final Boolean[] boolValues = new Boolean[] {
+ false, true,
+ };
+
+ private static final Integer[] enumValues = new Integer[] {
+ TestMap.FOO, TestMap.BAR, TestMap.BAZ, TestMap.QUX,
+ Integer.MAX_VALUE /* unknown */,
+ };
+
+ private static final TestMap.MessageValue[] messageValues =
+ new TestMap.MessageValue[] {
+ newMapValueMessage(0),
+ newMapValueMessage(1),
+ newMapValueMessage(-1),
+ newMapValueMessage(Integer.MAX_VALUE),
+ newMapValueMessage(Integer.MIN_VALUE),
+ };
+
+ private static TestMap.MessageValue newMapValueMessage(int value) {
+ TestMap.MessageValue result = new TestMap.MessageValue();
+ result.value = value;
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T[] deepCopy(T[] orig) throws Exception {
+ if (orig instanceof MessageValue[]) {
+ MessageValue[] result = new MessageValue[orig.length];
+ for (int i = 0; i < orig.length; i++) {
+ result[i] = new MessageValue();
+ MessageNano.mergeFrom(
+ result[i], MessageNano.toByteArray((MessageValue) orig[i]));
+ }
+ return (T[]) result;
+ }
+ if (orig instanceof byte[][]) {
+ byte[][] result = new byte[orig.length][];
+ for (int i = 0; i < orig.length; i++) {
+ byte[] origBytes = (byte[]) orig[i];
+ result[i] = Arrays.copyOf(origBytes, origBytes.length);
+ }
+ }
+ return Arrays.copyOf(orig, orig.length);
+ }
+
+ private <K, V> void setMap(Map<K, V> map, K[] keys, V[] values) {
+ assert(keys.length == values.length);
+ for (int i = 0; i < keys.length; i++) {
+ map.put(keys[i], values[i]);
+ }
+ }
+
+ private <K, V> void assertMapSet(
+ Map<K, V> map, K[] keys, V[] values) throws Exception {
+ assert(keys.length == values.length);
+ for (int i = 0; i < values.length; i++) {
+ assertEquals(values[i], map.get(keys[i]));
+ }
+ assertEquals(keys.length, map.size());
+ }
+
+ private void setMapMessage(TestMap testMap) {
+ testMap.int32ToInt32Field = new HashMap<Integer, Integer>();
+ testMap.int32ToBytesField = new HashMap<Integer, byte[]>();
+ testMap.int32ToEnumField = new HashMap<Integer, Integer>();
+ testMap.int32ToMessageField =
+ new HashMap<Integer, MapTestProto.TestMap.MessageValue>();
+ testMap.int32ToStringField = new HashMap<Integer, String>();
+ testMap.stringToInt32Field = new HashMap<String, Integer>();
+ testMap.boolToBoolField = new HashMap<Boolean, Boolean>();
+ testMap.uint32ToUint32Field = new HashMap<Integer, Integer>();
+ testMap.sint32ToSint32Field = new HashMap<Integer, Integer>();
+ testMap.fixed32ToFixed32Field = new HashMap<Integer, Integer>();
+ testMap.sfixed32ToSfixed32Field = new HashMap<Integer, Integer>();
+ testMap.int64ToInt64Field = new HashMap<Long, Long>();
+ testMap.uint64ToUint64Field = new HashMap<Long, Long>();
+ testMap.sint64ToSint64Field = new HashMap<Long, Long>();
+ testMap.fixed64ToFixed64Field = new HashMap<Long, Long>();
+ testMap.sfixed64ToSfixed64Field = new HashMap<Long, Long>();
+ setMap(testMap.int32ToInt32Field, int32Values, int32Values);
+ setMap(testMap.int32ToBytesField, int32Values, bytesValues);
+ setMap(testMap.int32ToEnumField, int32Values, enumValues);
+ setMap(testMap.int32ToMessageField, int32Values, messageValues);
+ setMap(testMap.int32ToStringField, int32Values, stringValues);
+ setMap(testMap.stringToInt32Field, stringValues, int32Values);
+ setMap(testMap.boolToBoolField, boolValues, boolValues);
+ setMap(testMap.uint32ToUint32Field, int32Values, int32Values);
+ setMap(testMap.sint32ToSint32Field, int32Values, int32Values);
+ setMap(testMap.fixed32ToFixed32Field, int32Values, int32Values);
+ setMap(testMap.sfixed32ToSfixed32Field, int32Values, int32Values);
+ setMap(testMap.int64ToInt64Field, int64Values, int64Values);
+ setMap(testMap.uint64ToUint64Field, int64Values, int64Values);
+ setMap(testMap.sint64ToSint64Field, int64Values, int64Values);
+ setMap(testMap.fixed64ToFixed64Field, int64Values, int64Values);
+ setMap(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
+ }
+ private void assertMapMessageSet(TestMap testMap) throws Exception {
+ assertMapSet(testMap.int32ToInt32Field, int32Values, int32Values);
+ assertMapSet(testMap.int32ToBytesField, int32Values, bytesValues);
+ assertMapSet(testMap.int32ToEnumField, int32Values, enumValues);
+ assertMapSet(testMap.int32ToMessageField, int32Values, messageValues);
+ assertMapSet(testMap.int32ToStringField, int32Values, stringValues);
+ assertMapSet(testMap.stringToInt32Field, stringValues, int32Values);
+ assertMapSet(testMap.boolToBoolField, boolValues, boolValues);
+ assertMapSet(testMap.uint32ToUint32Field, int32Values, int32Values);
+ assertMapSet(testMap.sint32ToSint32Field, int32Values, int32Values);
+ assertMapSet(testMap.fixed32ToFixed32Field, int32Values, int32Values);
+ assertMapSet(testMap.sfixed32ToSfixed32Field, int32Values, int32Values);
+ assertMapSet(testMap.int64ToInt64Field, int64Values, int64Values);
+ assertMapSet(testMap.uint64ToUint64Field, int64Values, int64Values);
+ assertMapSet(testMap.sint64ToSint64Field, int64Values, int64Values);
+ assertMapSet(testMap.fixed64ToFixed64Field, int64Values, int64Values);
+ assertMapSet(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
+ }
+
private void assertRepeatedPackablesEqual(
NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) {
// Not using MessageNano.equals() -- that belongs to a separate test.
diff --git a/javanano/src/test/java/com/google/protobuf/nano/map_test.proto b/javanano/src/test/java/com/google/protobuf/nano/map_test.proto
new file mode 100644
index 00000000..f72833ad
--- /dev/null
+++ b/javanano/src/test/java/com/google/protobuf/nano/map_test.proto
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package map_test;
+
+option java_package = "com.google.protobuf.nano";
+option java_outer_classname = "MapTestProto";
+
+message TestMap {
+ message MessageValue {
+ int32 value = 1;
+ int32 value2 = 2;
+ }
+ enum EnumValue {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+
+ map<int32, int32> int32_to_int32_field = 1;
+ map<int32, string> int32_to_string_field = 2;
+ map<int32, bytes> int32_to_bytes_field = 3;
+ map<int32, EnumValue> int32_to_enum_field = 4;
+ map<int32, MessageValue> int32_to_message_field = 5;
+ map<string, int32> string_to_int32_field = 6;
+ map<bool, bool> bool_to_bool_field = 7;
+
+ // Test all the other primitive types. As the key and value are not coupled in
+ // the implementation, we do not test all the combinations of key/value pairs,
+ // so that we can keep the number of test cases manageable
+ map<uint32, uint32> uint32_to_uint32_field = 11;
+ map<sint32, sint32> sint32_to_sint32_field = 12;
+ map<fixed32, fixed32> fixed32_to_fixed32_field = 13;
+ map<sfixed32, sfixed32> sfixed32_to_sfixed32_field = 14;
+ map<int64, int64> int64_to_int64_field = 15;
+ map<uint64, uint64> uint64_to_uint64_field = 16;
+ map<sint64, sint64> sint64_to_sint64_field = 17;
+ map<fixed64, fixed64> fixed64_to_fixed64_field = 18;
+ map<sfixed64, sfixed64> sfixed64_to_sfixed64_field = 19;
+}
diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
index 4519533c..efaf5269 100644
--- a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
+++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto
@@ -167,6 +167,15 @@ message TestAllTypesNano {
// Try to fail with java reserved keywords
optional int32 synchronized = 96;
+
+ oneof oneof_field {
+ uint32 oneof_uint32 = 111;
+ NestedMessage oneof_nested_message = 112;
+ string oneof_string = 123;
+ bytes oneof_bytes = 124;
+ fixed64 oneof_fixed64 = 115;
+ NestedEnum oneof_enum = 116;
+ }
}
message ForeignMessageNano {
diff --git a/post_process_dist.sh b/post_process_dist.sh
index 733fa088..3c01ed8f 100755
--- a/post_process_dist.sh
+++ b/post_process_dist.sh
@@ -27,7 +27,7 @@ fi
set -ex
-LANGUAGES="cpp java python"
+LANGUAGES="cpp java javanano python ruby"
BASENAME=`basename $1 .tar.gz`
VERSION=${BASENAME:9}
diff --git a/python/README.txt b/python/README.md
index 7d852458..ee7e7213 100644
--- a/python/README.txt
+++ b/python/README.md
@@ -1,4 +1,8 @@
Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
Copyright 2008 Google Inc.
This directory contains the Python Protocol Buffers runtime library.
@@ -48,8 +52,9 @@ Installation
$ python setup.py build
$ python setup.py google_test
- If you want to test c++ implementation, run:
- $ python setup.py test --cpp_implementation
+ If you want to build/test c++ implementation, run:
+ $ python setup.py build --cpp_implementation
+ $ python setup.py google_test --cpp_implementation
If some tests fail, this library may not work correctly on your
system. Continue at your own risk.
@@ -64,9 +69,11 @@ Installation
5) Install:
- $ python setup.py install
- or:
- $ python setup.py install --cpp_implementation
+ $ python setup.py install
+
+ or:
+
+ $ python setup.py install --cpp_implementation
This step may require superuser privileges.
NOTE: To use C++ implementation, you need to install C++ protobuf runtime
@@ -92,8 +99,8 @@ To use the C++ implementation, you need to:
parent directory.
2) Export an environment variable:
- $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
- $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
+ $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
+ $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
You need to export this variable before running setup.py script to build and
install the extension. You must also set the variable at runtime, otherwise
@@ -102,4 +109,3 @@ change the default so that C++ implementation is used whenever it is available.
It is strongly recommended to run `python setup.py test` after setting the
variable to "cpp", so the tests will be against C++ implemented Python
messages.
-
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index ec3b0934..1345bd5f 100755
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -32,4 +32,4 @@
#
# Copyright 2007 Google Inc. All Rights Reserved.
-__version__ = '3.0.0-pre'
+__version__ = '3.0.0a3.dev0'
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index af571b7c..f7a58ca0 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -41,15 +41,13 @@ __author__ = 'robinson@google.com (Will Robinson)'
from google.protobuf.internal import api_implementation
+_USE_C_DESCRIPTORS = False
if api_implementation.Type() == 'cpp':
# Used by MakeDescriptor in cpp mode
import os
import uuid
-
- if api_implementation.Version() == 2:
- from google.protobuf.pyext import _message
- else:
- from google.protobuf.internal import cpp_message
+ from google.protobuf.pyext import _message
+ _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False)
class Error(Exception):
@@ -60,12 +58,29 @@ class TypeTransformationError(Error):
"""Error transforming between python proto type and corresponding C++ type."""
+if _USE_C_DESCRIPTORS:
+ # This metaclass allows to override the behavior of code like
+ # isinstance(my_descriptor, FieldDescriptor)
+ # and make it return True when the descriptor is an instance of the extension
+ # type written in C++.
+ class DescriptorMetaclass(type):
+ def __instancecheck__(cls, obj):
+ if super(DescriptorMetaclass, cls).__instancecheck__(obj):
+ return True
+ if isinstance(obj, cls._C_DESCRIPTOR_CLASS):
+ return True
+ return False
+else:
+ # The standard metaclass; nothing changes.
+ DescriptorMetaclass = type
+
+
class DescriptorBase(object):
"""Descriptors base class.
This class is the base of all descriptor classes. It provides common options
- related functionaility.
+ related functionality.
Attributes:
has_options: True if the descriptor has non-default options. Usually it
@@ -75,6 +90,12 @@ class DescriptorBase(object):
avoid some bootstrapping issues.
"""
+ __metaclass__ = DescriptorMetaclass
+ if _USE_C_DESCRIPTORS:
+ # The class, or tuple of classes, that are considered as "virtual
+ # subclasses" of this descriptor class.
+ _C_DESCRIPTOR_CLASS = ()
+
def __init__(self, options, options_class_name):
"""Initialize the descriptor given its options message and the name of the
class of the options message. The name of the class is required in case
@@ -235,13 +256,25 @@ class Descriptor(_NestedDescriptorBase):
file: (FileDescriptor) Reference to file descriptor.
"""
+ if _USE_C_DESCRIPTORS:
+ _C_DESCRIPTOR_CLASS = _message.Descriptor
+
+ def __new__(cls, name, full_name, filename, containing_type, fields,
+ nested_types, enum_types, extensions, options=None,
+ is_extendable=True, extension_ranges=None, oneofs=None,
+ file=None, serialized_start=None, serialized_end=None,
+ syntax=None):
+ _message.Message._CheckCalledFromGeneratedFile()
+ return _message.Message._GetMessageDescriptor(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
# name of the argument.
def __init__(self, name, full_name, filename, containing_type, fields,
nested_types, enum_types, extensions, options=None,
is_extendable=True, extension_ranges=None, oneofs=None,
- file=None, serialized_start=None, serialized_end=None): # pylint:disable=redefined-builtin
+ file=None, serialized_start=None, serialized_end=None,
+ syntax=None): # pylint:disable=redefined-builtin
"""Arguments to __init__() are as described in the description
of Descriptor fields above.
@@ -286,6 +319,7 @@ class Descriptor(_NestedDescriptorBase):
self.oneofs_by_name = dict((o.name, o) for o in self.oneofs)
for oneof in self.oneofs:
oneof.containing_type = self
+ self.syntax = syntax or "proto2"
def EnumValueName(self, enum, value):
"""Returns the string name of an enum value.
@@ -452,6 +486,19 @@ class FieldDescriptor(DescriptorBase):
FIRST_RESERVED_FIELD_NUMBER = 19000
LAST_RESERVED_FIELD_NUMBER = 19999
+ if _USE_C_DESCRIPTORS:
+ _C_DESCRIPTOR_CLASS = _message.FieldDescriptor
+
+ def __new__(cls, name, full_name, index, number, type, cpp_type, label,
+ default_value, message_type, enum_type, containing_type,
+ is_extension, extension_scope, options=None,
+ has_default_value=True, containing_oneof=None):
+ _message.Message._CheckCalledFromGeneratedFile()
+ if is_extension:
+ return _message.Message._GetExtensionDescriptor(full_name)
+ else:
+ return _message.Message._GetFieldDescriptor(full_name)
+
def __init__(self, name, full_name, index, number, type, cpp_type, label,
default_value, message_type, enum_type, containing_type,
is_extension, extension_scope, options=None,
@@ -481,20 +528,14 @@ class FieldDescriptor(DescriptorBase):
self.containing_oneof = containing_oneof
if api_implementation.Type() == 'cpp':
if is_extension:
- if api_implementation.Version() == 2:
- # pylint: disable=protected-access
- self._cdescriptor = (
- _message.Message._GetExtensionDescriptor(full_name))
- # pylint: enable=protected-access
- else:
- self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name)
+ # pylint: disable=protected-access
+ self._cdescriptor = (
+ _message.Message._GetExtensionDescriptor(full_name))
+ # pylint: enable=protected-access
else:
- if api_implementation.Version() == 2:
- # pylint: disable=protected-access
- self._cdescriptor = _message.Message._GetFieldDescriptor(full_name)
- # pylint: enable=protected-access
- else:
- self._cdescriptor = cpp_message.GetFieldDescriptor(full_name)
+ # pylint: disable=protected-access
+ self._cdescriptor = _message.Message._GetFieldDescriptor(full_name)
+ # pylint: enable=protected-access
else:
self._cdescriptor = None
@@ -544,6 +585,15 @@ class EnumDescriptor(_NestedDescriptorBase):
None to use default enum options.
"""
+ if _USE_C_DESCRIPTORS:
+ _C_DESCRIPTOR_CLASS = _message.EnumDescriptor
+
+ def __new__(cls, name, full_name, filename, values,
+ containing_type=None, options=None, file=None,
+ serialized_start=None, serialized_end=None):
+ _message.Message._CheckCalledFromGeneratedFile()
+ return _message.Message._GetEnumDescriptor(full_name)
+
def __init__(self, name, full_name, filename, values,
containing_type=None, options=None, file=None,
serialized_start=None, serialized_end=None):
@@ -588,6 +638,17 @@ class EnumValueDescriptor(DescriptorBase):
None to use default enum value options options.
"""
+ if _USE_C_DESCRIPTORS:
+ _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor
+
+ def __new__(cls, name, index, number, type=None, options=None):
+ _message.Message._CheckCalledFromGeneratedFile()
+ # There is no way we can build a complete EnumValueDescriptor with the
+ # given parameters (the name of the Enum is not known, for example).
+ # Fortunately generated files just pass it to the EnumDescriptor()
+ # constructor, which will ignore it, so returning None is good enough.
+ return None
+
def __init__(self, name, index, number, type=None, options=None):
"""Arguments are as described in the attribute description above."""
super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions')
@@ -611,6 +672,13 @@ class OneofDescriptor(object):
oneof can contain.
"""
+ if _USE_C_DESCRIPTORS:
+ _C_DESCRIPTOR_CLASS = _message.OneofDescriptor
+
+ def __new__(cls, name, full_name, index, containing_type, fields):
+ _message.Message._CheckCalledFromGeneratedFile()
+ return _message.Message._GetOneofDescriptor(full_name)
+
def __init__(self, name, full_name, index, containing_type, fields):
"""Arguments are as described in the attribute description above."""
self.name = name
@@ -704,6 +772,7 @@ class FileDescriptor(DescriptorBase):
name: name of file, relative to root of source tree.
package: name of the package
+ syntax: string indicating syntax of the file (can be "proto2" or "proto3")
serialized_pb: (str) Byte string of serialized
descriptor_pb2.FileDescriptorProto.
dependencies: List of other FileDescriptors this FileDescriptor depends on.
@@ -712,14 +781,31 @@ class FileDescriptor(DescriptorBase):
extensions_by_name: Dict of extension names and their descriptors.
"""
+ if _USE_C_DESCRIPTORS:
+ _C_DESCRIPTOR_CLASS = _message.FileDescriptor
+
+ def __new__(cls, name, package, options=None, serialized_pb=None,
+ 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
+ else:
+ return super(FileDescriptor, cls).__new__(cls)
+
def __init__(self, name, package, options=None, serialized_pb=None,
- dependencies=None):
+ dependencies=None, syntax=None):
"""Constructor."""
super(FileDescriptor, self).__init__(options, 'FileOptions')
self.message_types_by_name = {}
self.name = name
self.package = package
+ self.syntax = syntax or "proto2"
self.serialized_pb = serialized_pb
self.enum_types_by_name = {}
@@ -728,12 +814,9 @@ class FileDescriptor(DescriptorBase):
if (api_implementation.Type() == 'cpp' and
self.serialized_pb is not None):
- if api_implementation.Version() == 2:
- # pylint: disable=protected-access
- _message.Message._BuildFile(self.serialized_pb)
- # pylint: enable=protected-access
- else:
- cpp_message.BuildFile(self.serialized_pb)
+ # pylint: disable=protected-access
+ _message.Message._BuildFile(self.serialized_pb)
+ # pylint: enable=protected-access
def CopyToProto(self, proto):
"""Copies this to a descriptor_pb2.FileDescriptorProto.
@@ -754,7 +837,8 @@ def _ParseOptions(message, string):
return message
-def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True):
+def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True,
+ syntax=None):
"""Make a protobuf Descriptor given a DescriptorProto protobuf.
Handles nested descriptors. Note that this is limited to the scope of defining
@@ -766,6 +850,8 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True):
package: Optional package name for the new message Descriptor (string).
build_file_if_cpp: Update the C++ descriptor pool if api matches.
Set to False on recursion, so no duplicates are created.
+ syntax: The syntax/semantics that should be used. Set to "proto3" to get
+ proto3 field presence semantics.
Returns:
A Descriptor for protobuf messages.
"""
@@ -791,12 +877,13 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True):
else:
file_descriptor_proto.name = proto_name + '.proto'
- if api_implementation.Version() == 2:
- # pylint: disable=protected-access
- _message.Message._BuildFile(file_descriptor_proto.SerializeToString())
- # pylint: enable=protected-access
- else:
- cpp_message.BuildFile(file_descriptor_proto.SerializeToString())
+ # pylint: disable=protected-access
+ result = _message.Message._BuildFile(
+ file_descriptor_proto.SerializeToString())
+ # pylint: enable=protected-access
+
+ if _USE_C_DESCRIPTORS:
+ return result.message_types_by_name[desc_proto.name]
full_message_name = [desc_proto.name]
if package: full_message_name.insert(0, package)
@@ -819,7 +906,8 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True):
# used by fields in the message, so no loops are possible here.
nested_desc = MakeDescriptor(nested_proto,
package='.'.join(full_message_name),
- build_file_if_cpp=False)
+ build_file_if_cpp=False,
+ syntax=syntax)
nested_types[full_name] = nested_desc
fields = []
diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py
index bcac513a..7e7701f8 100644
--- a/python/google/protobuf/descriptor_pool.py
+++ b/python/google/protobuf/descriptor_pool.py
@@ -64,6 +64,9 @@ from google.protobuf import descriptor_database
from google.protobuf import text_encoding
+_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS
+
+
def _NormalizeFullyQualifiedName(name):
"""Remove leading period from fully-qualified type name.
@@ -271,58 +274,81 @@ class DescriptorPool(object):
file_descriptor = descriptor.FileDescriptor(
name=file_proto.name,
package=file_proto.package,
+ syntax=file_proto.syntax,
options=file_proto.options,
serialized_pb=file_proto.SerializeToString(),
dependencies=direct_deps)
- scope = {}
-
- # This loop extracts all the message and enum types from all the
- # dependencoes of the file_proto. This is necessary to create the
- # scope of available message types when defining the passed in
- # file proto.
- for dependency in built_deps:
- scope.update(self._ExtractSymbols(
- dependency.message_types_by_name.values()))
- scope.update((_PrefixWithDot(enum.full_name), enum)
- for enum in dependency.enum_types_by_name.values())
-
- for message_type in file_proto.message_type:
- message_desc = self._ConvertMessageDescriptor(
- message_type, file_proto.package, file_descriptor, scope)
- file_descriptor.message_types_by_name[message_desc.name] = message_desc
-
- for enum_type in file_proto.enum_type:
- file_descriptor.enum_types_by_name[enum_type.name] = (
- self._ConvertEnumDescriptor(enum_type, file_proto.package,
- file_descriptor, None, scope))
-
- for index, extension_proto in enumerate(file_proto.extension):
- extension_desc = self.MakeFieldDescriptor(
- extension_proto, file_proto.package, index, is_extension=True)
- extension_desc.containing_type = self._GetTypeFromScope(
- file_descriptor.package, extension_proto.extendee, scope)
- self.SetFieldType(extension_proto, extension_desc,
- file_descriptor.package, scope)
- file_descriptor.extensions_by_name[extension_desc.name] = extension_desc
-
- for desc_proto in file_proto.message_type:
- self.SetAllFieldTypes(file_proto.package, desc_proto, scope)
-
- if file_proto.package:
- desc_proto_prefix = _PrefixWithDot(file_proto.package)
+ if _USE_C_DESCRIPTORS:
+ # When using C++ descriptors, all objects defined in the file were added
+ # to the C++ database when the FileDescriptor was built above.
+ # Just add them to this descriptor pool.
+ def _AddMessageDescriptor(message_desc):
+ self._descriptors[message_desc.full_name] = message_desc
+ for nested in message_desc.nested_types:
+ _AddMessageDescriptor(nested)
+ for enum_type in message_desc.enum_types:
+ _AddEnumDescriptor(enum_type)
+ def _AddEnumDescriptor(enum_desc):
+ self._enum_descriptors[enum_desc.full_name] = enum_desc
+ for message_type in file_descriptor.message_types_by_name.values():
+ _AddMessageDescriptor(message_type)
+ for enum_type in file_descriptor.enum_types_by_name.values():
+ _AddEnumDescriptor(enum_type)
else:
- desc_proto_prefix = ''
+ scope = {}
+
+ # This loop extracts all the message and enum types from all the
+ # dependencies of the file_proto. This is necessary to create the
+ # scope of available message types when defining the passed in
+ # file proto.
+ for dependency in built_deps:
+ scope.update(self._ExtractSymbols(
+ dependency.message_types_by_name.values()))
+ scope.update((_PrefixWithDot(enum.full_name), enum)
+ for enum in dependency.enum_types_by_name.values())
+
+ for message_type in file_proto.message_type:
+ message_desc = self._ConvertMessageDescriptor(
+ message_type, file_proto.package, file_descriptor, scope,
+ file_proto.syntax)
+ file_descriptor.message_types_by_name[message_desc.name] = (
+ message_desc)
+
+ for enum_type in file_proto.enum_type:
+ file_descriptor.enum_types_by_name[enum_type.name] = (
+ self._ConvertEnumDescriptor(enum_type, file_proto.package,
+ file_descriptor, None, scope))
+
+ for index, extension_proto in enumerate(file_proto.extension):
+ extension_desc = self.MakeFieldDescriptor(
+ extension_proto, file_proto.package, index, is_extension=True)
+ extension_desc.containing_type = self._GetTypeFromScope(
+ file_descriptor.package, extension_proto.extendee, scope)
+ self.SetFieldType(extension_proto, extension_desc,
+ file_descriptor.package, scope)
+ file_descriptor.extensions_by_name[extension_desc.name] = (
+ extension_desc)
+
+ for desc_proto in file_proto.message_type:
+ self.SetAllFieldTypes(file_proto.package, desc_proto, scope)
+
+ if file_proto.package:
+ desc_proto_prefix = _PrefixWithDot(file_proto.package)
+ else:
+ desc_proto_prefix = ''
+
+ for desc_proto in file_proto.message_type:
+ desc = self._GetTypeFromScope(
+ desc_proto_prefix, desc_proto.name, scope)
+ file_descriptor.message_types_by_name[desc_proto.name] = desc
- for desc_proto in file_proto.message_type:
- desc = self._GetTypeFromScope(desc_proto_prefix, desc_proto.name, scope)
- file_descriptor.message_types_by_name[desc_proto.name] = desc
self.Add(file_proto)
self._file_descriptors[file_proto.name] = file_descriptor
return self._file_descriptors[file_proto.name]
def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None,
- scope=None):
+ scope=None, syntax=None):
"""Adds the proto to the pool in the specified package.
Args:
@@ -349,7 +375,8 @@ class DescriptorPool(object):
scope = {}
nested = [
- self._ConvertMessageDescriptor(nested, desc_name, file_desc, scope)
+ self._ConvertMessageDescriptor(
+ nested, desc_name, file_desc, scope, syntax)
for nested in desc_proto.nested_type]
enums = [
self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
@@ -383,7 +410,8 @@ class DescriptorPool(object):
extension_ranges=extension_ranges,
file=file_desc,
serialized_start=None,
- serialized_end=None)
+ serialized_end=None,
+ syntax=syntax)
for nested in desc.nested_types:
nested.containing_type = desc
for enum in desc.enum_types:
diff --git a/python/google/protobuf/internal/_parameterized.py b/python/google/protobuf/internal/_parameterized.py
new file mode 100755
index 00000000..6ed23308
--- /dev/null
+++ b/python/google/protobuf/internal/_parameterized.py
@@ -0,0 +1,438 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Adds support for parameterized tests to Python's unittest TestCase class.
+
+A parameterized test is a method in a test case that is invoked with different
+argument tuples.
+
+A simple example:
+
+ class AdditionExample(parameterized.ParameterizedTestCase):
+ @parameterized.Parameters(
+ (1, 2, 3),
+ (4, 5, 9),
+ (1, 1, 3))
+ def testAddition(self, op1, op2, result):
+ self.assertEquals(result, op1 + op2)
+
+
+Each invocation is a separate test case and properly isolated just
+like a normal test method, with its own setUp/tearDown cycle. In the
+example above, there are three separate testcases, one of which will
+fail due to an assertion error (1 + 1 != 3).
+
+Parameters for invididual test cases can be tuples (with positional parameters)
+or dictionaries (with named parameters):
+
+ class AdditionExample(parameterized.ParameterizedTestCase):
+ @parameterized.Parameters(
+ {'op1': 1, 'op2': 2, 'result': 3},
+ {'op1': 4, 'op2': 5, 'result': 9},
+ )
+ def testAddition(self, op1, op2, result):
+ self.assertEquals(result, op1 + op2)
+
+If a parameterized test fails, the error message will show the
+original test name (which is modified internally) and the arguments
+for the specific invocation, which are part of the string returned by
+the shortDescription() method on test cases.
+
+The id method of the test, used internally by the unittest framework,
+is also modified to show the arguments. To make sure that test names
+stay the same across several invocations, object representations like
+
+ >>> class Foo(object):
+ ... pass
+ >>> repr(Foo())
+ '<__main__.Foo object at 0x23d8610>'
+
+are turned into '<__main__.Foo>'. For even more descriptive names,
+especially in test logs, you can use the NamedParameters decorator. In
+this case, only tuples are supported, and the first parameters has to
+be a string (or an object that returns an apt name when converted via
+str()):
+
+ class NamedExample(parameterized.ParameterizedTestCase):
+ @parameterized.NamedParameters(
+ ('Normal', 'aa', 'aaa', True),
+ ('EmptyPrefix', '', 'abc', True),
+ ('BothEmpty', '', '', True))
+ def testStartsWith(self, prefix, string, result):
+ self.assertEquals(result, strings.startswith(prefix))
+
+Named tests also have the benefit that they can be run individually
+from the command line:
+
+ $ testmodule.py NamedExample.testStartsWithNormal
+ .
+ --------------------------------------------------------------------
+ Ran 1 test in 0.000s
+
+ OK
+
+Parameterized Classes
+=====================
+If invocation arguments are shared across test methods in a single
+ParameterizedTestCase class, instead of decorating all test methods
+individually, the class itself can be decorated:
+
+ @parameterized.Parameters(
+ (1, 2, 3)
+ (4, 5, 9))
+ class ArithmeticTest(parameterized.ParameterizedTestCase):
+ def testAdd(self, arg1, arg2, result):
+ self.assertEqual(arg1 + arg2, result)
+
+ def testSubtract(self, arg2, arg2, result):
+ self.assertEqual(result - arg1, arg2)
+
+Inputs from Iterables
+=====================
+If parameters should be shared across several test cases, or are dynamically
+created from other sources, a single non-tuple iterable can be passed into
+the decorator. This iterable will be used to obtain the test cases:
+
+ class AdditionExample(parameterized.ParameterizedTestCase):
+ @parameterized.Parameters(
+ c.op1, c.op2, c.result for c in testcases
+ )
+ def testAddition(self, op1, op2, result):
+ self.assertEquals(result, op1 + op2)
+
+
+Single-Argument Test Methods
+============================
+If a test method takes only one argument, the single argument does not need to
+be wrapped into a tuple:
+
+ class NegativeNumberExample(parameterized.ParameterizedTestCase):
+ @parameterized.Parameters(
+ -1, -3, -4, -5
+ )
+ def testIsNegative(self, arg):
+ self.assertTrue(IsNegative(arg))
+"""
+
+__author__ = 'tmarek@google.com (Torsten Marek)'
+
+import collections
+import functools
+import re
+import types
+import unittest
+import uuid
+
+from google.apputils import basetest
+
+ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>')
+_SEPARATOR = uuid.uuid1().hex
+_FIRST_ARG = object()
+_ARGUMENT_REPR = object()
+
+
+def _CleanRepr(obj):
+ return ADDR_RE.sub(r'<\1>', repr(obj))
+
+
+# Helper function formerly from the unittest module, removed from it in
+# Python 2.7.
+def _StrClass(cls):
+ return '%s.%s' % (cls.__module__, cls.__name__)
+
+
+def _NonStringIterable(obj):
+ return (isinstance(obj, collections.Iterable) and not
+ isinstance(obj, basestring))
+
+
+def _FormatParameterList(testcase_params):
+ if isinstance(testcase_params, collections.Mapping):
+ return ', '.join('%s=%s' % (argname, _CleanRepr(value))
+ for argname, value in testcase_params.iteritems())
+ elif _NonStringIterable(testcase_params):
+ return ', '.join(map(_CleanRepr, testcase_params))
+ else:
+ return _FormatParameterList((testcase_params,))
+
+
+class _ParameterizedTestIter(object):
+ """Callable and iterable class for producing new test cases."""
+
+ def __init__(self, test_method, testcases, naming_type):
+ """Returns concrete test functions for a test and a list of parameters.
+
+ The naming_type is used to determine the name of the concrete
+ functions as reported by the unittest framework. If naming_type is
+ _FIRST_ARG, the testcases must be tuples, and the first element must
+ have a string representation that is a valid Python identifier.
+
+ Args:
+ test_method: The decorated test method.
+ testcases: (list of tuple/dict) A list of parameter
+ tuples/dicts for individual test invocations.
+ naming_type: The test naming type, either _NAMED or _ARGUMENT_REPR.
+ """
+ self._test_method = test_method
+ self.testcases = testcases
+ self._naming_type = naming_type
+
+ def __call__(self, *args, **kwargs):
+ raise RuntimeError('You appear to be running a parameterized test case '
+ 'without having inherited from parameterized.'
+ 'ParameterizedTestCase. This is bad because none of '
+ 'your test cases are actually being run.')
+
+ def __iter__(self):
+ test_method = self._test_method
+ naming_type = self._naming_type
+
+ def MakeBoundParamTest(testcase_params):
+ @functools.wraps(test_method)
+ def BoundParamTest(self):
+ if isinstance(testcase_params, collections.Mapping):
+ test_method(self, **testcase_params)
+ elif _NonStringIterable(testcase_params):
+ test_method(self, *testcase_params)
+ else:
+ test_method(self, testcase_params)
+
+ if naming_type is _FIRST_ARG:
+ # Signal the metaclass that the name of the test function is unique
+ # and descriptive.
+ BoundParamTest.__x_use_name__ = True
+ BoundParamTest.__name__ += str(testcase_params[0])
+ testcase_params = testcase_params[1:]
+ elif naming_type is _ARGUMENT_REPR:
+ # __x_extra_id__ is used to pass naming information to the __new__
+ # method of TestGeneratorMetaclass.
+ # The metaclass will make sure to create a unique, but nondescriptive
+ # name for this test.
+ BoundParamTest.__x_extra_id__ = '(%s)' % (
+ _FormatParameterList(testcase_params),)
+ else:
+ raise RuntimeError('%s is not a valid naming type.' % (naming_type,))
+
+ BoundParamTest.__doc__ = '%s(%s)' % (
+ BoundParamTest.__name__, _FormatParameterList(testcase_params))
+ if test_method.__doc__:
+ BoundParamTest.__doc__ += '\n%s' % (test_method.__doc__,)
+ return BoundParamTest
+ return (MakeBoundParamTest(c) for c in self.testcases)
+
+
+def _IsSingletonList(testcases):
+ """True iff testcases contains only a single non-tuple element."""
+ return len(testcases) == 1 and not isinstance(testcases[0], tuple)
+
+
+def _ModifyClass(class_object, testcases, naming_type):
+ assert not getattr(class_object, '_id_suffix', None), (
+ 'Cannot add parameters to %s,'
+ ' which already has parameterized methods.' % (class_object,))
+ class_object._id_suffix = id_suffix = {}
+ for name, obj in class_object.__dict__.items():
+ if (name.startswith(unittest.TestLoader.testMethodPrefix)
+ and isinstance(obj, types.FunctionType)):
+ delattr(class_object, name)
+ methods = {}
+ _UpdateClassDictForParamTestCase(
+ methods, id_suffix, name,
+ _ParameterizedTestIter(obj, testcases, naming_type))
+ for name, meth in methods.iteritems():
+ setattr(class_object, name, meth)
+
+
+def _ParameterDecorator(naming_type, testcases):
+ """Implementation of the parameterization decorators.
+
+ Args:
+ naming_type: The naming type.
+ testcases: Testcase parameters.
+
+ Returns:
+ A function for modifying the decorated object.
+ """
+ def _Apply(obj):
+ if isinstance(obj, type):
+ _ModifyClass(
+ obj,
+ list(testcases) if not isinstance(testcases, collections.Sequence)
+ else testcases,
+ naming_type)
+ return obj
+ else:
+ return _ParameterizedTestIter(obj, testcases, naming_type)
+
+ if _IsSingletonList(testcases):
+ assert _NonStringIterable(testcases[0]), (
+ 'Single parameter argument must be a non-string iterable')
+ testcases = testcases[0]
+
+ return _Apply
+
+
+def Parameters(*testcases):
+ """A decorator for creating parameterized tests.
+
+ See the module docstring for a usage example.
+ Args:
+ *testcases: Parameters for the decorated method, either a single
+ iterable, or a list of tuples/dicts/objects (for tests
+ with only one argument).
+
+ Returns:
+ A test generator to be handled by TestGeneratorMetaclass.
+ """
+ return _ParameterDecorator(_ARGUMENT_REPR, testcases)
+
+
+def NamedParameters(*testcases):
+ """A decorator for creating parameterized tests.
+
+ See the module docstring for a usage example. The first element of
+ each parameter tuple should be a string and will be appended to the
+ name of the test method.
+
+ Args:
+ *testcases: Parameters for the decorated method, either a single
+ iterable, or a list of tuples.
+
+ Returns:
+ A test generator to be handled by TestGeneratorMetaclass.
+ """
+ return _ParameterDecorator(_FIRST_ARG, testcases)
+
+
+class TestGeneratorMetaclass(type):
+ """Metaclass for test cases with test generators.
+
+ A test generator is an iterable in a testcase that produces callables. These
+ callables must be single-argument methods. These methods are injected into
+ the class namespace and the original iterable is removed. If the name of the
+ iterable conforms to the test pattern, the injected methods will be picked
+ up as tests by the unittest framework.
+
+ In general, it is supposed to be used in conjuction with the
+ Parameters decorator.
+ """
+
+ def __new__(mcs, class_name, bases, dct):
+ dct['_id_suffix'] = id_suffix = {}
+ for name, obj in dct.items():
+ if (name.startswith(unittest.TestLoader.testMethodPrefix) and
+ _NonStringIterable(obj)):
+ iterator = iter(obj)
+ dct.pop(name)
+ _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator)
+
+ return type.__new__(mcs, class_name, bases, dct)
+
+
+def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator):
+ """Adds individual test cases to a dictionary.
+
+ Args:
+ dct: The target dictionary.
+ id_suffix: The dictionary for mapping names to test IDs.
+ name: The original name of the test case.
+ iterator: The iterator generating the individual test cases.
+ """
+ for idx, func in enumerate(iterator):
+ assert callable(func), 'Test generators must yield callables, got %r' % (
+ func,)
+ if getattr(func, '__x_use_name__', False):
+ new_name = func.__name__
+ else:
+ new_name = '%s%s%d' % (name, _SEPARATOR, idx)
+ assert new_name not in dct, (
+ 'Name of parameterized test case "%s" not unique' % (new_name,))
+ dct[new_name] = func
+ id_suffix[new_name] = getattr(func, '__x_extra_id__', '')
+
+
+class ParameterizedTestCase(basetest.TestCase):
+ """Base class for test cases using the Parameters decorator."""
+ __metaclass__ = TestGeneratorMetaclass
+
+ def _OriginalName(self):
+ return self._testMethodName.split(_SEPARATOR)[0]
+
+ def __str__(self):
+ return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__))
+
+ def id(self): # pylint: disable=invalid-name
+ """Returns the descriptive ID of the test.
+
+ This is used internally by the unittesting framework to get a name
+ for the test to be used in reports.
+
+ Returns:
+ The test id.
+ """
+ return '%s.%s%s' % (_StrClass(self.__class__),
+ self._OriginalName(),
+ self._id_suffix.get(self._testMethodName, ''))
+
+
+def CoopParameterizedTestCase(other_base_class):
+ """Returns a new base class with a cooperative metaclass base.
+
+ This enables the ParameterizedTestCase to be used in combination
+ with other base classes that have custom metaclasses, such as
+ mox.MoxTestBase.
+
+ Only works with metaclasses that do not override type.__new__.
+
+ Example:
+
+ import google3
+ import mox
+
+ from google3.testing.pybase import parameterized
+
+ class ExampleTest(parameterized.CoopParameterizedTestCase(mox.MoxTestBase)):
+ ...
+
+ Args:
+ other_base_class: (class) A test case base class.
+
+ Returns:
+ A new class object.
+ """
+ metaclass = type(
+ 'CoopMetaclass',
+ (other_base_class.__metaclass__,
+ TestGeneratorMetaclass), {})
+ return metaclass(
+ 'CoopParameterizedTestCase',
+ (other_base_class, ParameterizedTestCase), {})
diff --git a/python/google/protobuf/internal/api_implementation.cc b/python/google/protobuf/internal/api_implementation.cc
index 83db40b1..6db12e8d 100644
--- a/python/google/protobuf/internal/api_implementation.cc
+++ b/python/google/protobuf/internal/api_implementation.cc
@@ -50,10 +50,7 @@ namespace python {
// and
// PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
#ifdef PYTHON_PROTO2_CPP_IMPL_V1
-#if PY_MAJOR_VERSION >= 3
-#error "PYTHON_PROTO2_CPP_IMPL_V1 is not supported under Python 3."
-#endif
-static int kImplVersion = 1;
+#error "PYTHON_PROTO2_CPP_IMPL_V1 is no longer supported."
#else
#ifdef PYTHON_PROTO2_CPP_IMPL_V2
static int kImplVersion = 2;
@@ -62,14 +59,7 @@ static int kImplVersion = 2;
static int kImplVersion = 0;
#else
-// The defaults are set here. Python 3 uses the fast C++ APIv2 by default.
-// Python 2 still uses the Python version by default until some compatibility
-// issues can be worked around.
-#if PY_MAJOR_VERSION >= 3
-static int kImplVersion = 2;
-#else
-static int kImplVersion = 0;
-#endif
+static int kImplVersion = -1; // -1 means "Unspecified by compiler flags".
#endif // PYTHON_PROTO2_PYTHON_IMPL
#endif // PYTHON_PROTO2_CPP_IMPL_V2
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
index f7926c16..8ba4357c 100755
--- a/python/google/protobuf/internal/api_implementation.py
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -40,14 +40,33 @@ try:
# The compile-time constants in the _api_implementation module can be used to
# switch to a certain implementation of the Python API at build time.
_api_version = _api_implementation.api_version
- del _api_implementation
+ _proto_extension_modules_exist_in_build = True
except ImportError:
- _api_version = 0
+ _api_version = -1 # Unspecified by compiler flags.
+ _proto_extension_modules_exist_in_build = False
+
+if _api_version == 1:
+ raise ValueError('api_version=1 is no longer supported.')
+if _api_version < 0: # Still unspecified?
+ try:
+ # The presence of this module in a build allows the proto implementation to
+ # be upgraded merely via build deps rather than a compiler flag or the
+ # runtime environment variable.
+ # pylint: disable=g-import-not-at-top
+ from google.protobuf import _use_fast_cpp_protos
+ # Work around a known issue in the classic bootstrap .par import hook.
+ if not _use_fast_cpp_protos:
+ raise ImportError('_use_fast_cpp_protos import succeeded but was None')
+ del _use_fast_cpp_protos
+ _api_version = 2
+ except ImportError:
+ if _proto_extension_modules_exist_in_build:
+ if sys.version_info[0] >= 3: # Python 3 defaults to C++ impl v2.
+ _api_version = 2
+ # TODO(b/17427486): Make Python 2 default to C++ impl v2.
_default_implementation_type = (
- 'python' if _api_version == 0 else 'cpp')
-_default_version_str = (
- '1' if _api_version <= 1 else '2')
+ 'python' if _api_version <= 0 else 'cpp')
# This environment variable can be used to switch to a certain implementation
# of the Python API, overriding the compile-time constants in the
@@ -64,13 +83,12 @@ if _implementation_type != 'python':
# _api_implementation module. Right now only 1 and 2 are valid values. Any other
# value will be ignored.
_implementation_version_str = os.getenv(
- 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION',
- _default_version_str)
+ 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', '2')
-if _implementation_version_str not in ('1', '2'):
+if _implementation_version_str != '2':
raise ValueError(
- "unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: '" +
- _implementation_version_str + "' (supported versions: 1, 2)"
+ 'unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: "' +
+ _implementation_version_str + '" (supported versions: 2)'
)
_implementation_version = int(_implementation_version_str)
diff --git a/python/google/protobuf/internal/api_implementation_default_test.py b/python/google/protobuf/internal/api_implementation_default_test.py
deleted file mode 100644
index 78d5cf23..00000000
--- a/python/google/protobuf/internal/api_implementation_default_test.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc. All rights reserved.
-# https://developers.google.com/protocol-buffers/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Test that the api_implementation defaults are what we expect."""
-
-import os
-import sys
-# Clear environment implementation settings before the google3 imports.
-os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', None)
-os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', None)
-
-# pylint: disable=g-import-not-at-top
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-
-
-class ApiImplementationDefaultTest(basetest.TestCase):
-
- if sys.version_info.major <= 2:
-
- def testThatPythonIsTheDefault(self):
- """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail."""
- self.assertEqual('python', api_implementation.Type())
-
- else:
-
- def testThatCppApiV2IsTheDefault(self):
- """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail."""
- self.assertEqual('cpp', api_implementation.Type())
- self.assertEqual(2, api_implementation.Version())
-
-
-if __name__ == '__main__':
- basetest.main()
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index 20bfa857..d976f9e1 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -41,7 +41,6 @@ are:
__author__ = 'petar@google.com (Petar Petrov)'
-
class BaseContainer(object):
"""Base container class."""
@@ -119,15 +118,23 @@ class RepeatedScalarFieldContainer(BaseContainer):
self._message_listener.Modified()
def extend(self, elem_seq):
- """Extends by appending the given sequence. Similar to list.extend()."""
- if not elem_seq:
- return
+ """Extends by appending the given iterable. Similar to list.extend()."""
- new_values = []
- for elem in elem_seq:
- new_values.append(self._type_checker.CheckValue(elem))
- self._values.extend(new_values)
- self._message_listener.Modified()
+ if elem_seq is None:
+ return
+ try:
+ elem_seq_iter = iter(elem_seq)
+ except TypeError:
+ if not elem_seq:
+ # silently ignore falsy inputs :-/.
+ # TODO(ptucker): Deprecate this behavior. b/18413862
+ return
+ raise
+
+ new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter]
+ if new_values:
+ self._values.extend(new_values)
+ self._message_listener.Modified()
def MergeFrom(self, other):
"""Appends the contents of another repeated field of the same type to this
@@ -141,6 +148,12 @@ class RepeatedScalarFieldContainer(BaseContainer):
self._values.remove(elem)
self._message_listener.Modified()
+ def pop(self, key=-1):
+ """Removes and returns an item at a given index. Similar to list.pop()."""
+ value = self._values[key]
+ self.__delitem__(key)
+ return value
+
def __setitem__(self, key, value):
"""Sets the item on the specified position."""
if isinstance(key, slice): # PY3
@@ -245,6 +258,12 @@ class RepeatedCompositeFieldContainer(BaseContainer):
self._values.remove(elem)
self._message_listener.Modified()
+ def pop(self, key=-1):
+ """Removes and returns an item at a given index. Similar to list.pop()."""
+ value = self._values[key]
+ self.__delitem__(key)
+ return value
+
def __getslice__(self, start, stop):
"""Retrieves the subset of items from between the specified indices."""
return self._values[start:stop]
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
index a4b90608..0f500606 100755
--- a/python/google/protobuf/internal/decoder.py
+++ b/python/google/protobuf/internal/decoder.py
@@ -621,9 +621,6 @@ def MessageDecoder(field_number, is_repeated, is_packed, key, new_default):
if value is None:
value = field_dict.setdefault(key, new_default(message))
while 1:
- value = field_dict.get(key)
- if value is None:
- value = field_dict.setdefault(key, new_default(message))
# Read length.
(size, pos) = local_DecodeVarint(buffer, pos)
new_pos = pos + size
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 3924f21a..50c4dbba 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -34,12 +34,16 @@
__author__ = 'robinson@google.com (Will Robinson)'
+import sys
+
from google.apputils import basetest
from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
from google.protobuf import descriptor_pb2
+from google.protobuf.internal import api_implementation
from google.protobuf import descriptor
+from google.protobuf import symbol_database
from google.protobuf import text_format
@@ -51,41 +55,28 @@ name: 'TestEmptyMessage'
class DescriptorTest(basetest.TestCase):
def setUp(self):
- self.my_file = descriptor.FileDescriptor(
+ file_proto = descriptor_pb2.FileDescriptorProto(
name='some/filename/some.proto',
- package='protobuf_unittest'
- )
- self.my_enum = descriptor.EnumDescriptor(
- name='ForeignEnum',
- full_name='protobuf_unittest.ForeignEnum',
- filename=None,
- file=self.my_file,
- values=[
- descriptor.EnumValueDescriptor(name='FOREIGN_FOO', index=0, number=4),
- descriptor.EnumValueDescriptor(name='FOREIGN_BAR', index=1, number=5),
- descriptor.EnumValueDescriptor(name='FOREIGN_BAZ', index=2, number=6),
- ])
- self.my_message = descriptor.Descriptor(
- name='NestedMessage',
- full_name='protobuf_unittest.TestAllTypes.NestedMessage',
- filename=None,
- file=self.my_file,
- containing_type=None,
- fields=[
- descriptor.FieldDescriptor(
- name='bb',
- full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb',
- index=0, number=1,
- type=5, cpp_type=1, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None),
- ],
- nested_types=[],
- enum_types=[
- self.my_enum,
- ],
- extensions=[])
+ package='protobuf_unittest')
+ message_proto = file_proto.message_type.add(
+ name='NestedMessage')
+ message_proto.field.add(
+ name='bb',
+ number=1,
+ type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32,
+ label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL)
+ enum_proto = message_proto.enum_type.add(
+ name='ForeignEnum')
+ enum_proto.value.add(name='FOREIGN_FOO', number=4)
+ enum_proto.value.add(name='FOREIGN_BAR', number=5)
+ enum_proto.value.add(name='FOREIGN_BAZ', number=6)
+
+ descriptor_pool = symbol_database.Default().pool
+ descriptor_pool.Add(file_proto)
+ self.my_file = descriptor_pool.FindFileByName(file_proto.name)
+ self.my_message = self.my_file.message_types_by_name[message_proto.name]
+ self.my_enum = self.my_message.enum_types_by_name[enum_proto.name]
+
self.my_method = descriptor.MethodDescriptor(
name='Bar',
full_name='protobuf_unittest.TestService.Bar',
@@ -173,6 +164,11 @@ class DescriptorTest(basetest.TestCase):
self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2,
method_options.Extensions[method_opt1])
+ message_descriptor = (
+ unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR)
+ self.assertTrue(file_descriptor.has_options)
+ self.assertFalse(message_descriptor.has_options)
+
def testDifferentCustomOptionTypes(self):
kint32min = -2**31
kint64min = -2**63
@@ -394,6 +390,108 @@ class DescriptorTest(basetest.TestCase):
self.assertEqual(self.my_file.name, 'some/filename/some.proto')
self.assertEqual(self.my_file.package, 'protobuf_unittest')
+ @basetest.unittest.skipIf(
+ api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
+ 'Immutability of descriptors is only enforced in v2 implementation')
+ def testImmutableCppDescriptor(self):
+ message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+ with self.assertRaises(AttributeError):
+ message_descriptor.fields_by_name = None
+ with self.assertRaises(TypeError):
+ message_descriptor.fields_by_name['Another'] = None
+ with self.assertRaises(TypeError):
+ message_descriptor.fields.append(None)
+
+
+class GeneratedDescriptorTest(basetest.TestCase):
+ """Tests for the properties of descriptors in generated code."""
+
+ def CheckMessageDescriptor(self, message_descriptor):
+ # Basic properties
+ self.assertEqual(message_descriptor.name, 'TestAllTypes')
+ self.assertEqual(message_descriptor.full_name,
+ 'protobuf_unittest.TestAllTypes')
+ # Test equality and hashability
+ self.assertEqual(message_descriptor, message_descriptor)
+ self.assertEqual(message_descriptor.fields[0].containing_type,
+ message_descriptor)
+ self.assertIn(message_descriptor, [message_descriptor])
+ self.assertIn(message_descriptor, {message_descriptor: None})
+ # Test field containers
+ self.CheckDescriptorSequence(message_descriptor.fields)
+ self.CheckDescriptorMapping(message_descriptor.fields_by_name)
+ self.CheckDescriptorMapping(message_descriptor.fields_by_number)
+
+ def CheckFieldDescriptor(self, field_descriptor):
+ # Basic properties
+ self.assertEqual(field_descriptor.name, 'optional_int32')
+ self.assertEqual(field_descriptor.full_name,
+ 'protobuf_unittest.TestAllTypes.optional_int32')
+ self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes')
+ # Test equality and hashability
+ self.assertEqual(field_descriptor, field_descriptor)
+ self.assertEqual(
+ field_descriptor.containing_type.fields_by_name['optional_int32'],
+ field_descriptor)
+ self.assertIn(field_descriptor, [field_descriptor])
+ self.assertIn(field_descriptor, {field_descriptor: None})
+
+ def CheckDescriptorSequence(self, sequence):
+ # Verifies that a property like 'messageDescriptor.fields' has all the
+ # properties of an immutable abc.Sequence.
+ self.assertGreater(len(sequence), 0) # Sized
+ self.assertEqual(len(sequence), len(list(sequence))) # Iterable
+ item = sequence[0]
+ self.assertEqual(item, sequence[0])
+ self.assertIn(item, sequence) # Container
+ self.assertEqual(sequence.index(item), 0)
+ self.assertEqual(sequence.count(item), 1)
+ reversed_iterator = reversed(sequence)
+ self.assertEqual(list(reversed_iterator), list(sequence)[::-1])
+ self.assertRaises(StopIteration, next, reversed_iterator)
+
+ def CheckDescriptorMapping(self, mapping):
+ # Verifies that a property like 'messageDescriptor.fields' has all the
+ # properties of an immutable abc.Mapping.
+ self.assertGreater(len(mapping), 0) # Sized
+ self.assertEqual(len(mapping), len(list(mapping))) # Iterable
+ if sys.version_info.major >= 3:
+ key, item = next(iter(mapping.items()))
+ else:
+ key, item = mapping.items()[0]
+ self.assertIn(key, mapping) # Container
+ self.assertEqual(mapping.get(key), item)
+ # keys(), iterkeys() &co
+ item = (next(iter(mapping.keys())), next(iter(mapping.values())))
+ self.assertEqual(item, next(iter(mapping.items())))
+ if sys.version_info.major < 3:
+ def CheckItems(seq, iterator):
+ self.assertEqual(next(iterator), seq[0])
+ self.assertEqual(list(iterator), seq[1:])
+ CheckItems(mapping.keys(), mapping.iterkeys())
+ CheckItems(mapping.values(), mapping.itervalues())
+ CheckItems(mapping.items(), mapping.iteritems())
+
+ def testDescriptor(self):
+ message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+ self.CheckMessageDescriptor(message_descriptor)
+ field_descriptor = message_descriptor.fields_by_name['optional_int32']
+ self.CheckFieldDescriptor(field_descriptor)
+
+ def testCppDescriptorContainer(self):
+ # Check that the collection is still valid even if the parent disappeared.
+ enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum']
+ values = enum.values
+ del enum
+ self.assertEqual('FOO', values[0].name)
+
+ def testCppDescriptorContainer_Iterator(self):
+ # Same test with the iterator
+ enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum']
+ values_iter = iter(enum.values)
+ del enum
+ self.assertEqual('FOO', next(values_iter).name)
+
class DescriptorCopyToProtoTest(basetest.TestCase):
"""Tests for CopyTo functions of Descriptor."""
@@ -588,10 +686,12 @@ class DescriptorCopyToProtoTest(basetest.TestCase):
output_type: '.protobuf_unittest.BarResponse'
>
"""
- self._InternalTestCopyToProto(
- unittest_pb2.TestService.DESCRIPTOR,
- descriptor_pb2.ServiceDescriptorProto,
- TEST_SERVICE_ASCII)
+ # TODO(rocking): enable this test after the proto descriptor change is
+ # checked in.
+ #self._InternalTestCopyToProto(
+ # unittest_pb2.TestService.DESCRIPTOR,
+ # descriptor_pb2.ServiceDescriptorProto,
+ # TEST_SERVICE_ASCII)
class MakeDescriptorTest(basetest.TestCase):
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 42e2ad7e..ed1298af 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -48,9 +48,12 @@ import math
import operator
import pickle
import sys
+import unittest
from google.apputils import basetest
+from google.protobuf.internal import _parameterized
from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
from google.protobuf.internal import api_implementation
from google.protobuf.internal import test_util
from google.protobuf import message
@@ -69,88 +72,65 @@ def IsNegInf(val):
return isinf(val) and (val < 0)
+@_parameterized.Parameters(
+ (unittest_pb2),
+ (unittest_proto3_arena_pb2))
class MessageTest(basetest.TestCase):
- def testBadUtf8String(self):
+ def testBadUtf8String(self, message_module):
if api_implementation.Type() != 'python':
self.skipTest("Skipping testBadUtf8String, currently only the python "
"api implementation raises UnicodeDecodeError when a "
"string field contains bad utf-8.")
bad_utf8_data = test_util.GoldenFileData('bad_utf8_string')
with self.assertRaises(UnicodeDecodeError) as context:
- unittest_pb2.TestAllTypes.FromString(bad_utf8_data)
- self.assertIn('field: protobuf_unittest.TestAllTypes.optional_string',
- str(context.exception))
-
- def testGoldenMessage(self):
- golden_data = test_util.GoldenFileData(
- 'golden_message_oneof_implemented')
- golden_message = unittest_pb2.TestAllTypes()
- golden_message.ParseFromString(golden_data)
- test_util.ExpectAllFieldsSet(self, golden_message)
- self.assertEqual(golden_data, golden_message.SerializeToString())
- golden_copy = copy.deepcopy(golden_message)
- self.assertEqual(golden_data, golden_copy.SerializeToString())
+ message_module.TestAllTypes.FromString(bad_utf8_data)
+ self.assertIn('TestAllTypes.optional_string', str(context.exception))
+
+ def testGoldenMessage(self, message_module):
+ # Proto3 doesn't have the "default_foo" members or foreign enums,
+ # and doesn't preserve unknown fields, so for proto3 we use a golden
+ # message that doesn't have these fields set.
+ if message_module is unittest_pb2:
+ golden_data = test_util.GoldenFileData(
+ 'golden_message_oneof_implemented')
+ else:
+ golden_data = test_util.GoldenFileData('golden_message_proto3')
- def testGoldenExtensions(self):
- golden_data = test_util.GoldenFileData('golden_message')
- golden_message = unittest_pb2.TestAllExtensions()
+ golden_message = message_module.TestAllTypes()
golden_message.ParseFromString(golden_data)
- all_set = unittest_pb2.TestAllExtensions()
- test_util.SetAllExtensions(all_set)
- self.assertEquals(all_set, golden_message)
+ if message_module is unittest_pb2:
+ test_util.ExpectAllFieldsSet(self, golden_message)
self.assertEqual(golden_data, golden_message.SerializeToString())
golden_copy = copy.deepcopy(golden_message)
self.assertEqual(golden_data, golden_copy.SerializeToString())
- def testGoldenPackedMessage(self):
+ def testGoldenPackedMessage(self, message_module):
golden_data = test_util.GoldenFileData('golden_packed_fields_message')
- golden_message = unittest_pb2.TestPackedTypes()
+ golden_message = message_module.TestPackedTypes()
golden_message.ParseFromString(golden_data)
- all_set = unittest_pb2.TestPackedTypes()
+ all_set = message_module.TestPackedTypes()
test_util.SetAllPackedFields(all_set)
- self.assertEquals(all_set, golden_message)
+ self.assertEqual(all_set, golden_message)
self.assertEqual(golden_data, all_set.SerializeToString())
golden_copy = copy.deepcopy(golden_message)
self.assertEqual(golden_data, golden_copy.SerializeToString())
- def testGoldenPackedExtensions(self):
- golden_data = test_util.GoldenFileData('golden_packed_fields_message')
- golden_message = unittest_pb2.TestPackedExtensions()
- golden_message.ParseFromString(golden_data)
- all_set = unittest_pb2.TestPackedExtensions()
- test_util.SetAllPackedExtensions(all_set)
- self.assertEquals(all_set, golden_message)
- self.assertEqual(golden_data, all_set.SerializeToString())
- golden_copy = copy.deepcopy(golden_message)
- self.assertEqual(golden_data, golden_copy.SerializeToString())
-
- def testPickleSupport(self):
+ def testPickleSupport(self, message_module):
golden_data = test_util.GoldenFileData('golden_message')
- golden_message = unittest_pb2.TestAllTypes()
+ golden_message = message_module.TestAllTypes()
golden_message.ParseFromString(golden_data)
pickled_message = pickle.dumps(golden_message)
unpickled_message = pickle.loads(pickled_message)
- self.assertEquals(unpickled_message, golden_message)
-
-
- def testPickleIncompleteProto(self):
- golden_message = unittest_pb2.TestRequired(a=1)
- pickled_message = pickle.dumps(golden_message)
-
- unpickled_message = pickle.loads(pickled_message)
- self.assertEquals(unpickled_message, golden_message)
- self.assertEquals(unpickled_message.a, 1)
- # This is still an incomplete proto - so serializing should fail
- self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
+ self.assertEqual(unpickled_message, golden_message)
- def testPositiveInfinity(self):
+ 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')
- golden_message = unittest_pb2.TestAllTypes()
+ golden_message = message_module.TestAllTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(IsPosInf(golden_message.optional_float))
self.assertTrue(IsPosInf(golden_message.optional_double))
@@ -158,12 +138,12 @@ class MessageTest(basetest.TestCase):
self.assertTrue(IsPosInf(golden_message.repeated_double[0]))
self.assertEqual(golden_data, golden_message.SerializeToString())
- def testNegativeInfinity(self):
+ 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')
- golden_message = unittest_pb2.TestAllTypes()
+ golden_message = message_module.TestAllTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(IsNegInf(golden_message.optional_float))
self.assertTrue(IsNegInf(golden_message.optional_double))
@@ -171,12 +151,12 @@ class MessageTest(basetest.TestCase):
self.assertTrue(IsNegInf(golden_message.repeated_double[0]))
self.assertEqual(golden_data, golden_message.SerializeToString())
- def testNotANumber(self):
+ def testNotANumber(self, message_module):
golden_data = (b'\x5D\x00\x00\xC0\x7F'
b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F'
b'\xCD\x02\x00\x00\xC0\x7F'
b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F')
- golden_message = unittest_pb2.TestAllTypes()
+ golden_message = message_module.TestAllTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(isnan(golden_message.optional_float))
self.assertTrue(isnan(golden_message.optional_double))
@@ -188,47 +168,47 @@ class MessageTest(basetest.TestCase):
# verify the serialized string can be converted into a correctly
# behaving protocol buffer.
serialized = golden_message.SerializeToString()
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
message.ParseFromString(serialized)
self.assertTrue(isnan(message.optional_float))
self.assertTrue(isnan(message.optional_double))
self.assertTrue(isnan(message.repeated_float[0]))
self.assertTrue(isnan(message.repeated_double[0]))
- def testPositiveInfinityPacked(self):
+ def testPositiveInfinityPacked(self, message_module):
golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F'
b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F')
- golden_message = unittest_pb2.TestPackedTypes()
+ golden_message = message_module.TestPackedTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(IsPosInf(golden_message.packed_float[0]))
self.assertTrue(IsPosInf(golden_message.packed_double[0]))
self.assertEqual(golden_data, golden_message.SerializeToString())
- def testNegativeInfinityPacked(self):
+ def testNegativeInfinityPacked(self, message_module):
golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF'
b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF')
- golden_message = unittest_pb2.TestPackedTypes()
+ golden_message = message_module.TestPackedTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(IsNegInf(golden_message.packed_float[0]))
self.assertTrue(IsNegInf(golden_message.packed_double[0]))
self.assertEqual(golden_data, golden_message.SerializeToString())
- def testNotANumberPacked(self):
+ def testNotANumberPacked(self, message_module):
golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F'
b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F')
- golden_message = unittest_pb2.TestPackedTypes()
+ golden_message = message_module.TestPackedTypes()
golden_message.ParseFromString(golden_data)
self.assertTrue(isnan(golden_message.packed_float[0]))
self.assertTrue(isnan(golden_message.packed_double[0]))
serialized = golden_message.SerializeToString()
- message = unittest_pb2.TestPackedTypes()
+ message = message_module.TestPackedTypes()
message.ParseFromString(serialized)
self.assertTrue(isnan(message.packed_float[0]))
self.assertTrue(isnan(message.packed_double[0]))
- def testExtremeFloatValues(self):
- message = unittest_pb2.TestAllTypes()
+ def testExtremeFloatValues(self, message_module):
+ message = message_module.TestAllTypes()
# Most positive exponent, no significand bits set.
kMostPosExponentNoSigBits = math.pow(2, 127)
@@ -272,8 +252,8 @@ class MessageTest(basetest.TestCase):
message.ParseFromString(message.SerializeToString())
self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit)
- def testExtremeDoubleValues(self):
- message = unittest_pb2.TestAllTypes()
+ def testExtremeDoubleValues(self, message_module):
+ message = message_module.TestAllTypes()
# Most positive exponent, no significand bits set.
kMostPosExponentNoSigBits = math.pow(2, 1023)
@@ -317,43 +297,43 @@ class MessageTest(basetest.TestCase):
message.ParseFromString(message.SerializeToString())
self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit)
- def testFloatPrinting(self):
- message = unittest_pb2.TestAllTypes()
+ def testFloatPrinting(self, message_module):
+ message = message_module.TestAllTypes()
message.optional_float = 2.0
self.assertEqual(str(message), 'optional_float: 2.0\n')
- def testHighPrecisionFloatPrinting(self):
- message = unittest_pb2.TestAllTypes()
+ def testHighPrecisionFloatPrinting(self, message_module):
+ message = message_module.TestAllTypes()
message.optional_double = 0.12345678912345678
if sys.version_info.major >= 3:
self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n')
else:
self.assertEqual(str(message), 'optional_double: 0.123456789123\n')
- def testUnknownFieldPrinting(self):
- populated = unittest_pb2.TestAllTypes()
+ def testUnknownFieldPrinting(self, message_module):
+ populated = message_module.TestAllTypes()
test_util.SetAllNonLazyFields(populated)
- empty = unittest_pb2.TestEmptyMessage()
+ empty = message_module.TestEmptyMessage()
empty.ParseFromString(populated.SerializeToString())
self.assertEqual(str(empty), '')
- def testRepeatedNestedFieldIteration(self):
- msg = unittest_pb2.TestAllTypes()
+ def testRepeatedNestedFieldIteration(self, message_module):
+ msg = message_module.TestAllTypes()
msg.repeated_nested_message.add(bb=1)
msg.repeated_nested_message.add(bb=2)
msg.repeated_nested_message.add(bb=3)
msg.repeated_nested_message.add(bb=4)
- self.assertEquals([1, 2, 3, 4],
- [m.bb for m in msg.repeated_nested_message])
- self.assertEquals([4, 3, 2, 1],
- [m.bb for m in reversed(msg.repeated_nested_message)])
- self.assertEquals([4, 3, 2, 1],
- [m.bb for m in msg.repeated_nested_message[::-1]])
+ self.assertEqual([1, 2, 3, 4],
+ [m.bb for m in msg.repeated_nested_message])
+ self.assertEqual([4, 3, 2, 1],
+ [m.bb for m in reversed(msg.repeated_nested_message)])
+ self.assertEqual([4, 3, 2, 1],
+ [m.bb for m in msg.repeated_nested_message[::-1]])
- def testSortingRepeatedScalarFieldsDefaultComparator(self):
+ def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module):
"""Check some different types with the default comparator."""
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
# TODO(mattp): would testing more scalar types strengthen test?
message.repeated_int32.append(1)
@@ -388,9 +368,9 @@ class MessageTest(basetest.TestCase):
self.assertEqual(message.repeated_bytes[1], b'b')
self.assertEqual(message.repeated_bytes[2], b'c')
- def testSortingRepeatedScalarFieldsCustomComparator(self):
+ def testSortingRepeatedScalarFieldsCustomComparator(self, message_module):
"""Check some different types with custom comparator."""
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
message.repeated_int32.append(-3)
message.repeated_int32.append(-2)
@@ -408,9 +388,9 @@ class MessageTest(basetest.TestCase):
self.assertEqual(message.repeated_string[1], 'bb')
self.assertEqual(message.repeated_string[2], 'aaa')
- def testSortingRepeatedCompositeFieldsCustomComparator(self):
+ def testSortingRepeatedCompositeFieldsCustomComparator(self, message_module):
"""Check passing a custom comparator to sort a repeated composite field."""
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
message.repeated_nested_message.add().bb = 1
message.repeated_nested_message.add().bb = 3
@@ -426,9 +406,9 @@ class MessageTest(basetest.TestCase):
self.assertEqual(message.repeated_nested_message[4].bb, 5)
self.assertEqual(message.repeated_nested_message[5].bb, 6)
- def testRepeatedCompositeFieldSortArguments(self):
+ def testRepeatedCompositeFieldSortArguments(self, message_module):
"""Check sorting a repeated composite field using list.sort() arguments."""
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
get_bb = operator.attrgetter('bb')
cmp_bb = lambda a, b: cmp(a.bb, b.bb)
@@ -452,9 +432,9 @@ class MessageTest(basetest.TestCase):
self.assertEqual([k.bb for k in message.repeated_nested_message],
[6, 5, 4, 3, 2, 1])
- def testRepeatedScalarFieldSortArguments(self):
+ def testRepeatedScalarFieldSortArguments(self, message_module):
"""Check sorting a scalar field using list.sort() arguments."""
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
message.repeated_int32.append(-3)
message.repeated_int32.append(-2)
@@ -484,9 +464,9 @@ class MessageTest(basetest.TestCase):
message.repeated_string.sort(cmp=len_cmp, reverse=True)
self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c'])
- def testRepeatedFieldsComparable(self):
- m1 = unittest_pb2.TestAllTypes()
- m2 = unittest_pb2.TestAllTypes()
+ def testRepeatedFieldsComparable(self, message_module):
+ m1 = message_module.TestAllTypes()
+ m2 = message_module.TestAllTypes()
m1.repeated_int32.append(0)
m1.repeated_int32.append(1)
m1.repeated_int32.append(2)
@@ -519,55 +499,6 @@ class MessageTest(basetest.TestCase):
# TODO(anuraag): Implement extensiondict comparison in C++ and then add test
- def testParsingMerge(self):
- """Check the merge behavior when a required or optional field appears
- multiple times in the input."""
- messages = [
- unittest_pb2.TestAllTypes(),
- unittest_pb2.TestAllTypes(),
- unittest_pb2.TestAllTypes() ]
- messages[0].optional_int32 = 1
- messages[1].optional_int64 = 2
- messages[2].optional_int32 = 3
- messages[2].optional_string = 'hello'
-
- merged_message = unittest_pb2.TestAllTypes()
- merged_message.optional_int32 = 3
- merged_message.optional_int64 = 2
- merged_message.optional_string = 'hello'
-
- generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
- generator.field1.extend(messages)
- generator.field2.extend(messages)
- generator.field3.extend(messages)
- generator.ext1.extend(messages)
- generator.ext2.extend(messages)
- generator.group1.add().field1.MergeFrom(messages[0])
- generator.group1.add().field1.MergeFrom(messages[1])
- generator.group1.add().field1.MergeFrom(messages[2])
- generator.group2.add().field1.MergeFrom(messages[0])
- generator.group2.add().field1.MergeFrom(messages[1])
- generator.group2.add().field1.MergeFrom(messages[2])
-
- data = generator.SerializeToString()
- parsing_merge = unittest_pb2.TestParsingMerge()
- parsing_merge.ParseFromString(data)
-
- # Required and optional fields should be merged.
- self.assertEqual(parsing_merge.required_all_types, merged_message)
- self.assertEqual(parsing_merge.optional_all_types, merged_message)
- self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
- merged_message)
- self.assertEqual(parsing_merge.Extensions[
- unittest_pb2.TestParsingMerge.optional_ext],
- merged_message)
-
- # Repeated fields should not be merged.
- self.assertEqual(len(parsing_merge.repeated_all_types), 3)
- self.assertEqual(len(parsing_merge.repeatedgroup), 3)
- self.assertEqual(len(parsing_merge.Extensions[
- unittest_pb2.TestParsingMerge.repeated_ext]), 3)
-
def ensureNestedMessageExists(self, msg, attribute):
"""Make sure that a nested message object exists.
@@ -577,12 +508,28 @@ class MessageTest(basetest.TestCase):
getattr(msg, attribute)
self.assertFalse(msg.HasField(attribute))
- def testOneofGetCaseNonexistingField(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofGetCaseNonexistingField(self, message_module):
+ m = message_module.TestAllTypes()
self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field')
- def testOneofSemantics(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofDefaultValues(self, message_module):
+ m = message_module.TestAllTypes()
+ self.assertIs(None, m.WhichOneof('oneof_field'))
+ self.assertFalse(m.HasField('oneof_uint32'))
+
+ # Oneof is set even when setting it to a default value.
+ m.oneof_uint32 = 0
+ self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+ self.assertTrue(m.HasField('oneof_uint32'))
+ self.assertFalse(m.HasField('oneof_string'))
+
+ m.oneof_string = ""
+ self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+ self.assertTrue(m.HasField('oneof_string'))
+ self.assertFalse(m.HasField('oneof_uint32'))
+
+ def testOneofSemantics(self, message_module):
+ m = message_module.TestAllTypes()
self.assertIs(None, m.WhichOneof('oneof_field'))
m.oneof_uint32 = 11
@@ -604,96 +551,569 @@ class MessageTest(basetest.TestCase):
self.assertFalse(m.HasField('oneof_nested_message'))
self.assertTrue(m.HasField('oneof_bytes'))
- def testOneofCompositeFieldReadAccess(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofCompositeFieldReadAccess(self, message_module):
+ m = message_module.TestAllTypes()
m.oneof_uint32 = 11
self.ensureNestedMessageExists(m, 'oneof_nested_message')
self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
self.assertEqual(11, m.oneof_uint32)
- def testOneofHasField(self):
- m = unittest_pb2.TestAllTypes()
- self.assertFalse(m.HasField('oneof_field'))
+ def testOneofWhichOneof(self, message_module):
+ m = message_module.TestAllTypes()
+ self.assertIs(None, m.WhichOneof('oneof_field'))
+ if message_module is unittest_pb2:
+ self.assertFalse(m.HasField('oneof_field'))
+
m.oneof_uint32 = 11
- self.assertTrue(m.HasField('oneof_field'))
+ self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
+ if message_module is unittest_pb2:
+ self.assertTrue(m.HasField('oneof_field'))
+
m.oneof_bytes = b'bb'
- self.assertTrue(m.HasField('oneof_field'))
+ self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+
m.ClearField('oneof_bytes')
- self.assertFalse(m.HasField('oneof_field'))
+ self.assertIs(None, m.WhichOneof('oneof_field'))
+ if message_module is unittest_pb2:
+ self.assertFalse(m.HasField('oneof_field'))
- def testOneofClearField(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofClearField(self, message_module):
+ m = message_module.TestAllTypes()
m.oneof_uint32 = 11
m.ClearField('oneof_field')
- self.assertFalse(m.HasField('oneof_field'))
+ if message_module is unittest_pb2:
+ self.assertFalse(m.HasField('oneof_field'))
self.assertFalse(m.HasField('oneof_uint32'))
self.assertIs(None, m.WhichOneof('oneof_field'))
- def testOneofClearSetField(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofClearSetField(self, message_module):
+ m = message_module.TestAllTypes()
m.oneof_uint32 = 11
m.ClearField('oneof_uint32')
- self.assertFalse(m.HasField('oneof_field'))
+ if message_module is unittest_pb2:
+ self.assertFalse(m.HasField('oneof_field'))
self.assertFalse(m.HasField('oneof_uint32'))
self.assertIs(None, m.WhichOneof('oneof_field'))
- def testOneofClearUnsetField(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofClearUnsetField(self, message_module):
+ m = message_module.TestAllTypes()
m.oneof_uint32 = 11
self.ensureNestedMessageExists(m, 'oneof_nested_message')
m.ClearField('oneof_nested_message')
self.assertEqual(11, m.oneof_uint32)
- self.assertTrue(m.HasField('oneof_field'))
+ if message_module is unittest_pb2:
+ self.assertTrue(m.HasField('oneof_field'))
self.assertTrue(m.HasField('oneof_uint32'))
self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field'))
- def testOneofDeserialize(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofDeserialize(self, message_module):
+ m = message_module.TestAllTypes()
m.oneof_uint32 = 11
- m2 = unittest_pb2.TestAllTypes()
+ m2 = message_module.TestAllTypes()
m2.ParseFromString(m.SerializeToString())
self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
- def testOneofCopyFrom(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofCopyFrom(self, message_module):
+ m = message_module.TestAllTypes()
m.oneof_uint32 = 11
- m2 = unittest_pb2.TestAllTypes()
+ m2 = message_module.TestAllTypes()
m2.CopyFrom(m)
self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
- def testOneofNestedMergeFrom(self):
- m = unittest_pb2.NestedTestAllTypes()
+ def testOneofNestedMergeFrom(self, message_module):
+ m = message_module.NestedTestAllTypes()
m.payload.oneof_uint32 = 11
- m2 = unittest_pb2.NestedTestAllTypes()
+ m2 = message_module.NestedTestAllTypes()
m2.payload.oneof_bytes = b'bb'
m2.child.payload.oneof_bytes = b'bb'
m2.MergeFrom(m)
self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field'))
self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field'))
- def testOneofClear(self):
- m = unittest_pb2.TestAllTypes()
+ def testOneofMessageMergeFrom(self, message_module):
+ m = message_module.NestedTestAllTypes()
+ m.payload.oneof_nested_message.bb = 11
+ m.child.payload.oneof_nested_message.bb = 12
+ m2 = message_module.NestedTestAllTypes()
+ m2.payload.oneof_uint32 = 13
+ m2.MergeFrom(m)
+ self.assertEqual('oneof_nested_message',
+ m2.payload.WhichOneof('oneof_field'))
+ self.assertEqual('oneof_nested_message',
+ m2.child.payload.WhichOneof('oneof_field'))
+
+ def testOneofNestedMessageInit(self, message_module):
+ m = message_module.TestAllTypes(
+ oneof_nested_message=message_module.TestAllTypes.NestedMessage())
+ self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
+
+ def testOneofClear(self, message_module):
+ m = message_module.TestAllTypes()
m.oneof_uint32 = 11
m.Clear()
self.assertIsNone(m.WhichOneof('oneof_field'))
m.oneof_bytes = b'bb'
- self.assertTrue(m.HasField('oneof_field'))
+ self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field'))
+
+ def testAssignByteStringToUnicodeField(self, message_module):
+ """Assigning a byte string to a string field should result
+ in the value being converted to a Unicode string."""
+ m = message_module.TestAllTypes()
+ m.optional_string = str('')
+ self.assertTrue(isinstance(m.optional_string, unicode))
+# TODO(haberman): why are these tests Google-internal only?
- def testSortEmptyRepeatedCompositeContainer(self):
+ def testLongValuedSlice(self, message_module):
+ """It should be possible to use long-valued indicies in slices
+
+ This didn't used to work in the v2 C++ implementation.
+ """
+ m = message_module.TestAllTypes()
+
+ # Repeated scalar
+ m.repeated_int32.append(1)
+ sl = m.repeated_int32[long(0):long(len(m.repeated_int32))]
+ self.assertEqual(len(m.repeated_int32), len(sl))
+
+ # Repeated composite
+ m.repeated_nested_message.add().bb = 3
+ sl = m.repeated_nested_message[long(0):long(len(m.repeated_nested_message))]
+ self.assertEqual(len(m.repeated_nested_message), len(sl))
+
+ def testExtendShouldNotSwallowExceptions(self, message_module):
+ """This didn't use to work in the v2 C++ implementation."""
+ m = message_module.TestAllTypes()
+ with self.assertRaises(NameError) as _:
+ m.repeated_int32.extend(a for i in range(10)) # pylint: disable=undefined-variable
+ with self.assertRaises(NameError) as _:
+ m.repeated_nested_enum.extend(
+ a for i in range(10)) # pylint: disable=undefined-variable
+
+ FALSY_VALUES = [None, False, 0, 0.0, b'', u'', bytearray(), [], {}, set()]
+
+ def testExtendInt32WithNothing(self, message_module):
+ """Test no-ops extending repeated int32 fields."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_int32)
+
+ # TODO(ptucker): Deprecate this behavior. b/18413862
+ for falsy_value in MessageTest.FALSY_VALUES:
+ m.repeated_int32.extend(falsy_value)
+ self.assertSequenceEqual([], m.repeated_int32)
+
+ m.repeated_int32.extend([])
+ self.assertSequenceEqual([], m.repeated_int32)
+
+ def testExtendFloatWithNothing(self, message_module):
+ """Test no-ops extending repeated float fields."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_float)
+
+ # TODO(ptucker): Deprecate this behavior. b/18413862
+ for falsy_value in MessageTest.FALSY_VALUES:
+ m.repeated_float.extend(falsy_value)
+ self.assertSequenceEqual([], m.repeated_float)
+
+ m.repeated_float.extend([])
+ self.assertSequenceEqual([], m.repeated_float)
+
+ def testExtendStringWithNothing(self, message_module):
+ """Test no-ops extending repeated string fields."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_string)
+
+ # TODO(ptucker): Deprecate this behavior. b/18413862
+ for falsy_value in MessageTest.FALSY_VALUES:
+ m.repeated_string.extend(falsy_value)
+ self.assertSequenceEqual([], m.repeated_string)
+
+ m.repeated_string.extend([])
+ self.assertSequenceEqual([], m.repeated_string)
+
+ def testExtendInt32WithPythonList(self, message_module):
+ """Test extending repeated int32 fields with python lists."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_int32)
+ m.repeated_int32.extend([0])
+ self.assertSequenceEqual([0], m.repeated_int32)
+ m.repeated_int32.extend([1, 2])
+ self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
+ m.repeated_int32.extend([3, 4])
+ self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
+
+ def testExtendFloatWithPythonList(self, message_module):
+ """Test extending repeated float fields with python lists."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_float)
+ m.repeated_float.extend([0.0])
+ self.assertSequenceEqual([0.0], m.repeated_float)
+ m.repeated_float.extend([1.0, 2.0])
+ self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
+ m.repeated_float.extend([3.0, 4.0])
+ self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
+
+ def testExtendStringWithPythonList(self, message_module):
+ """Test extending repeated string fields with python lists."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_string)
+ m.repeated_string.extend([''])
+ self.assertSequenceEqual([''], m.repeated_string)
+ m.repeated_string.extend(['11', '22'])
+ self.assertSequenceEqual(['', '11', '22'], m.repeated_string)
+ m.repeated_string.extend(['33', '44'])
+ self.assertSequenceEqual(['', '11', '22', '33', '44'], m.repeated_string)
+
+ def testExtendStringWithString(self, message_module):
+ """Test extending repeated string fields with characters from a string."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_string)
+ m.repeated_string.extend('abc')
+ self.assertSequenceEqual(['a', 'b', 'c'], m.repeated_string)
+
+ class TestIterable(object):
+ """This iterable object mimics the behavior of numpy.array.
+
+ __nonzero__ fails for length > 1, and returns bool(item[0]) for length == 1.
+
+ """
+
+ def __init__(self, values=None):
+ self._list = values or []
+
+ def __nonzero__(self):
+ size = len(self._list)
+ if size == 0:
+ return False
+ if size == 1:
+ return bool(self._list[0])
+ raise ValueError('Truth value is ambiguous.')
+
+ def __len__(self):
+ return len(self._list)
+
+ def __iter__(self):
+ return self._list.__iter__()
+
+ def testExtendInt32WithIterable(self, message_module):
+ """Test extending repeated int32 fields with iterable."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_int32)
+ m.repeated_int32.extend(MessageTest.TestIterable([]))
+ self.assertSequenceEqual([], m.repeated_int32)
+ m.repeated_int32.extend(MessageTest.TestIterable([0]))
+ self.assertSequenceEqual([0], m.repeated_int32)
+ m.repeated_int32.extend(MessageTest.TestIterable([1, 2]))
+ self.assertSequenceEqual([0, 1, 2], m.repeated_int32)
+ m.repeated_int32.extend(MessageTest.TestIterable([3, 4]))
+ self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32)
+
+ def testExtendFloatWithIterable(self, message_module):
+ """Test extending repeated float fields with iterable."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_float)
+ m.repeated_float.extend(MessageTest.TestIterable([]))
+ self.assertSequenceEqual([], m.repeated_float)
+ m.repeated_float.extend(MessageTest.TestIterable([0.0]))
+ self.assertSequenceEqual([0.0], m.repeated_float)
+ m.repeated_float.extend(MessageTest.TestIterable([1.0, 2.0]))
+ self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float)
+ m.repeated_float.extend(MessageTest.TestIterable([3.0, 4.0]))
+ self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float)
+
+ def testExtendStringWithIterable(self, message_module):
+ """Test extending repeated string fields with iterable."""
+ m = message_module.TestAllTypes()
+ self.assertSequenceEqual([], m.repeated_string)
+ m.repeated_string.extend(MessageTest.TestIterable([]))
+ self.assertSequenceEqual([], m.repeated_string)
+ m.repeated_string.extend(MessageTest.TestIterable(['']))
+ self.assertSequenceEqual([''], m.repeated_string)
+ m.repeated_string.extend(MessageTest.TestIterable(['1', '2']))
+ self.assertSequenceEqual(['', '1', '2'], m.repeated_string)
+ m.repeated_string.extend(MessageTest.TestIterable(['3', '4']))
+ self.assertSequenceEqual(['', '1', '2', '3', '4'], m.repeated_string)
+
+ def testPickleRepeatedScalarContainer(self, message_module):
+ # TODO(tibell): The pure-Python implementation support pickling of
+ # scalar containers in *some* cases. For now the cpp2 version
+ # throws an exception to avoid a segfault. Investigate if we
+ # want to support pickling of these fields.
+ #
+ # For more information see: https://b2.corp.google.com/u/0/issues/18677897
+ if (api_implementation.Type() != 'cpp' or
+ api_implementation.Version() == 2):
+ return
+ m = message_module.TestAllTypes()
+ with self.assertRaises(pickle.PickleError) as _:
+ pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL)
+
+
+ def testSortEmptyRepeatedCompositeContainer(self, message_module):
"""Exercise a scenario that has led to segfaults in the past.
"""
- m = unittest_pb2.TestAllTypes()
+ m = message_module.TestAllTypes()
m.repeated_nested_message.sort()
- def testHasFieldOnRepeatedField(self):
+ def testHasFieldOnRepeatedField(self, message_module):
"""Using HasField on a repeated field should raise an exception.
"""
- m = unittest_pb2.TestAllTypes()
+ m = message_module.TestAllTypes()
with self.assertRaises(ValueError) as _:
m.HasField('repeated_int32')
+ def testRepeatedScalarFieldPop(self, message_module):
+ m = message_module.TestAllTypes()
+ with self.assertRaises(IndexError) as _:
+ m.repeated_int32.pop()
+ m.repeated_int32.extend(range(5))
+ self.assertEqual(4, m.repeated_int32.pop())
+ self.assertEqual(0, m.repeated_int32.pop(0))
+ self.assertEqual(2, m.repeated_int32.pop(1))
+ self.assertEqual([1, 3], m.repeated_int32)
+
+ def testRepeatedCompositeFieldPop(self, message_module):
+ m = message_module.TestAllTypes()
+ with self.assertRaises(IndexError) as _:
+ m.repeated_nested_message.pop()
+ for i in range(5):
+ n = m.repeated_nested_message.add()
+ n.bb = i
+ self.assertEqual(4, m.repeated_nested_message.pop().bb)
+ self.assertEqual(0, m.repeated_nested_message.pop(0).bb)
+ self.assertEqual(2, m.repeated_nested_message.pop(1).bb)
+ self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message])
+
+
+# Class to test proto2-only features (required, extensions, etc.)
+class Proto2Test(basetest.TestCase):
+
+ def testFieldPresence(self):
+ message = unittest_pb2.TestAllTypes()
+
+ self.assertFalse(message.HasField("optional_int32"))
+ self.assertFalse(message.HasField("optional_bool"))
+ self.assertFalse(message.HasField("optional_nested_message"))
+
+ with self.assertRaises(ValueError):
+ message.HasField("field_doesnt_exist")
+
+ with self.assertRaises(ValueError):
+ message.HasField("repeated_int32")
+ with self.assertRaises(ValueError):
+ message.HasField("repeated_nested_message")
+
+ self.assertEqual(0, message.optional_int32)
+ self.assertEqual(False, message.optional_bool)
+ self.assertEqual(0, message.optional_nested_message.bb)
+
+ # Fields are set even when setting the values to default values.
+ message.optional_int32 = 0
+ message.optional_bool = False
+ message.optional_nested_message.bb = 0
+ self.assertTrue(message.HasField("optional_int32"))
+ self.assertTrue(message.HasField("optional_bool"))
+ self.assertTrue(message.HasField("optional_nested_message"))
+
+ # Set the fields to non-default values.
+ message.optional_int32 = 5
+ message.optional_bool = True
+ message.optional_nested_message.bb = 15
+
+ self.assertTrue(message.HasField("optional_int32"))
+ self.assertTrue(message.HasField("optional_bool"))
+ self.assertTrue(message.HasField("optional_nested_message"))
+
+ # Clearing the fields unsets them and resets their value to default.
+ message.ClearField("optional_int32")
+ message.ClearField("optional_bool")
+ message.ClearField("optional_nested_message")
+
+ self.assertFalse(message.HasField("optional_int32"))
+ self.assertFalse(message.HasField("optional_bool"))
+ self.assertFalse(message.HasField("optional_nested_message"))
+ self.assertEqual(0, message.optional_int32)
+ self.assertEqual(False, message.optional_bool)
+ self.assertEqual(0, message.optional_nested_message.bb)
+
+ # TODO(tibell): The C++ implementations actually allows assignment
+ # of unknown enum values to *scalar* fields (but not repeated
+ # fields). Once checked enum fields becomes the default in the
+ # Python implementation, the C++ implementation should follow suit.
+ def testAssignInvalidEnum(self):
+ """It should not be possible to assign an invalid enum number to an
+ enum field."""
+ m = unittest_pb2.TestAllTypes()
+
+ with self.assertRaises(ValueError) as _:
+ m.optional_nested_enum = 1234567
+ self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567)
+
+ def testGoldenExtensions(self):
+ golden_data = test_util.GoldenFileData('golden_message')
+ golden_message = unittest_pb2.TestAllExtensions()
+ golden_message.ParseFromString(golden_data)
+ all_set = unittest_pb2.TestAllExtensions()
+ test_util.SetAllExtensions(all_set)
+ self.assertEqual(all_set, golden_message)
+ self.assertEqual(golden_data, golden_message.SerializeToString())
+ golden_copy = copy.deepcopy(golden_message)
+ self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+ def testGoldenPackedExtensions(self):
+ golden_data = test_util.GoldenFileData('golden_packed_fields_message')
+ golden_message = unittest_pb2.TestPackedExtensions()
+ golden_message.ParseFromString(golden_data)
+ all_set = unittest_pb2.TestPackedExtensions()
+ test_util.SetAllPackedExtensions(all_set)
+ self.assertEqual(all_set, golden_message)
+ self.assertEqual(golden_data, all_set.SerializeToString())
+ golden_copy = copy.deepcopy(golden_message)
+ self.assertEqual(golden_data, golden_copy.SerializeToString())
+
+ def testPickleIncompleteProto(self):
+ golden_message = unittest_pb2.TestRequired(a=1)
+ pickled_message = pickle.dumps(golden_message)
+
+ unpickled_message = pickle.loads(pickled_message)
+ self.assertEqual(unpickled_message, golden_message)
+ self.assertEqual(unpickled_message.a, 1)
+ # This is still an incomplete proto - so serializing should fail
+ self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
+
+
+ # TODO(haberman): this isn't really a proto2-specific test except that this
+ # message has a required field in it. Should probably be factored out so
+ # that we can test the other parts with proto3.
+ def testParsingMerge(self):
+ """Check the merge behavior when a required or optional field appears
+ multiple times in the input."""
+ messages = [
+ unittest_pb2.TestAllTypes(),
+ unittest_pb2.TestAllTypes(),
+ unittest_pb2.TestAllTypes() ]
+ messages[0].optional_int32 = 1
+ messages[1].optional_int64 = 2
+ messages[2].optional_int32 = 3
+ messages[2].optional_string = 'hello'
+
+ merged_message = unittest_pb2.TestAllTypes()
+ merged_message.optional_int32 = 3
+ merged_message.optional_int64 = 2
+ merged_message.optional_string = 'hello'
+
+ generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator()
+ generator.field1.extend(messages)
+ generator.field2.extend(messages)
+ generator.field3.extend(messages)
+ generator.ext1.extend(messages)
+ generator.ext2.extend(messages)
+ generator.group1.add().field1.MergeFrom(messages[0])
+ generator.group1.add().field1.MergeFrom(messages[1])
+ generator.group1.add().field1.MergeFrom(messages[2])
+ generator.group2.add().field1.MergeFrom(messages[0])
+ generator.group2.add().field1.MergeFrom(messages[1])
+ generator.group2.add().field1.MergeFrom(messages[2])
+
+ data = generator.SerializeToString()
+ parsing_merge = unittest_pb2.TestParsingMerge()
+ parsing_merge.ParseFromString(data)
+
+ # Required and optional fields should be merged.
+ self.assertEqual(parsing_merge.required_all_types, merged_message)
+ self.assertEqual(parsing_merge.optional_all_types, merged_message)
+ self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types,
+ merged_message)
+ self.assertEqual(parsing_merge.Extensions[
+ unittest_pb2.TestParsingMerge.optional_ext],
+ merged_message)
+
+ # Repeated fields should not be merged.
+ self.assertEqual(len(parsing_merge.repeated_all_types), 3)
+ self.assertEqual(len(parsing_merge.repeatedgroup), 3)
+ self.assertEqual(len(parsing_merge.Extensions[
+ unittest_pb2.TestParsingMerge.repeated_ext]), 3)
+
+
+# Class to test proto3-only features/behavior (updated field presence & enums)
+class Proto3Test(basetest.TestCase):
+
+ 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")
+ with self.assertRaises(ValueError):
+ message.HasField("optional_float")
+ with self.assertRaises(ValueError):
+ message.HasField("optional_string")
+ with self.assertRaises(ValueError):
+ message.HasField("optional_bool")
+
+ # But we can still test presence of submessage fields.
+ 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")
+
+ with self.assertRaises(ValueError):
+ message.HasField("repeated_int32")
+ with self.assertRaises(ValueError):
+ 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(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"))
+
+ # Set the fields to non-default values.
+ message.optional_int32 = 5
+ message.optional_float = 1.1
+ 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")
+
+ self.assertEqual(0, message.optional_int32)
+ self.assertEqual(0, message.optional_float)
+ self.assertEqual("", message.optional_string)
+ self.assertEqual(False, message.optional_bool)
+ self.assertEqual(0, message.optional_nested_message.bb)
+
+ def testAssignUnknownEnum(self):
+ """Assigning an unknown enum value is allowed and preserves the value."""
+ m = unittest_proto3_arena_pb2.TestAllTypes()
+
+ m.optional_nested_enum = 1234567
+ self.assertEqual(1234567, m.optional_nested_enum)
+ m.repeated_nested_enum.append(22334455)
+ self.assertEqual(22334455, m.repeated_nested_enum[0])
+ # Assignment is a different code path than append for the C++ impl.
+ m.repeated_nested_enum[0] = 7654321
+ self.assertEqual(7654321, m.repeated_nested_enum[0])
+ serialized = m.SerializeToString()
+
+ m2 = unittest_proto3_arena_pb2.TestAllTypes()
+ m2.ParseFromString(serialized)
+ self.assertEqual(1234567, m2.optional_nested_enum)
+ self.assertEqual(7654321, m2.repeated_nested_enum[0])
+
class ValidTypeNamesTest(basetest.TestCase):
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index 86b91c8a..54f584ae 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -219,12 +219,20 @@ def _AttachFieldHelpers(cls, field_descriptor):
def AddDecoder(wiretype, is_packed):
tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
- cls._decoders_by_tag[tag_bytes] = (
- type_checkers.TYPE_TO_DECODER[field_descriptor.type](
- field_descriptor.number, is_repeated, is_packed,
- field_descriptor, field_descriptor._default_constructor),
- field_descriptor if field_descriptor.containing_oneof is not None
- else None)
+ decode_type = field_descriptor.type
+ if (decode_type == _FieldDescriptor.TYPE_ENUM and
+ type_checkers.SupportsOpenEnums(field_descriptor)):
+ decode_type = _FieldDescriptor.TYPE_INT32
+
+ oneof_descriptor = None
+ 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)
+
+ cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor)
AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type],
False)
@@ -296,6 +304,8 @@ def _DefaultValueConstructorForField(field):
def MakeSubMessageDefault(message):
result = message_type._concrete_class()
result._SetListener(message._listener_for_children)
+ if field.containing_oneof:
+ message._UpdateOneofState(field)
return result
return MakeSubMessageDefault
@@ -476,6 +486,7 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls):
type_checker = type_checkers.GetTypeChecker(field)
default_value = field.default_value
valid_values = set()
+ is_proto3 = field.containing_type.syntax == "proto3"
def getter(self):
# TODO(protobuf-team): This may be broken since there may not be
@@ -483,15 +494,24 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls):
return self._fields.get(field, default_value)
getter.__module__ = None
getter.__doc__ = 'Getter for %s.' % proto_field_name
+
+ clear_when_set_to_default = is_proto3 and not field.containing_oneof
+
def field_setter(self, new_value):
# pylint: disable=protected-access
- self._fields[field] = type_checker.CheckValue(new_value)
+ # Testing the value for truthiness captures all of the proto3 defaults
+ # (0, 0.0, enum 0, and False).
+ new_value = type_checker.CheckValue(new_value)
+ if clear_when_set_to_default and not new_value:
+ self._fields.pop(field, None)
+ else:
+ self._fields[field] = new_value
# Check _cached_byte_size_dirty inline to improve performance, since scalar
# setters are called frequently.
if not self._cached_byte_size_dirty:
self._Modified()
- if field.containing_oneof is not None:
+ if field.containing_oneof:
def setter(self, new_value):
field_setter(self, new_value)
self._UpdateOneofState(field)
@@ -624,24 +644,35 @@ def _AddListFieldsMethod(message_descriptor, cls):
cls.ListFields = ListFields
+_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"'
+_Proto2HasError = 'Protocol message has no non-repeated field "%s"'
def _AddHasFieldMethod(message_descriptor, cls):
"""Helper for _AddMessageMethods()."""
- singular_fields = {}
+ is_proto3 = (message_descriptor.syntax == "proto3")
+ error_msg = _Proto3HasError if is_proto3 else _Proto2HasError
+
+ hassable_fields = {}
for field in message_descriptor.fields:
- if field.label != _FieldDescriptor.LABEL_REPEATED:
- singular_fields[field.name] = field
- # Fields inside oneofs are never repeated (enforced by the compiler).
- for field in message_descriptor.oneofs:
- singular_fields[field.name] = field
+ if field.label == _FieldDescriptor.LABEL_REPEATED:
+ continue
+ # For proto3, only submessages and fields inside a oneof have presence.
+ if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and
+ not field.containing_oneof):
+ continue
+ hassable_fields[field.name] = field
+
+ if not is_proto3:
+ # Fields inside oneofs are never repeated (enforced by the compiler).
+ for oneof in message_descriptor.oneofs:
+ hassable_fields[oneof.name] = oneof
def HasField(self, field_name):
try:
- field = singular_fields[field_name]
+ field = hassable_fields[field_name]
except KeyError:
- raise ValueError(
- 'Protocol message has no singular "%s" field.' % field_name)
+ raise ValueError(error_msg % field_name)
if isinstance(field, descriptor_mod.OneofDescriptor):
try:
@@ -871,6 +902,7 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
local_ReadTag = decoder.ReadTag
local_SkipField = decoder.SkipField
decoders_by_tag = cls._decoders_by_tag
+ is_proto3 = message_descriptor.syntax == "proto3"
def InternalParse(self, buffer, pos, end):
self._Modified()
@@ -884,9 +916,11 @@ def _AddMergeFromStringMethod(message_descriptor, cls):
new_pos = local_SkipField(buffer, new_pos, end, tag_bytes)
if new_pos == -1:
return pos
- if not unknown_field_list:
- unknown_field_list = self._unknown_fields = []
- unknown_field_list.append((tag_bytes, buffer[value_start_pos:new_pos]))
+ if not is_proto3:
+ if not unknown_field_list:
+ unknown_field_list = self._unknown_fields = []
+ unknown_field_list.append(
+ (tag_bytes, buffer[value_start_pos:new_pos]))
pos = new_pos
else:
pos = field_decoder(buffer, new_pos, end, self, field_dict)
@@ -1008,6 +1042,8 @@ def _AddMergeFromMethod(cls):
# Construct a new object to represent this field.
field_value = field._default_constructor(self)
fields[field] = field_value
+ if field.containing_oneof:
+ self._UpdateOneofState(field)
field_value.MergeFrom(value)
else:
self._fields[field] = value
@@ -1252,11 +1288,10 @@ class _ExtensionDict(object):
# It's slightly wasteful to lookup the type checker each time,
# but we expect this to be a vanishingly uncommon case anyway.
- type_checker = type_checkers.GetTypeChecker(
- extension_handle)
+ type_checker = type_checkers.GetTypeChecker(extension_handle)
# pylint: disable=protected-access
self._extended_message._fields[extension_handle] = (
- type_checker.CheckValue(value))
+ type_checker.CheckValue(value))
self._extended_message._Modified()
def _FindExtensionByName(self, name):
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 6b24b092..a62d9845 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -1792,6 +1792,17 @@ class ReflectionTest(basetest.TestCase):
# Just check the default value.
self.assertEqual(57, msg.inner.value)
+ @basetest.unittest.skipIf(
+ api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
+ 'CPPv2-specific test')
+ 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,
+ unittest_pb2.TestAllTypes().__getattribute__, 42)
+
# Since we had so many tests for protocol buffer equality, we broke these out
# into separate TestCase classes.
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index 787f4650..d84e3836 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -40,13 +40,19 @@ import os.path
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_pb2
+from google.protobuf import descriptor_pb2
+# Tests whether the given TestAllTypes message is proto2 or not.
+# This is used to gate several fields/features that only exist
+# for the proto2 version of the message.
+def IsProto2(message):
+ return message.DESCRIPTOR.syntax == "proto2"
def SetAllNonLazyFields(message):
"""Sets every non-lazy field in the message to a unique value.
Args:
- message: A unittest_pb2.TestAllTypes instance.
+ message: A TestAllTypes instance.
"""
#
@@ -77,7 +83,8 @@ def SetAllNonLazyFields(message):
message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ
message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ
- message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ
+ if IsProto2(message):
+ message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ
message.optional_string_piece = u'124'
message.optional_cord = u'125'
@@ -110,7 +117,8 @@ def SetAllNonLazyFields(message):
message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR)
message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR)
- message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR)
+ if IsProto2(message):
+ message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR)
message.repeated_string_piece.append(u'224')
message.repeated_cord.append(u'225')
@@ -140,7 +148,8 @@ def SetAllNonLazyFields(message):
message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ)
message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ)
- message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ)
+ if IsProto2(message):
+ message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ)
message.repeated_string_piece.append(u'324')
message.repeated_cord.append(u'325')
@@ -149,28 +158,29 @@ def SetAllNonLazyFields(message):
# Fields that have defaults.
#
- message.default_int32 = 401
- message.default_int64 = 402
- message.default_uint32 = 403
- message.default_uint64 = 404
- message.default_sint32 = 405
- message.default_sint64 = 406
- message.default_fixed32 = 407
- message.default_fixed64 = 408
- message.default_sfixed32 = 409
- message.default_sfixed64 = 410
- message.default_float = 411
- message.default_double = 412
- message.default_bool = False
- message.default_string = '415'
- message.default_bytes = b'416'
-
- message.default_nested_enum = unittest_pb2.TestAllTypes.FOO
- message.default_foreign_enum = unittest_pb2.FOREIGN_FOO
- message.default_import_enum = unittest_import_pb2.IMPORT_FOO
-
- message.default_string_piece = '424'
- message.default_cord = '425'
+ if IsProto2(message):
+ message.default_int32 = 401
+ message.default_int64 = 402
+ message.default_uint32 = 403
+ message.default_uint64 = 404
+ message.default_sint32 = 405
+ message.default_sint64 = 406
+ message.default_fixed32 = 407
+ message.default_fixed64 = 408
+ message.default_sfixed32 = 409
+ message.default_sfixed64 = 410
+ message.default_float = 411
+ message.default_double = 412
+ message.default_bool = False
+ message.default_string = '415'
+ message.default_bytes = b'416'
+
+ message.default_nested_enum = unittest_pb2.TestAllTypes.FOO
+ message.default_foreign_enum = unittest_pb2.FOREIGN_FOO
+ message.default_import_enum = unittest_import_pb2.IMPORT_FOO
+
+ message.default_string_piece = '424'
+ message.default_cord = '425'
message.oneof_uint32 = 601
message.oneof_nested_message.bb = 602
@@ -398,7 +408,8 @@ def ExpectAllFieldsSet(test_case, message):
test_case.assertTrue(message.HasField('optional_nested_enum'))
test_case.assertTrue(message.HasField('optional_foreign_enum'))
- test_case.assertTrue(message.HasField('optional_import_enum'))
+ if IsProto2(message):
+ test_case.assertTrue(message.HasField('optional_import_enum'))
test_case.assertTrue(message.HasField('optional_string_piece'))
test_case.assertTrue(message.HasField('optional_cord'))
@@ -430,8 +441,9 @@ def ExpectAllFieldsSet(test_case, message):
message.optional_nested_enum)
test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
message.optional_foreign_enum)
- test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
- message.optional_import_enum)
+ if IsProto2(message):
+ test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+ message.optional_import_enum)
# -----------------------------------------------------------------
@@ -457,7 +469,8 @@ def ExpectAllFieldsSet(test_case, message):
test_case.assertEqual(2, len(message.repeated_import_message))
test_case.assertEqual(2, len(message.repeated_nested_enum))
test_case.assertEqual(2, len(message.repeated_foreign_enum))
- test_case.assertEqual(2, len(message.repeated_import_enum))
+ if IsProto2(message):
+ test_case.assertEqual(2, len(message.repeated_import_enum))
test_case.assertEqual(2, len(message.repeated_string_piece))
test_case.assertEqual(2, len(message.repeated_cord))
@@ -488,8 +501,9 @@ def ExpectAllFieldsSet(test_case, message):
message.repeated_nested_enum[0])
test_case.assertEqual(unittest_pb2.FOREIGN_BAR,
message.repeated_foreign_enum[0])
- test_case.assertEqual(unittest_import_pb2.IMPORT_BAR,
- message.repeated_import_enum[0])
+ if IsProto2(message):
+ test_case.assertEqual(unittest_import_pb2.IMPORT_BAR,
+ message.repeated_import_enum[0])
test_case.assertEqual(301, message.repeated_int32[1])
test_case.assertEqual(302, message.repeated_int64[1])
@@ -517,53 +531,55 @@ def ExpectAllFieldsSet(test_case, message):
message.repeated_nested_enum[1])
test_case.assertEqual(unittest_pb2.FOREIGN_BAZ,
message.repeated_foreign_enum[1])
- test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
- message.repeated_import_enum[1])
+ if IsProto2(message):
+ test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ,
+ message.repeated_import_enum[1])
# -----------------------------------------------------------------
- test_case.assertTrue(message.HasField('default_int32'))
- test_case.assertTrue(message.HasField('default_int64'))
- test_case.assertTrue(message.HasField('default_uint32'))
- test_case.assertTrue(message.HasField('default_uint64'))
- test_case.assertTrue(message.HasField('default_sint32'))
- test_case.assertTrue(message.HasField('default_sint64'))
- test_case.assertTrue(message.HasField('default_fixed32'))
- test_case.assertTrue(message.HasField('default_fixed64'))
- test_case.assertTrue(message.HasField('default_sfixed32'))
- test_case.assertTrue(message.HasField('default_sfixed64'))
- test_case.assertTrue(message.HasField('default_float'))
- test_case.assertTrue(message.HasField('default_double'))
- test_case.assertTrue(message.HasField('default_bool'))
- test_case.assertTrue(message.HasField('default_string'))
- test_case.assertTrue(message.HasField('default_bytes'))
-
- test_case.assertTrue(message.HasField('default_nested_enum'))
- test_case.assertTrue(message.HasField('default_foreign_enum'))
- test_case.assertTrue(message.HasField('default_import_enum'))
-
- test_case.assertEqual(401, message.default_int32)
- test_case.assertEqual(402, message.default_int64)
- test_case.assertEqual(403, message.default_uint32)
- test_case.assertEqual(404, message.default_uint64)
- test_case.assertEqual(405, message.default_sint32)
- test_case.assertEqual(406, message.default_sint64)
- test_case.assertEqual(407, message.default_fixed32)
- test_case.assertEqual(408, message.default_fixed64)
- test_case.assertEqual(409, message.default_sfixed32)
- test_case.assertEqual(410, message.default_sfixed64)
- test_case.assertEqual(411, message.default_float)
- test_case.assertEqual(412, message.default_double)
- test_case.assertEqual(False, message.default_bool)
- test_case.assertEqual('415', message.default_string)
- test_case.assertEqual(b'416', message.default_bytes)
-
- test_case.assertEqual(unittest_pb2.TestAllTypes.FOO,
- message.default_nested_enum)
- test_case.assertEqual(unittest_pb2.FOREIGN_FOO,
- message.default_foreign_enum)
- test_case.assertEqual(unittest_import_pb2.IMPORT_FOO,
- message.default_import_enum)
+ if IsProto2(message):
+ test_case.assertTrue(message.HasField('default_int32'))
+ test_case.assertTrue(message.HasField('default_int64'))
+ test_case.assertTrue(message.HasField('default_uint32'))
+ test_case.assertTrue(message.HasField('default_uint64'))
+ test_case.assertTrue(message.HasField('default_sint32'))
+ test_case.assertTrue(message.HasField('default_sint64'))
+ test_case.assertTrue(message.HasField('default_fixed32'))
+ test_case.assertTrue(message.HasField('default_fixed64'))
+ test_case.assertTrue(message.HasField('default_sfixed32'))
+ test_case.assertTrue(message.HasField('default_sfixed64'))
+ test_case.assertTrue(message.HasField('default_float'))
+ test_case.assertTrue(message.HasField('default_double'))
+ test_case.assertTrue(message.HasField('default_bool'))
+ test_case.assertTrue(message.HasField('default_string'))
+ test_case.assertTrue(message.HasField('default_bytes'))
+
+ test_case.assertTrue(message.HasField('default_nested_enum'))
+ test_case.assertTrue(message.HasField('default_foreign_enum'))
+ test_case.assertTrue(message.HasField('default_import_enum'))
+
+ test_case.assertEqual(401, message.default_int32)
+ test_case.assertEqual(402, message.default_int64)
+ test_case.assertEqual(403, message.default_uint32)
+ test_case.assertEqual(404, message.default_uint64)
+ test_case.assertEqual(405, message.default_sint32)
+ test_case.assertEqual(406, message.default_sint64)
+ test_case.assertEqual(407, message.default_fixed32)
+ test_case.assertEqual(408, message.default_fixed64)
+ test_case.assertEqual(409, message.default_sfixed32)
+ test_case.assertEqual(410, message.default_sfixed64)
+ test_case.assertEqual(411, message.default_float)
+ test_case.assertEqual(412, message.default_double)
+ test_case.assertEqual(False, message.default_bool)
+ test_case.assertEqual('415', message.default_string)
+ test_case.assertEqual(b'416', message.default_bytes)
+
+ test_case.assertEqual(unittest_pb2.TestAllTypes.FOO,
+ message.default_nested_enum)
+ test_case.assertEqual(unittest_pb2.FOREIGN_FOO,
+ message.default_foreign_enum)
+ test_case.assertEqual(unittest_import_pb2.IMPORT_FOO,
+ message.default_import_enum)
def GoldenFile(filename):
@@ -594,7 +610,7 @@ def SetAllPackedFields(message):
"""Sets every field in the message to a unique value.
Args:
- message: A unittest_pb2.TestPackedTypes instance.
+ message: A TestPackedTypes instance.
"""
message.packed_int32.extend([601, 701])
message.packed_int64.extend([602, 702])
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 55e3c2c8..7d5813fb 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -37,13 +37,17 @@ __author__ = 'kenton@google.com (Kenton Varda)'
import re
from google.apputils import basetest
-from google.protobuf import text_format
+from google.protobuf.internal import _parameterized
+
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
from google.protobuf.internal import api_implementation
from google.protobuf.internal import test_util
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_mset_pb2
+from google.protobuf import text_format
-class TextFormatTest(basetest.TestCase):
+# Base class with some common functionality.
+class TextFormatBase(basetest.TestCase):
def ReadGolden(self, golden_filename):
with test_util.GoldenFile(golden_filename) as f:
@@ -57,73 +61,24 @@ class TextFormatTest(basetest.TestCase):
def CompareToGoldenText(self, text, golden_text):
self.assertMultiLineEqual(text, golden_text)
- def testPrintAllFields(self):
- message = unittest_pb2.TestAllTypes()
- test_util.SetAllFields(message)
- self.CompareToGoldenFile(
- self.RemoveRedundantZeros(text_format.MessageToString(message)),
- 'text_format_unittest_data_oneof_implemented.txt')
-
- def testPrintInIndexOrder(self):
- message = unittest_pb2.TestFieldOrderings()
- message.my_string = '115'
- message.my_int = 101
- message.my_float = 111
- message.optional_nested_message.oo = 0
- message.optional_nested_message.bb = 1
- self.CompareToGoldenText(
- self.RemoveRedundantZeros(text_format.MessageToString(
- message, use_index_order=True)),
- 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n'
- 'optional_nested_message {\n oo: 0\n bb: 1\n}\n')
- self.CompareToGoldenText(
- self.RemoveRedundantZeros(text_format.MessageToString(
- message)),
- 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n'
- 'optional_nested_message {\n bb: 1\n oo: 0\n}\n')
-
- def testPrintAllExtensions(self):
- message = unittest_pb2.TestAllExtensions()
- test_util.SetAllExtensions(message)
- self.CompareToGoldenFile(
- self.RemoveRedundantZeros(text_format.MessageToString(message)),
- 'text_format_unittest_extensions_data.txt')
-
- def testPrintAllFieldsPointy(self):
- message = unittest_pb2.TestAllTypes()
- test_util.SetAllFields(message)
- self.CompareToGoldenFile(
- self.RemoveRedundantZeros(
- text_format.MessageToString(message, pointy_brackets=True)),
- 'text_format_unittest_data_pointy_oneof.txt')
+ def RemoveRedundantZeros(self, text):
+ # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove
+ # these zeros in order to match the golden file.
+ text = text.replace('e+0','e+').replace('e+0','e+') \
+ .replace('e-0','e-').replace('e-0','e-')
+ # Floating point fields are printed with .0 suffix even if they are
+ # actualy integer numbers.
+ text = re.compile('\.0$', re.MULTILINE).sub('', text)
+ return text
- def testPrintAllExtensionsPointy(self):
- message = unittest_pb2.TestAllExtensions()
- test_util.SetAllExtensions(message)
- self.CompareToGoldenFile(
- self.RemoveRedundantZeros(text_format.MessageToString(
- message, pointy_brackets=True)),
- 'text_format_unittest_extensions_data_pointy.txt')
- def testPrintMessageSet(self):
- message = unittest_mset_pb2.TestMessageSetContainer()
- ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
- ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
- message.message_set.Extensions[ext1].i = 23
- message.message_set.Extensions[ext2].str = 'foo'
- self.CompareToGoldenText(
- text_format.MessageToString(message),
- 'message_set {\n'
- ' [protobuf_unittest.TestMessageSetExtension1] {\n'
- ' i: 23\n'
- ' }\n'
- ' [protobuf_unittest.TestMessageSetExtension2] {\n'
- ' str: \"foo\"\n'
- ' }\n'
- '}\n')
+@_parameterized.Parameters(
+ (unittest_pb2),
+ (unittest_proto3_arena_pb2))
+class TextFormatTest(TextFormatBase):
- def testPrintExotic(self):
- message = unittest_pb2.TestAllTypes()
+ def testPrintExotic(self, message_module):
+ message = message_module.TestAllTypes()
message.repeated_int64.append(-9223372036854775808)
message.repeated_uint64.append(18446744073709551615)
message.repeated_double.append(123.456)
@@ -142,61 +97,44 @@ class TextFormatTest(basetest.TestCase):
' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n'
'repeated_string: "\\303\\274\\352\\234\\237"\n')
- def testPrintExoticUnicodeSubclass(self):
+ def testPrintExoticUnicodeSubclass(self, message_module):
class UnicodeSub(unicode):
pass
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
message.repeated_string.append(UnicodeSub(u'\u00fc\ua71f'))
self.CompareToGoldenText(
text_format.MessageToString(message),
'repeated_string: "\\303\\274\\352\\234\\237"\n')
- def testPrintNestedMessageAsOneLine(self):
- message = unittest_pb2.TestAllTypes()
+ def testPrintNestedMessageAsOneLine(self, message_module):
+ message = message_module.TestAllTypes()
msg = message.repeated_nested_message.add()
msg.bb = 42
self.CompareToGoldenText(
text_format.MessageToString(message, as_one_line=True),
'repeated_nested_message { bb: 42 }')
- def testPrintRepeatedFieldsAsOneLine(self):
- message = unittest_pb2.TestAllTypes()
+ def testPrintRepeatedFieldsAsOneLine(self, message_module):
+ message = message_module.TestAllTypes()
message.repeated_int32.append(1)
message.repeated_int32.append(1)
message.repeated_int32.append(3)
- message.repeated_string.append("Google")
- message.repeated_string.append("Zurich")
+ message.repeated_string.append('Google')
+ message.repeated_string.append('Zurich')
self.CompareToGoldenText(
text_format.MessageToString(message, as_one_line=True),
'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 '
'repeated_string: "Google" repeated_string: "Zurich"')
- def testPrintNestedNewLineInStringAsOneLine(self):
- message = unittest_pb2.TestAllTypes()
- message.optional_string = "a\nnew\nline"
+ def testPrintNestedNewLineInStringAsOneLine(self, message_module):
+ message = message_module.TestAllTypes()
+ message.optional_string = 'a\nnew\nline'
self.CompareToGoldenText(
text_format.MessageToString(message, as_one_line=True),
'optional_string: "a\\nnew\\nline"')
- def testPrintMessageSetAsOneLine(self):
- message = unittest_mset_pb2.TestMessageSetContainer()
- ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
- ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
- message.message_set.Extensions[ext1].i = 23
- message.message_set.Extensions[ext2].str = 'foo'
- self.CompareToGoldenText(
- text_format.MessageToString(message, as_one_line=True),
- 'message_set {'
- ' [protobuf_unittest.TestMessageSetExtension1] {'
- ' i: 23'
- ' }'
- ' [protobuf_unittest.TestMessageSetExtension2] {'
- ' str: \"foo\"'
- ' }'
- ' }')
-
- def testPrintExoticAsOneLine(self):
- message = unittest_pb2.TestAllTypes()
+ def testPrintExoticAsOneLine(self, message_module):
+ message = message_module.TestAllTypes()
message.repeated_int64.append(-9223372036854775808)
message.repeated_uint64.append(18446744073709551615)
message.repeated_double.append(123.456)
@@ -216,8 +154,8 @@ class TextFormatTest(basetest.TestCase):
'"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""'
' repeated_string: "\\303\\274\\352\\234\\237"')
- def testRoundTripExoticAsOneLine(self):
- message = unittest_pb2.TestAllTypes()
+ def testRoundTripExoticAsOneLine(self, message_module):
+ message = message_module.TestAllTypes()
message.repeated_int64.append(-9223372036854775808)
message.repeated_uint64.append(18446744073709551615)
message.repeated_double.append(123.456)
@@ -229,7 +167,7 @@ class TextFormatTest(basetest.TestCase):
# Test as_utf8 = False.
wire_text = text_format.MessageToString(
message, as_one_line=True, as_utf8=False)
- parsed_message = unittest_pb2.TestAllTypes()
+ parsed_message = message_module.TestAllTypes()
r = text_format.Parse(wire_text, parsed_message)
self.assertIs(r, parsed_message)
self.assertEquals(message, parsed_message)
@@ -237,25 +175,25 @@ class TextFormatTest(basetest.TestCase):
# Test as_utf8 = True.
wire_text = text_format.MessageToString(
message, as_one_line=True, as_utf8=True)
- parsed_message = unittest_pb2.TestAllTypes()
+ parsed_message = message_module.TestAllTypes()
r = text_format.Parse(wire_text, parsed_message)
self.assertIs(r, parsed_message)
self.assertEquals(message, parsed_message,
'\n%s != %s' % (message, parsed_message))
- def testPrintRawUtf8String(self):
- message = unittest_pb2.TestAllTypes()
+ def testPrintRawUtf8String(self, message_module):
+ message = message_module.TestAllTypes()
message.repeated_string.append(u'\u00fc\ua71f')
text = text_format.MessageToString(message, as_utf8=True)
self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n')
- parsed_message = unittest_pb2.TestAllTypes()
+ parsed_message = message_module.TestAllTypes()
text_format.Parse(text, parsed_message)
self.assertEquals(message, parsed_message,
'\n%s != %s' % (message, parsed_message))
- def testPrintFloatFormat(self):
+ def testPrintFloatFormat(self, message_module):
# Check that float_format argument is passed to sub-message formatting.
- message = unittest_pb2.NestedTestAllTypes()
+ message = message_module.NestedTestAllTypes()
# We use 1.25 as it is a round number in binary. The proto 32-bit float
# will not gain additional imprecise digits as a 64-bit Python float and
# show up in its str. 32-bit 1.2 is noisy when extended to 64-bit:
@@ -285,85 +223,24 @@ class TextFormatTest(basetest.TestCase):
self.RemoveRedundantZeros(text_message),
'payload {{ {} {} {} {} }}'.format(*formatted_fields))
- def testMessageToString(self):
- message = unittest_pb2.ForeignMessage()
+ def testMessageToString(self, message_module):
+ message = message_module.ForeignMessage()
message.c = 123
self.assertEqual('c: 123\n', str(message))
- def RemoveRedundantZeros(self, text):
- # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove
- # these zeros in order to match the golden file.
- text = text.replace('e+0','e+').replace('e+0','e+') \
- .replace('e-0','e-').replace('e-0','e-')
- # Floating point fields are printed with .0 suffix even if they are
- # actualy integer numbers.
- text = re.compile('\.0$', re.MULTILINE).sub('', text)
- return text
-
- def testParseGolden(self):
- golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
- parsed_message = unittest_pb2.TestAllTypes()
- r = text_format.Parse(golden_text, parsed_message)
- self.assertIs(r, parsed_message)
-
- message = unittest_pb2.TestAllTypes()
- test_util.SetAllFields(message)
- self.assertEquals(message, parsed_message)
-
- def testParseGoldenExtensions(self):
- golden_text = '\n'.join(self.ReadGolden(
- 'text_format_unittest_extensions_data.txt'))
- parsed_message = unittest_pb2.TestAllExtensions()
- text_format.Parse(golden_text, parsed_message)
-
- message = unittest_pb2.TestAllExtensions()
- test_util.SetAllExtensions(message)
- self.assertEquals(message, parsed_message)
-
- def testParseAllFields(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseAllFields(self, message_module):
+ message = message_module.TestAllTypes()
test_util.SetAllFields(message)
ascii_text = text_format.MessageToString(message)
- parsed_message = unittest_pb2.TestAllTypes()
- text_format.Parse(ascii_text, parsed_message)
- self.assertEqual(message, parsed_message)
- test_util.ExpectAllFieldsSet(self, message)
-
- def testParseAllExtensions(self):
- message = unittest_pb2.TestAllExtensions()
- test_util.SetAllExtensions(message)
- ascii_text = text_format.MessageToString(message)
-
- parsed_message = unittest_pb2.TestAllExtensions()
+ parsed_message = message_module.TestAllTypes()
text_format.Parse(ascii_text, parsed_message)
self.assertEqual(message, parsed_message)
+ if message_module is unittest_pb2:
+ test_util.ExpectAllFieldsSet(self, message)
- def testParseMessageSet(self):
- message = unittest_pb2.TestAllTypes()
- text = ('repeated_uint64: 1\n'
- 'repeated_uint64: 2\n')
- text_format.Parse(text, message)
- self.assertEqual(1, message.repeated_uint64[0])
- self.assertEqual(2, message.repeated_uint64[1])
-
- message = unittest_mset_pb2.TestMessageSetContainer()
- text = ('message_set {\n'
- ' [protobuf_unittest.TestMessageSetExtension1] {\n'
- ' i: 23\n'
- ' }\n'
- ' [protobuf_unittest.TestMessageSetExtension2] {\n'
- ' str: \"foo\"\n'
- ' }\n'
- '}\n')
- text_format.Parse(text, message)
- ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
- ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
- self.assertEquals(23, message.message_set.Extensions[ext1].i)
- self.assertEquals('foo', message.message_set.Extensions[ext2].str)
-
- def testParseExotic(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseExotic(self, message_module):
+ message = message_module.TestAllTypes()
text = ('repeated_int64: -9223372036854775808\n'
'repeated_uint64: 18446744073709551615\n'
'repeated_double: 123.456\n'
@@ -388,8 +265,8 @@ class TextFormatTest(basetest.TestCase):
self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2])
self.assertEqual(u'\u00fc', message.repeated_string[3])
- def testParseTrailingCommas(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseTrailingCommas(self, message_module):
+ message = message_module.TestAllTypes()
text = ('repeated_int64: 100;\n'
'repeated_int64: 200;\n'
'repeated_int64: 300,\n'
@@ -403,51 +280,37 @@ class TextFormatTest(basetest.TestCase):
self.assertEqual(u'one', message.repeated_string[0])
self.assertEqual(u'two', message.repeated_string[1])
- def testParseEmptyText(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseEmptyText(self, message_module):
+ message = message_module.TestAllTypes()
text = ''
text_format.Parse(text, message)
- self.assertEquals(unittest_pb2.TestAllTypes(), message)
+ self.assertEquals(message_module.TestAllTypes(), message)
- def testParseInvalidUtf8(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseInvalidUtf8(self, message_module):
+ message = message_module.TestAllTypes()
text = 'repeated_string: "\\xc3\\xc3"'
self.assertRaises(text_format.ParseError, text_format.Parse, text, message)
- def testParseSingleWord(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseSingleWord(self, message_module):
+ message = message_module.TestAllTypes()
text = 'foo'
- self.assertRaisesWithLiteralMatch(
+ self.assertRaisesRegexp(
text_format.ParseError,
- ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
- '"foo".'),
+ (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+ r'"foo".'),
text_format.Parse, text, message)
- def testParseUnknownField(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseUnknownField(self, message_module):
+ message = message_module.TestAllTypes()
text = 'unknown_field: 8\n'
- self.assertRaisesWithLiteralMatch(
+ self.assertRaisesRegexp(
text_format.ParseError,
- ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named '
- '"unknown_field".'),
+ (r'1:1 : Message type "\w+.TestAllTypes" has no field named '
+ r'"unknown_field".'),
text_format.Parse, text, message)
- def testParseBadExtension(self):
- message = unittest_pb2.TestAllExtensions()
- text = '[unknown_extension]: 8\n'
- self.assertRaisesWithLiteralMatch(
- text_format.ParseError,
- '1:2 : Extension "unknown_extension" not registered.',
- text_format.Parse, text, message)
- message = unittest_pb2.TestAllTypes()
- self.assertRaisesWithLiteralMatch(
- text_format.ParseError,
- ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
- 'extensions.'),
- text_format.Parse, text, message)
-
- def testParseGroupNotClosed(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseGroupNotClosed(self, message_module):
+ message = message_module.TestAllTypes()
text = 'RepeatedGroup: <'
self.assertRaisesWithLiteralMatch(
text_format.ParseError, '1:16 : Expected ">".',
@@ -458,46 +321,46 @@ class TextFormatTest(basetest.TestCase):
text_format.ParseError, '1:16 : Expected "}".',
text_format.Parse, text, message)
- def testParseEmptyGroup(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseEmptyGroup(self, message_module):
+ message = message_module.TestAllTypes()
text = 'OptionalGroup: {}'
text_format.Parse(text, message)
self.assertTrue(message.HasField('optionalgroup'))
message.Clear()
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
text = 'OptionalGroup: <>'
text_format.Parse(text, message)
self.assertTrue(message.HasField('optionalgroup'))
- def testParseBadEnumValue(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseBadEnumValue(self, message_module):
+ message = message_module.TestAllTypes()
text = 'optional_nested_enum: BARR'
- self.assertRaisesWithLiteralMatch(
+ self.assertRaisesRegexp(
text_format.ParseError,
- ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
- 'has no value named BARR.'),
+ (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
+ r'has no value named BARR.'),
text_format.Parse, text, message)
- message = unittest_pb2.TestAllTypes()
+ message = message_module.TestAllTypes()
text = 'optional_nested_enum: 100'
- self.assertRaisesWithLiteralMatch(
+ self.assertRaisesRegexp(
text_format.ParseError,
- ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" '
- 'has no value with number 100.'),
+ (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" '
+ r'has no value with number 100.'),
text_format.Parse, text, message)
- def testParseBadIntValue(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseBadIntValue(self, message_module):
+ message = message_module.TestAllTypes()
text = 'optional_int32: bork'
self.assertRaisesWithLiteralMatch(
text_format.ParseError,
('1:17 : Couldn\'t parse integer: bork'),
text_format.Parse, text, message)
- def testParseStringFieldUnescape(self):
- message = unittest_pb2.TestAllTypes()
+ def testParseStringFieldUnescape(self, message_module):
+ message = message_module.TestAllTypes()
text = r'''repeated_string: "\xf\x62"
repeated_string: "\\xf\\x62"
repeated_string: "\\\xf\\\x62"
@@ -516,40 +379,205 @@ class TextFormatTest(basetest.TestCase):
message.repeated_string[4])
self.assertEqual(SLASH + 'x20', message.repeated_string[5])
- def testMergeDuplicateScalars(self):
- message = unittest_pb2.TestAllTypes()
+ def testMergeDuplicateScalars(self, message_module):
+ message = message_module.TestAllTypes()
text = ('optional_int32: 42 '
'optional_int32: 67')
r = text_format.Merge(text, message)
self.assertIs(r, message)
self.assertEqual(67, message.optional_int32)
- def testParseDuplicateScalars(self):
- message = unittest_pb2.TestAllTypes()
- text = ('optional_int32: 42 '
- 'optional_int32: 67')
- self.assertRaisesWithLiteralMatch(
- text_format.ParseError,
- ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not '
- 'have multiple "optional_int32" fields.'),
- text_format.Parse, text, message)
-
- def testMergeDuplicateNestedMessageScalars(self):
- message = unittest_pb2.TestAllTypes()
+ def testMergeDuplicateNestedMessageScalars(self, message_module):
+ message = message_module.TestAllTypes()
text = ('optional_nested_message { bb: 1 } '
'optional_nested_message { bb: 2 }')
r = text_format.Merge(text, message)
self.assertTrue(r is message)
self.assertEqual(2, message.optional_nested_message.bb)
- def testParseDuplicateNestedMessageScalars(self):
+ def testParseOneof(self, message_module):
+ m = message_module.TestAllTypes()
+ m.oneof_uint32 = 11
+ m2 = message_module.TestAllTypes()
+ text_format.Parse(text_format.MessageToString(m), m2)
+ self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+
+
+# These are tests that aren't fundamentally specific to proto2, but are at
+# the moment because of differences between the proto2 and proto3 test schemas.
+# Ideally the schemas would be made more similar so these tests could pass.
+class OnlyWorksWithProto2RightNowTests(TextFormatBase):
+
+ def testParseGolden(self):
+ golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt'))
+ parsed_message = unittest_pb2.TestAllTypes()
+ r = text_format.Parse(golden_text, parsed_message)
+ self.assertIs(r, parsed_message)
+
message = unittest_pb2.TestAllTypes()
- text = ('optional_nested_message { bb: 1 } '
- 'optional_nested_message { bb: 2 }')
+ test_util.SetAllFields(message)
+ self.assertEquals(message, parsed_message)
+
+ def testPrintAllFields(self):
+ message = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(message)
+ self.CompareToGoldenFile(
+ self.RemoveRedundantZeros(text_format.MessageToString(message)),
+ 'text_format_unittest_data_oneof_implemented.txt')
+
+ def testPrintAllFieldsPointy(self):
+ message = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(message)
+ self.CompareToGoldenFile(
+ self.RemoveRedundantZeros(
+ text_format.MessageToString(message, pointy_brackets=True)),
+ 'text_format_unittest_data_pointy_oneof.txt')
+
+ def testPrintInIndexOrder(self):
+ message = unittest_pb2.TestFieldOrderings()
+ message.my_string = '115'
+ message.my_int = 101
+ message.my_float = 111
+ message.optional_nested_message.oo = 0
+ message.optional_nested_message.bb = 1
+ self.CompareToGoldenText(
+ self.RemoveRedundantZeros(text_format.MessageToString(
+ message, use_index_order=True)),
+ 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n'
+ 'optional_nested_message {\n oo: 0\n bb: 1\n}\n')
+ self.CompareToGoldenText(
+ self.RemoveRedundantZeros(text_format.MessageToString(
+ message)),
+ 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n'
+ 'optional_nested_message {\n bb: 1\n oo: 0\n}\n')
+
+ def testMergeLinesGolden(self):
+ opened = self.ReadGolden('text_format_unittest_data.txt')
+ parsed_message = unittest_pb2.TestAllTypes()
+ r = text_format.MergeLines(opened, parsed_message)
+ self.assertIs(r, parsed_message)
+
+ message = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(message)
+ self.assertEqual(message, parsed_message)
+
+ def testParseLinesGolden(self):
+ opened = self.ReadGolden('text_format_unittest_data.txt')
+ parsed_message = unittest_pb2.TestAllTypes()
+ r = text_format.ParseLines(opened, parsed_message)
+ self.assertIs(r, parsed_message)
+
+ message = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(message)
+ self.assertEquals(message, parsed_message)
+
+
+# Tests of proto2-only features (MessageSet and extensions).
+class Proto2Tests(TextFormatBase):
+
+ def testPrintMessageSet(self):
+ message = unittest_mset_pb2.TestMessageSetContainer()
+ ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+ ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+ message.message_set.Extensions[ext1].i = 23
+ message.message_set.Extensions[ext2].str = 'foo'
+ self.CompareToGoldenText(
+ text_format.MessageToString(message),
+ 'message_set {\n'
+ ' [protobuf_unittest.TestMessageSetExtension1] {\n'
+ ' i: 23\n'
+ ' }\n'
+ ' [protobuf_unittest.TestMessageSetExtension2] {\n'
+ ' str: \"foo\"\n'
+ ' }\n'
+ '}\n')
+
+ def testPrintMessageSetAsOneLine(self):
+ message = unittest_mset_pb2.TestMessageSetContainer()
+ ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+ ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+ message.message_set.Extensions[ext1].i = 23
+ message.message_set.Extensions[ext2].str = 'foo'
+ self.CompareToGoldenText(
+ text_format.MessageToString(message, as_one_line=True),
+ 'message_set {'
+ ' [protobuf_unittest.TestMessageSetExtension1] {'
+ ' i: 23'
+ ' }'
+ ' [protobuf_unittest.TestMessageSetExtension2] {'
+ ' str: \"foo\"'
+ ' }'
+ ' }')
+
+ def testParseMessageSet(self):
+ message = unittest_pb2.TestAllTypes()
+ text = ('repeated_uint64: 1\n'
+ 'repeated_uint64: 2\n')
+ text_format.Parse(text, message)
+ self.assertEqual(1, message.repeated_uint64[0])
+ self.assertEqual(2, message.repeated_uint64[1])
+
+ message = unittest_mset_pb2.TestMessageSetContainer()
+ text = ('message_set {\n'
+ ' [protobuf_unittest.TestMessageSetExtension1] {\n'
+ ' i: 23\n'
+ ' }\n'
+ ' [protobuf_unittest.TestMessageSetExtension2] {\n'
+ ' str: \"foo\"\n'
+ ' }\n'
+ '}\n')
+ text_format.Parse(text, message)
+ ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+ ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+ self.assertEquals(23, message.message_set.Extensions[ext1].i)
+ self.assertEquals('foo', message.message_set.Extensions[ext2].str)
+
+ def testPrintAllExtensions(self):
+ message = unittest_pb2.TestAllExtensions()
+ test_util.SetAllExtensions(message)
+ self.CompareToGoldenFile(
+ self.RemoveRedundantZeros(text_format.MessageToString(message)),
+ 'text_format_unittest_extensions_data.txt')
+
+ def testPrintAllExtensionsPointy(self):
+ message = unittest_pb2.TestAllExtensions()
+ test_util.SetAllExtensions(message)
+ self.CompareToGoldenFile(
+ self.RemoveRedundantZeros(text_format.MessageToString(
+ message, pointy_brackets=True)),
+ 'text_format_unittest_extensions_data_pointy.txt')
+
+ def testParseGoldenExtensions(self):
+ golden_text = '\n'.join(self.ReadGolden(
+ 'text_format_unittest_extensions_data.txt'))
+ parsed_message = unittest_pb2.TestAllExtensions()
+ text_format.Parse(golden_text, parsed_message)
+
+ message = unittest_pb2.TestAllExtensions()
+ test_util.SetAllExtensions(message)
+ self.assertEquals(message, parsed_message)
+
+ def testParseAllExtensions(self):
+ message = unittest_pb2.TestAllExtensions()
+ test_util.SetAllExtensions(message)
+ ascii_text = text_format.MessageToString(message)
+
+ parsed_message = unittest_pb2.TestAllExtensions()
+ text_format.Parse(ascii_text, parsed_message)
+ self.assertEqual(message, parsed_message)
+
+ def testParseBadExtension(self):
+ message = unittest_pb2.TestAllExtensions()
+ text = '[unknown_extension]: 8\n'
self.assertRaisesWithLiteralMatch(
text_format.ParseError,
- ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" '
- 'should not have multiple "bb" fields.'),
+ '1:2 : Extension "unknown_extension" not registered.',
+ text_format.Parse, text, message)
+ message = unittest_pb2.TestAllTypes()
+ self.assertRaisesWithLiteralMatch(
+ text_format.ParseError,
+ ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have '
+ 'extensions.'),
text_format.Parse, text, message)
def testMergeDuplicateExtensionScalars(self):
@@ -572,32 +600,25 @@ class TextFormatTest(basetest.TestCase):
'"protobuf_unittest.optional_int32_extension" extensions.'),
text_format.Parse, text, message)
- def testParseLinesGolden(self):
- opened = self.ReadGolden('text_format_unittest_data.txt')
- parsed_message = unittest_pb2.TestAllTypes()
- r = text_format.ParseLines(opened, parsed_message)
- self.assertIs(r, parsed_message)
-
+ def testParseDuplicateNestedMessageScalars(self):
message = unittest_pb2.TestAllTypes()
- test_util.SetAllFields(message)
- self.assertEquals(message, parsed_message)
-
- def testMergeLinesGolden(self):
- opened = self.ReadGolden('text_format_unittest_data.txt')
- parsed_message = unittest_pb2.TestAllTypes()
- r = text_format.MergeLines(opened, parsed_message)
- self.assertIs(r, parsed_message)
+ text = ('optional_nested_message { bb: 1 } '
+ 'optional_nested_message { bb: 2 }')
+ self.assertRaisesWithLiteralMatch(
+ text_format.ParseError,
+ ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" '
+ 'should not have multiple "bb" fields.'),
+ text_format.Parse, text, message)
+ def testParseDuplicateScalars(self):
message = unittest_pb2.TestAllTypes()
- test_util.SetAllFields(message)
- self.assertEqual(message, parsed_message)
-
- def testParseOneof(self):
- m = unittest_pb2.TestAllTypes()
- m.oneof_uint32 = 11
- m2 = unittest_pb2.TestAllTypes()
- text_format.Parse(text_format.MessageToString(m), m2)
- self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
+ text = ('optional_int32: 42 '
+ 'optional_int32: 67')
+ self.assertRaisesWithLiteralMatch(
+ text_format.ParseError,
+ ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not '
+ 'have multiple "optional_int32" fields.'),
+ text_format.Parse, text, message)
class TokenizerTest(basetest.TestCase):
diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py
index 118725da..76c056c4 100755
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -59,6 +59,8 @@ from google.protobuf import descriptor
_FieldDescriptor = descriptor.FieldDescriptor
+def SupportsOpenEnums(field_descriptor):
+ return field_descriptor.containing_type.syntax == "proto3"
def GetTypeChecker(field):
"""Returns a type checker for a message field of the specified types.
@@ -74,7 +76,11 @@ def GetTypeChecker(field):
field.type == _FieldDescriptor.TYPE_STRING):
return UnicodeValueChecker()
if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
- return EnumValueChecker(field.enum_type)
+ if SupportsOpenEnums(field):
+ # When open enums are supported, any int32 can be assigned.
+ return _VALUE_CHECKERS[_FieldDescriptor.CPPTYPE_INT32]
+ else:
+ return EnumValueChecker(field.enum_type)
return _VALUE_CHECKERS[field.cpp_type]
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index a4dc1f7c..59f9ae4c 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -38,6 +38,7 @@ __author__ = 'bohdank@google.com (Bohdan Koval)'
from google.apputils import basetest
from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
from google.protobuf.internal import api_implementation
from google.protobuf.internal import encoder
from google.protobuf.internal import missing_enum_values_pb2
@@ -45,10 +46,81 @@ from google.protobuf.internal import test_util
from google.protobuf.internal import type_checkers
+class UnknownFieldsTest(basetest.TestCase):
+
+ def setUp(self):
+ self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+ self.all_fields = unittest_pb2.TestAllTypes()
+ test_util.SetAllFields(self.all_fields)
+ self.all_fields_data = self.all_fields.SerializeToString()
+ self.empty_message = unittest_pb2.TestEmptyMessage()
+ self.empty_message.ParseFromString(self.all_fields_data)
+
+ def testSerialize(self):
+ data = self.empty_message.SerializeToString()
+
+ # Don't use assertEqual because we don't want to dump raw binary data to
+ # stdout.
+ self.assertTrue(data == self.all_fields_data)
+
+ def testSerializeProto3(self):
+ # Verify that proto3 doesn't preserve unknown fields.
+ message = unittest_proto3_arena_pb2.TestEmptyMessage()
+ message.ParseFromString(self.all_fields_data)
+ self.assertEqual(0, len(message.SerializeToString()))
+
+ def testByteSize(self):
+ self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize())
+
+ def testListFields(self):
+ # Make sure ListFields doesn't return unknown fields.
+ self.assertEqual(0, len(self.empty_message.ListFields()))
+
+ def testSerializeMessageSetWireFormatUnknownExtension(self):
+ # Create a message using the message set wire format with an unknown
+ # message.
+ raw = unittest_mset_pb2.RawMessageSet()
+
+ # Add an unknown extension.
+ item = raw.item.add()
+ item.type_id = 1545009
+ message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ message1.i = 12345
+ item.message = message1.SerializeToString()
+
+ serialized = raw.SerializeToString()
+
+ # Parse message using the message set wire format.
+ proto = unittest_mset_pb2.TestMessageSet()
+ proto.MergeFromString(serialized)
+
+ # Verify that the unknown extension is serialized unchanged
+ reserialized = proto.SerializeToString()
+ new_raw = unittest_mset_pb2.RawMessageSet()
+ new_raw.MergeFromString(reserialized)
+ self.assertEqual(raw, new_raw)
+
+ # C++ implementation for proto2 does not currently take into account unknown
+ # fields when checking equality.
+ #
+ # TODO(haberman): fix this.
+ @basetest.unittest.skipIf(
+ api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+ 'C++ implementation does not expose unknown fields to Python')
+ def testEquals(self):
+ message = unittest_pb2.TestEmptyMessage()
+ message.ParseFromString(self.all_fields_data)
+ self.assertEqual(self.empty_message, message)
+
+ self.all_fields.ClearField('optional_string')
+ message.ParseFromString(self.all_fields.SerializeToString())
+ self.assertNotEqual(self.empty_message, message)
+
+
@basetest.unittest.skipIf(
api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
'C++ implementation does not expose unknown fields to Python')
-class UnknownFieldsTest(basetest.TestCase):
+class UnknownFieldsAccessorsTest(basetest.TestCase):
def setUp(self):
self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
@@ -98,13 +170,6 @@ class UnknownFieldsTest(basetest.TestCase):
value = self.GetField('optionalgroup')
self.assertEqual(self.all_fields.optionalgroup, value)
- def testSerialize(self):
- data = self.empty_message.SerializeToString()
-
- # Don't use assertEqual because we don't want to dump raw binary data to
- # stdout.
- self.assertTrue(data == self.all_fields_data)
-
def testCopyFrom(self):
message = unittest_pb2.TestEmptyMessage()
message.CopyFrom(self.empty_message)
@@ -132,51 +197,12 @@ class UnknownFieldsTest(basetest.TestCase):
self.empty_message.Clear()
self.assertEqual(0, len(self.empty_message._unknown_fields))
- def testByteSize(self):
- self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize())
-
def testUnknownExtensions(self):
message = unittest_pb2.TestEmptyMessageWithExtensions()
message.ParseFromString(self.all_fields_data)
self.assertEqual(self.empty_message._unknown_fields,
message._unknown_fields)
- def testListFields(self):
- # Make sure ListFields doesn't return unknown fields.
- self.assertEqual(0, len(self.empty_message.ListFields()))
-
- def testSerializeMessageSetWireFormatUnknownExtension(self):
- # Create a message using the message set wire format with an unknown
- # message.
- raw = unittest_mset_pb2.RawMessageSet()
-
- # Add an unknown extension.
- item = raw.item.add()
- item.type_id = 1545009
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
- message1.i = 12345
- item.message = message1.SerializeToString()
-
- serialized = raw.SerializeToString()
-
- # Parse message using the message set wire format.
- proto = unittest_mset_pb2.TestMessageSet()
- proto.MergeFromString(serialized)
-
- # Verify that the unknown extension is serialized unchanged
- reserialized = proto.SerializeToString()
- new_raw = unittest_mset_pb2.RawMessageSet()
- new_raw.MergeFromString(reserialized)
- self.assertEqual(raw, new_raw)
-
- def testEquals(self):
- message = unittest_pb2.TestEmptyMessage()
- message.ParseFromString(self.all_fields_data)
- self.assertEqual(self.empty_message, message)
-
- self.all_fields.ClearField('optional_string')
- message.ParseFromString(self.all_fields.SerializeToString())
- self.assertNotEqual(self.empty_message, message)
@basetest.unittest.skipIf(
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index 88ed9f4c..de2f5697 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -36,7 +36,6 @@
__author__ = 'robinson@google.com (Will Robinson)'
-
class Error(Exception): pass
class DecodeError(Error): pass
class EncodeError(Error): pass
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 7343c0b7..e77d0bb9 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -31,10 +31,15 @@
// Author: petar@google.com (Petar Petrov)
#include <Python.h>
+#include <frameobject.h>
#include <string>
+#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_containers.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
@@ -42,19 +47,97 @@
#if PY_MAJOR_VERSION >= 3
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+ #define PyString_Check PyUnicode_Check
+ #define PyString_InternFromString PyUnicode_InternFromString
#define PyInt_FromLong PyLong_FromLong
+ #define PyInt_FromSize_t PyLong_FromSize_t
#if PY_VERSION_HEX < 0x03030000
#error "Python 3.0 - 3.2 are not supported."
- #else
- #define PyString_AsString(ob) \
- (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
#endif
+ #define PyString_AsStringAndSize(ob, charpp, sizep) \
+ (PyUnicode_Check(ob)? \
+ ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+ PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
namespace google {
namespace protobuf {
namespace python {
+PyObject* PyString_FromCppString(const string& str) {
+ return PyString_FromStringAndSize(str.c_str(), str.size());
+}
+
+// Check that the calling Python code is the global scope of a _pb2.py module.
+// This function is used to support the current code generated by the proto
+// compiler, which creates descriptors, then update some properties.
+// For example:
+// message_descriptor = Descriptor(
+// name='Message',
+// fields = [FieldDescriptor(name='field')]
+// message_descriptor.fields[0].containing_type = message_descriptor
+//
+// This code is still executed, but the descriptors now have no other storage
+// than the (const) C++ pointer, and are immutable.
+// So we let this code pass, by simply ignoring the new value.
+//
+// From user code, descriptors still look immutable.
+//
+// TODO(amauryfa): Change the proto2 compiler to remove the assignments, and
+// remove this hack.
+bool _CalledFromGeneratedFile(int stacklevel) {
+ PyThreadState *state = PyThreadState_GET();
+ if (state == NULL) {
+ return false;
+ }
+ PyFrameObject* frame = state->frame;
+ if (frame == NULL) {
+ return false;
+ }
+ while (stacklevel-- > 0) {
+ frame = frame->f_back;
+ if (frame == NULL) {
+ return false;
+ }
+ }
+ if (frame->f_globals != frame->f_locals) {
+ // Not at global module scope
+ return false;
+ }
+
+ if (frame->f_code->co_filename == NULL) {
+ return false;
+ }
+ char* filename;
+ Py_ssize_t filename_size;
+ if (PyString_AsStringAndSize(frame->f_code->co_filename,
+ &filename, &filename_size) < 0) {
+ // filename is not a string.
+ PyErr_Clear();
+ return false;
+ }
+ if (filename_size < 7) {
+ // filename is too short.
+ return false;
+ }
+ if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) {
+ // Filename is not ending with _pb2.
+ return false;
+ }
+ return true;
+}
+
+// If the calling code is not a _pb2.py file, raise AttributeError.
+// To be used in attribute setters.
+static int CheckCalledFromGeneratedFile(const char* attr_name) {
+ if (_CalledFromGeneratedFile(0)) {
+ return 0;
+ }
+ PyErr_Format(PyExc_AttributeError,
+ "attribute is not writable: %s", attr_name);
+ return -1;
+}
+
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
@@ -64,42 +147,417 @@ namespace python {
#endif
-static google::protobuf::DescriptorPool* g_descriptor_pool = NULL;
+// Helper functions for descriptor objects.
-namespace cmessage_descriptor {
+// Converts options into a Python protobuf, and cache the result.
+//
+// This is a bit tricky because options can contain extension fields defined in
+// the same proto file. In this case the options parsed from the serialized_pb
+// have unkown fields, and we need to parse them again.
+//
+// Always returns a new reference.
+template<class DescriptorClass>
+static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
+ hash_map<const void*, PyObject*>* descriptor_options =
+ GetDescriptorPool()->descriptor_options;
+ // First search in the cache.
+ if (descriptor_options->find(descriptor) != descriptor_options->end()) {
+ PyObject *value = (*descriptor_options)[descriptor];
+ Py_INCREF(value);
+ return value;
+ }
-static void Dealloc(CMessageDescriptor* self) {
+ // Build the Options object: get its Python class, and make a copy of the C++
+ // read-only instance.
+ const Message& options(descriptor->options());
+ const Descriptor *message_type = options.GetDescriptor();
+ PyObject* message_class(cdescriptor_pool::GetMessageClass(
+ GetDescriptorPool(), message_type));
+ if (message_class == NULL) {
+ PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s",
+ message_type->full_name().c_str());
+ return NULL;
+ }
+ ScopedPyObjectPtr value(PyEval_CallObject(message_class, NULL));
+ if (value == NULL) {
+ return NULL;
+ }
+ CMessage* cmsg = reinterpret_cast<CMessage*>(value.get());
+
+ const Reflection* reflection = options.GetReflection();
+ const UnknownFieldSet& unknown_fields(reflection->GetUnknownFields(options));
+ if (unknown_fields.empty()) {
+ cmsg->message->CopyFrom(options);
+ } else {
+ // Reparse options string! XXX call cmessage::MergeFromString
+ string serialized;
+ options.SerializeToString(&serialized);
+ io::CodedInputStream input(
+ reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
+ input.SetExtensionRegistry(GetDescriptorPool()->pool,
+ cmessage::GetMessageFactory());
+ bool success = cmsg->message->MergePartialFromCodedStream(&input);
+ if (!success) {
+ PyErr_Format(PyExc_ValueError, "Error parsing Options message");
+ return NULL;
+ }
+ }
+
+ // Cache the result.
+ Py_INCREF(value);
+ (*GetDescriptorPool()->descriptor_options)[descriptor] = value.get();
+
+ return value.release();
+}
+
+// Copy the C++ descriptor to a Python message.
+// The Python message is an instance of descriptor_pb2.DescriptorProto
+// or similar.
+template<class DescriptorProtoClass, class DescriptorClass>
+static PyObject* CopyToPythonProto(const DescriptorClass *descriptor,
+ PyObject *target) {
+ const Descriptor* self_descriptor =
+ DescriptorProtoClass::default_instance().GetDescriptor();
+ CMessage* message = reinterpret_cast<CMessage*>(target);
+ if (!PyObject_TypeCheck(target, &CMessage_Type) ||
+ message->message->GetDescriptor() != self_descriptor) {
+ PyErr_Format(PyExc_TypeError, "Not a %s message",
+ self_descriptor->full_name().c_str());
+ return NULL;
+ }
+ cmessage::AssureWritable(message);
+ DescriptorProtoClass* descriptor_message =
+ static_cast<DescriptorProtoClass*>(message->message);
+ descriptor->CopyTo(descriptor_message);
+ Py_RETURN_NONE;
+}
+
+// All Descriptors classes share the same memory layout.
+typedef struct PyBaseDescriptor {
+ PyObject_HEAD
+
+ // Pointer to the C++ proto2 descriptor.
+ // Like all descriptors, it is owned by the global DescriptorPool.
+ const void* descriptor;
+} PyBaseDescriptor;
+
+
+// FileDescriptor structure "inherits" from the base descriptor.
+typedef struct PyFileDescriptor {
+ PyBaseDescriptor base;
+
+ // The cached version of serialized pb. Either NULL, or a Bytes string.
+ // We own the reference.
+ PyObject *serialized_pb;
+} PyFileDescriptor;
+
+
+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.
+// Always return a new reference.
+PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor) {
+ if (descriptor == NULL) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+
+ // See if the object is in the map of interned descriptors
+ hash_map<const void*, PyObject*>::iterator it =
+ GetDescriptorPool()->interned_descriptors->find(descriptor);
+ if (it != GetDescriptorPool()->interned_descriptors->end()) {
+ GOOGLE_DCHECK(Py_TYPE(it->second) == type);
+ Py_INCREF(it->second);
+ return it->second;
+ }
+ // Create a new descriptor object
+ PyBaseDescriptor* py_descriptor = PyObject_New(
+ PyBaseDescriptor, type);
+ if (py_descriptor == NULL) {
+ return NULL;
+ }
+ py_descriptor->descriptor = descriptor;
+ // and cache it.
+ GetDescriptorPool()->interned_descriptors->insert(
+ std::make_pair(descriptor, reinterpret_cast<PyObject*>(py_descriptor)));
+
+ return reinterpret_cast<PyObject*>(py_descriptor);
+}
+
+static void Dealloc(PyBaseDescriptor* self) {
+ // Remove from interned dictionary
+ GetDescriptorPool()->interned_descriptors->erase(self->descriptor);
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
-static PyObject* GetFullName(CMessageDescriptor* self, void *closure) {
- return PyString_FromStringAndSize(
- self->descriptor->full_name().c_str(),
- self->descriptor->full_name().size());
+static PyGetSetDef Getters[] = {
+ {NULL}
+};
+
+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
+ sizeof(PyBaseDescriptor), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)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
+ "Descriptors base class", // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ Getters, // tp_getset
+};
+
+} // namespace descriptor
+
+const void* PyDescriptor_AsVoidPtr(PyObject* obj) {
+ if (!PyObject_TypeCheck(obj, &descriptor::PyBaseDescriptor_Type)) {
+ PyErr_SetString(PyExc_TypeError, "Not a BaseDescriptor");
+ return NULL;
+ }
+ return reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor;
+}
+
+namespace message_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const Descriptor* _GetDescriptor(PyBaseDescriptor* self) {
+ return reinterpret_cast<const Descriptor*>(self->descriptor);
}
-static PyObject* GetName(CMessageDescriptor *self, void *closure) {
- return PyString_FromStringAndSize(
- self->descriptor->name().c_str(),
- self->descriptor->name().size());
+static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+ return PyFileDescriptor_New(_GetDescriptor(self)->file());
+}
+
+static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) {
+ PyObject* concrete_class(cdescriptor_pool::GetMessageClass(
+ GetDescriptorPool(), _GetDescriptor(self)));
+ Py_XINCREF(concrete_class);
+ 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));
+}
+
+static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) {
+ return NewMessageFieldsByNumber(_GetDescriptor(self));
+}
+
+static PyObject* GetFieldsSeq(PyBaseDescriptor* self, void *closure) {
+ return NewMessageFieldsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetNestedTypesByName(PyBaseDescriptor* self, void *closure) {
+ return NewMessageNestedTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetNestedTypesSeq(PyBaseDescriptor* self, void *closure) {
+ return NewMessageNestedTypesSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensionsByName(PyBaseDescriptor* self, void *closure) {
+ return NewMessageExtensionsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensions(PyBaseDescriptor* self, void *closure) {
+ return NewMessageExtensionsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumsSeq(PyBaseDescriptor* self, void *closure) {
+ return NewMessageEnumsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumTypesByName(PyBaseDescriptor* self, void *closure) {
+ return NewMessageEnumsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumValuesByName(PyBaseDescriptor* self, void *closure) {
+ return NewMessageEnumValuesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetOneofsByName(PyBaseDescriptor* self, void *closure) {
+ return NewMessageOneofsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetOneofsSeq(PyBaseDescriptor* self, void *closure) {
+ return NewMessageOneofsSeq(_GetDescriptor(self));
+}
+
+static PyObject* IsExtendable(PyBaseDescriptor *self, void *closure) {
+ if (_GetDescriptor(self)->extension_range_count() > 0) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) {
+ const Descriptor* descriptor = _GetDescriptor(self);
+ PyObject* range_list = PyList_New(descriptor->extension_range_count());
+
+ for (int i = 0; i < descriptor->extension_range_count(); i++) {
+ const Descriptor::ExtensionRange* range = descriptor->extension_range(i);
+ PyObject* start = PyInt_FromLong(range->start);
+ PyObject* end = PyInt_FromLong(range->end);
+ PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
+ }
+
+ return range_list;
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+ const Descriptor* containing_type =
+ _GetDescriptor(self)->containing_type();
+ if (containing_type) {
+ return PyMessageDescriptor_New(containing_type);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("containing_type");
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+ const MessageOptions& options(_GetDescriptor(self)->options());
+ if (&options != &MessageOptions::default_instance()) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+ return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
+ return CopyToPythonProto<DescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) {
+ const char *enum_name;
+ int number;
+ if (!PyArg_ParseTuple(args, "si", &enum_name, &number))
+ return NULL;
+ const EnumDescriptor *enum_type =
+ _GetDescriptor(self)->FindEnumTypeByName(enum_name);
+ if (enum_type == NULL) {
+ PyErr_SetString(PyExc_KeyError, enum_name);
+ return NULL;
+ }
+ const EnumValueDescriptor *enum_value =
+ enum_type->FindValueByNumber(number);
+ if (enum_value == NULL) {
+ PyErr_Format(PyExc_KeyError, "%d", number);
+ return NULL;
+ }
+ return PyString_FromCppString(enum_value->name());
+}
+
+static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) {
+ return PyString_InternFromString(
+ FileDescriptor::SyntaxName(_GetDescriptor(self)->file()->syntax()));
}
static PyGetSetDef Getters[] = {
+ { C("name"), (getter)GetName, NULL, "Last name", NULL},
{ C("full_name"), (getter)GetFullName, NULL, "Full name", NULL},
- { C("name"), (getter)GetName, NULL, "Unqualified 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},
{NULL}
};
-} // namespace cmessage_descriptor
+static PyMethodDef Methods[] = {
+ { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+ { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+ { "EnumValueName", (PyCFunction)EnumValueName, METH_VARARGS, },
+ {NULL}
+};
-PyTypeObject CMessageDescriptor_Type = {
+} // namespace message_descriptor
+
+PyTypeObject PyMessageDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- C("google.protobuf.internal."
- "_net_proto2___python."
- "CMessageDescriptor"), // tp_name
- sizeof(CMessageDescriptor), // tp_basicsize
+ // Keep the fully qualified _message symbol in a line for opensource.
+ C("google.protobuf.internal._message."
+ "MessageDescriptor"), // tp_name
+ sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
- (destructor)cmessage_descriptor::Dealloc, // tp_dealloc
+ 0, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
@@ -122,70 +580,266 @@ PyTypeObject CMessageDescriptor_Type = {
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
- 0, // tp_methods
+ message_descriptor::Methods, // tp_methods
0, // tp_members
- cmessage_descriptor::Getters, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
- PyType_GenericAlloc, // tp_alloc
- PyType_GenericNew, // tp_new
- PyObject_Del, // tp_free
+ message_descriptor::Getters, // tp_getset
+ &descriptor::PyBaseDescriptor_Type, // tp_base
};
+PyObject* PyMessageDescriptor_New(
+ const Descriptor* message_descriptor) {
+ return descriptor::NewInternedDescriptor(
+ &PyMessageDescriptor_Type, message_descriptor);
+}
+
+const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) {
+ if (!PyObject_TypeCheck(obj, &PyMessageDescriptor_Type)) {
+ PyErr_SetString(PyExc_TypeError, "Not a MessageDescriptor");
+ return NULL;
+ }
+ return reinterpret_cast<const Descriptor*>(
+ reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
+}
+
+namespace field_descriptor {
-namespace cfield_descriptor {
+// Unchecked accessor to the C++ pointer.
+static const FieldDescriptor* _GetDescriptor(
+ PyBaseDescriptor *self) {
+ return reinterpret_cast<const FieldDescriptor*>(self->descriptor);
+}
-static void Dealloc(CFieldDescriptor* self) {
- Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->type());
}
-static PyObject* GetFullName(CFieldDescriptor* self, void *closure) {
- return PyString_FromStringAndSize(
- self->descriptor->full_name().c_str(),
- self->descriptor->full_name().size());
+static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->cpp_type());
}
-static PyObject* GetName(CFieldDescriptor *self, void *closure) {
- return PyString_FromStringAndSize(
- self->descriptor->name().c_str(),
- self->descriptor->name().size());
+static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->label());
}
-static PyObject* GetCppType(CFieldDescriptor *self, void *closure) {
- return PyInt_FromLong(self->descriptor->cpp_type());
+static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->number());
}
-static PyObject* GetLabel(CFieldDescriptor *self, void *closure) {
- return PyInt_FromLong(self->descriptor->label());
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->index());
}
-static PyObject* GetID(CFieldDescriptor *self, void *closure) {
+static PyObject* GetID(PyBaseDescriptor *self, void *closure) {
return PyLong_FromVoidPtr(self);
}
+static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) {
+ return PyBool_FromLong(_GetDescriptor(self)->is_extension());
+}
+
+static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) {
+ return PyBool_FromLong(_GetDescriptor(self)->has_default_value());
+}
+
+static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) {
+ PyObject *result;
+
+ switch (_GetDescriptor(self)->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32: {
+ int32 value = _GetDescriptor(self)->default_value_int32();
+ result = PyInt_FromLong(value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_INT64: {
+ int64 value = _GetDescriptor(self)->default_value_int64();
+ result = PyLong_FromLongLong(value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_UINT32: {
+ uint32 value = _GetDescriptor(self)->default_value_uint32();
+ result = PyInt_FromSize_t(value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_UINT64: {
+ uint64 value = _GetDescriptor(self)->default_value_uint64();
+ result = PyLong_FromUnsignedLongLong(value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = _GetDescriptor(self)->default_value_float();
+ result = PyFloat_FromDouble(value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
+ double value = _GetDescriptor(self)->default_value_double();
+ result = PyFloat_FromDouble(value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_BOOL: {
+ bool value = _GetDescriptor(self)->default_value_bool();
+ result = PyBool_FromLong(value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_STRING: {
+ string value = _GetDescriptor(self)->default_value_string();
+ result = ToStringObject(_GetDescriptor(self), value);
+ break;
+ }
+ case FieldDescriptor::CPPTYPE_ENUM: {
+ const EnumValueDescriptor* value =
+ _GetDescriptor(self)->default_value_enum();
+ result = PyInt_FromLong(value->number());
+ break;
+ }
+ default:
+ PyErr_Format(PyExc_NotImplementedError, "default value for %s",
+ _GetDescriptor(self)->full_name().c_str());
+ return NULL;
+ }
+ return result;
+}
+
+static PyObject* GetCDescriptor(PyObject *self, void *closure) {
+ Py_INCREF(self);
+ return self;
+}
+
+static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) {
+ const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type();
+ if (enum_type) {
+ return PyEnumDescriptor_New(enum_type);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) {
+ return CheckCalledFromGeneratedFile("enum_type");
+}
+
+static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) {
+ const Descriptor* message_type = _GetDescriptor(self)->message_type();
+ if (message_type) {
+ return PyMessageDescriptor_New(message_type);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static int SetMessageType(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("message_type");
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+ const Descriptor* containing_type =
+ _GetDescriptor(self)->containing_type();
+ if (containing_type) {
+ return PyMessageDescriptor_New(containing_type);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("containing_type");
+}
+
+static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) {
+ const Descriptor* extension_scope =
+ _GetDescriptor(self)->extension_scope();
+ if (extension_scope) {
+ return PyMessageDescriptor_New(extension_scope);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) {
+ const OneofDescriptor* containing_oneof =
+ _GetDescriptor(self)->containing_oneof();
+ if (containing_oneof) {
+ return PyOneofDescriptor_New(containing_oneof);
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static int SetContainingOneof(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("containing_oneof");
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+ const FieldOptions& options(_GetDescriptor(self)->options());
+ if (&options != &FieldOptions::default_instance()) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+ return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_options");
+}
+
+
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},
{NULL}
};
-} // namespace cfield_descriptor
+static PyMethodDef Methods[] = {
+ { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+ {NULL}
+};
-PyTypeObject CFieldDescriptor_Type = {
+} // namespace field_descriptor
+
+PyTypeObject PyFieldDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
C("google.protobuf.internal."
- "_net_proto2___python."
- "CFieldDescriptor"), // tp_name
- sizeof(CFieldDescriptor), // tp_basicsize
+ "_message.FieldDescriptor"), // tp_name
+ sizeof(PyBaseDescriptor), // tp_basicsize
0, // tp_itemsize
- (destructor)cfield_descriptor::Dealloc, // tp_dealloc
+ 0, // tp_dealloc
0, // tp_print
0, // tp_getattr
0, // tp_setattr
@@ -208,297 +862,605 @@ PyTypeObject CFieldDescriptor_Type = {
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
- 0, // tp_methods
+ field_descriptor::Methods, // tp_methods
0, // tp_members
- cfield_descriptor::Getters, // tp_getset
- 0, // tp_base
- 0, // tp_dict
- 0, // tp_descr_get
- 0, // tp_descr_set
- 0, // tp_dictoffset
- 0, // tp_init
- PyType_GenericAlloc, // tp_alloc
- PyType_GenericNew, // tp_new
- PyObject_Del, // tp_free
+ field_descriptor::Getters, // tp_getset
+ &descriptor::PyBaseDescriptor_Type, // tp_base
};
+PyObject* PyFieldDescriptor_New(
+ const FieldDescriptor* field_descriptor) {
+ return descriptor::NewInternedDescriptor(
+ &PyFieldDescriptor_Type, field_descriptor);
+}
-namespace cdescriptor_pool {
-
-PyDescriptorPool* NewDescriptorPool() {
- PyDescriptorPool* cdescriptor_pool = PyObject_New(
- PyDescriptorPool, &PyDescriptorPool_Type);
- if (cdescriptor_pool == NULL) {
+const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) {
+ if (!PyObject_TypeCheck(obj, &PyFieldDescriptor_Type)) {
+ PyErr_SetString(PyExc_TypeError, "Not a FieldDescriptor");
return NULL;
}
+ return reinterpret_cast<const FieldDescriptor*>(
+ reinterpret_cast<PyBaseDescriptor*>(obj)->descriptor);
+}
- // Build a DescriptorPool for messages only declared in Python libraries.
- // generated_pool() contains all messages linked in C++ libraries, and is used
- // as underlay.
- cdescriptor_pool->pool = new google::protobuf::DescriptorPool(
- google::protobuf::DescriptorPool::generated_pool());
+namespace enum_descriptor {
- // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
- // storage.
- cdescriptor_pool->classes_by_descriptor =
- new PyDescriptorPool::ClassesByMessageMap();
+// Unchecked accessor to the C++ pointer.
+static const EnumDescriptor* _GetDescriptor(
+ PyBaseDescriptor *self) {
+ return reinterpret_cast<const EnumDescriptor*>(self->descriptor);
+}
- return cdescriptor_pool;
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->full_name());
}
-static void Dealloc(PyDescriptorPool* self) {
- typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
- for (iterator it = self->classes_by_descriptor->begin();
- it != self->classes_by_descriptor->end(); ++it) {
- Py_DECREF(it->second);
- }
- delete self->classes_by_descriptor;
- Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->name());
}
-const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
- const string& name) {
- return self->pool->FindMessageTypeByName(name);
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+ return PyFileDescriptor_New(_GetDescriptor(self)->file());
}
-static PyObject* NewCMessageDescriptor(
- const google::protobuf::Descriptor* message_descriptor) {
- CMessageDescriptor* cmessage_descriptor = PyObject_New(
- CMessageDescriptor, &CMessageDescriptor_Type);
- if (cmessage_descriptor == NULL) {
- return NULL;
- }
- cmessage_descriptor->descriptor = message_descriptor;
+static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) {
+ return NewEnumValuesByName(_GetDescriptor(self));
+}
- return reinterpret_cast<PyObject*>(cmessage_descriptor);
+static PyObject* GetEnumvaluesByNumber(PyBaseDescriptor* self, void *closure) {
+ return NewEnumValuesByNumber(_GetDescriptor(self));
}
-static PyObject* NewCFieldDescriptor(
- const google::protobuf::FieldDescriptor* field_descriptor) {
- CFieldDescriptor* cfield_descriptor = PyObject_New(
- CFieldDescriptor, &CFieldDescriptor_Type);
- if (cfield_descriptor == NULL) {
- return NULL;
+static PyObject* GetEnumvaluesSeq(PyBaseDescriptor* self, void *closure) {
+ return NewEnumValuesSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+ const Descriptor* containing_type =
+ _GetDescriptor(self)->containing_type();
+ if (containing_type) {
+ return PyMessageDescriptor_New(containing_type);
+ } else {
+ Py_RETURN_NONE;
}
- cfield_descriptor->descriptor = field_descriptor;
+}
- return reinterpret_cast<PyObject*>(cfield_descriptor);
+static int SetContainingType(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("containing_type");
}
-// Add a message class to our database.
-const google::protobuf::Descriptor* RegisterMessageClass(
- PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) {
- ScopedPyObjectPtr full_message_name(
- PyObject_GetAttrString(descriptor, "full_name"));
- const char* full_name = PyString_AsString(full_message_name);
- if (full_name == NULL) {
- return NULL;
- }
- const Descriptor *message_descriptor =
- self->pool->FindMessageTypeByName(full_name);
- if (!message_descriptor) {
- PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'",
- full_name);
- return NULL;
- }
- Py_INCREF(message_class);
- typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
- std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
- make_pair(message_descriptor, message_class));
- if (!ret.second) {
- // Update case: DECREF the previous value.
- Py_DECREF(ret.first->second);
- ret.first->second = message_class;
- }
- // Also add the C++ descriptor to the Python descriptor class.
- ScopedPyObjectPtr cdescriptor(NewCMessageDescriptor(message_descriptor));
- if (cdescriptor == NULL) {
- return NULL;
- }
- if (PyObject_SetAttrString(
- descriptor, "_cdescriptor", cdescriptor) < 0) {
- return NULL;
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+ const EnumOptions& options(_GetDescriptor(self)->options());
+ if (&options != &EnumOptions::default_instance()) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
}
- return message_descriptor;
+}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("has_options");
}
-// Retrieve the message class added to our database.
-PyObject *GetMessageClass(PyDescriptorPool* self,
- const Descriptor *message_descriptor) {
- typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
- iterator ret = self->classes_by_descriptor->find(message_descriptor);
- if (ret == self->classes_by_descriptor->end()) {
- PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
- message_descriptor->full_name().c_str());
- return NULL;
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+ return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) {
+ return CopyToPythonProto<EnumDescriptorProto>(_GetDescriptor(self), target);
+}
+
+static PyMethodDef Methods[] = {
+ { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+ { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
+ {NULL}
+};
+
+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},
+ {NULL}
+};
+
+} // namespace enum_descriptor
+
+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
+ sizeof(PyBaseDescriptor), // tp_basicsize
+ 0, // tp_itemsize
+ 0, // 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 Enum Descriptor"), // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ enum_descriptor::Methods, // tp_getset
+ 0, // tp_members
+ enum_descriptor::Getters, // tp_getset
+ &descriptor::PyBaseDescriptor_Type, // tp_base
+};
+
+PyObject* PyEnumDescriptor_New(
+ const EnumDescriptor* enum_descriptor) {
+ return descriptor::NewInternedDescriptor(
+ &PyEnumDescriptor_Type, enum_descriptor);
+}
+
+namespace enumvalue_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const EnumValueDescriptor* _GetDescriptor(
+ PyBaseDescriptor *self) {
+ return reinterpret_cast<const EnumValueDescriptor*>(self->descriptor);
+}
+
+static PyObject* GetName(PyBaseDescriptor *self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->number());
+}
+
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->index());
+}
+
+static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
+ return PyEnumDescriptor_New(_GetDescriptor(self)->type());
+}
+
+static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) {
+ const EnumValueOptions& options(_GetDescriptor(self)->options());
+ if (&options != &EnumValueOptions::default_instance()) {
+ Py_RETURN_TRUE;
} else {
- return ret->second;
+ Py_RETURN_FALSE;
}
}
+static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("has_options");
+}
-PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name) {
- const char* full_field_name = PyString_AsString(name);
- if (full_field_name == NULL) {
- return NULL;
- }
+static PyObject* GetOptions(PyBaseDescriptor *self) {
+ return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyBaseDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_options");
+}
- const google::protobuf::FieldDescriptor* field_descriptor = NULL;
- field_descriptor = self->pool->FindFieldByName(full_field_name);
+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},
- if (field_descriptor == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
- full_field_name);
- return NULL;
- }
+ { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL},
+ { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL},
+ {NULL}
+};
+
+static PyMethodDef Methods[] = {
+ { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+ {NULL}
+};
+
+} // namespace enumvalue_descriptor
+
+PyTypeObject PyEnumValueDescriptor_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ C("google.protobuf.internal."
+ "_message.EnumValueDescriptor"), // tp_name
+ sizeof(PyBaseDescriptor), // tp_basicsize
+ 0, // tp_itemsize
+ 0, // 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 EnumValue Descriptor"), // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ enumvalue_descriptor::Methods, // tp_methods
+ 0, // tp_members
+ enumvalue_descriptor::Getters, // tp_getset
+ &descriptor::PyBaseDescriptor_Type, // tp_base
+};
+
+PyObject* PyEnumValueDescriptor_New(
+ const EnumValueDescriptor* enumvalue_descriptor) {
+ return descriptor::NewInternedDescriptor(
+ &PyEnumValueDescriptor_Type, enumvalue_descriptor);
+}
+
+namespace file_descriptor {
+
+// Unchecked accessor to the C++ pointer.
+static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) {
+ return reinterpret_cast<const FileDescriptor*>(self->base.descriptor);
+}
- return NewCFieldDescriptor(field_descriptor);
+static void Dealloc(PyFileDescriptor* self) {
+ Py_XDECREF(self->serialized_pb);
+ descriptor::Dealloc(&self->base);
}
-PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
- const char* full_field_name = PyString_AsString(arg);
- if (full_field_name == NULL) {
+static PyObject* GetName(PyFileDescriptor *self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetPackage(PyFileDescriptor *self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->package());
+}
+
+static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) {
+ PyObject *serialized_pb = self->serialized_pb;
+ if (serialized_pb != NULL) {
+ Py_INCREF(serialized_pb);
+ return serialized_pb;
+ }
+ FileDescriptorProto file_proto;
+ _GetDescriptor(self)->CopyTo(&file_proto);
+ string contents;
+ file_proto.SerializePartialToString(&contents);
+ self->serialized_pb = PyBytes_FromStringAndSize(
+ contents.c_str(), contents.size());
+ if (self->serialized_pb == NULL) {
return NULL;
}
+ Py_INCREF(self->serialized_pb);
+ return self->serialized_pb;
+}
- const google::protobuf::FieldDescriptor* field_descriptor =
- self->pool->FindExtensionByName(full_field_name);
- if (field_descriptor == NULL) {
- PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
- full_field_name);
- return NULL;
+static PyObject* GetMessageTypesByName(PyFileDescriptor* self, void *closure) {
+ return NewFileMessageTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetEnumTypesByName(PyFileDescriptor* self, void *closure) {
+ return NewFileEnumTypesByName(_GetDescriptor(self));
+}
+
+static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) {
+ return NewFileExtensionsByName(_GetDescriptor(self));
+}
+
+static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) {
+ return NewFileDependencies(_GetDescriptor(self));
+}
+
+static PyObject* GetPublicDependencies(PyFileDescriptor* self, void *closure) {
+ return NewFilePublicDependencies(_GetDescriptor(self));
+}
+
+static PyObject* GetHasOptions(PyFileDescriptor *self, void *closure) {
+ const FileOptions& options(_GetDescriptor(self)->options());
+ if (&options != &FileOptions::default_instance()) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
}
+}
+static int SetHasOptions(PyFileDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("has_options");
+}
+
+static PyObject* GetOptions(PyFileDescriptor *self) {
+ return GetOrBuildOptions(_GetDescriptor(self));
+}
+
+static int SetOptions(PyFileDescriptor *self, PyObject *value,
+ void *closure) {
+ return CheckCalledFromGeneratedFile("_options");
+}
+
+static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) {
+ return PyString_InternFromString(
+ FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax()));
+}
- return NewCFieldDescriptor(field_descriptor);
+static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) {
+ return CopyToPythonProto<FileDescriptorProto>(_GetDescriptor(self), 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},
+ {NULL}
+};
+
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.") },
+ { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, },
+ { "CopyToProto", (PyCFunction)CopyToProto, METH_O, },
{NULL}
};
-} // namespace cdescriptor_pool
+} // namespace file_descriptor
-PyTypeObject PyDescriptorPool_Type = {
+PyTypeObject PyFileDescriptor_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
C("google.protobuf.internal."
- "_net_proto2___python."
- "CFieldDescriptor"), // 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
+ "_message.FileDescriptor"), // tp_name
+ sizeof(PyFileDescriptor), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)file_descriptor::Dealloc, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ 0, // tp_repr
+ 0, // tp_as_number
+ 0, // tp_as_sequence
+ 0, // tp_as_mapping
+ 0, // tp_hash
+ 0, // tp_call
+ 0, // tp_str
+ 0, // tp_getattro
+ 0, // tp_setattro
+ 0, // tp_as_buffer
+ Py_TPFLAGS_DEFAULT, // tp_flags
+ C("A File Descriptor"), // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ file_descriptor::Methods, // tp_methods
+ 0, // tp_members
+ file_descriptor::Getters, // tp_getset
+ &descriptor::PyBaseDescriptor_Type, // tp_base
+ 0, // tp_dict
+ 0, // tp_descr_get
+ 0, // tp_descr_set
+ 0, // tp_dictoffset
+ 0, // tp_init
+ PyType_GenericAlloc, // tp_alloc
+ PyType_GenericNew, // tp_new
+ PyObject_Del, // tp_free
};
+PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor) {
+ return descriptor::NewInternedDescriptor(
+ &PyFileDescriptor_Type, file_descriptor);
+}
-// Collects errors that occur during proto file building to allow them to be
-// propagated in the python exception instead of only living in ERROR logs.
-class BuildFileErrorCollector : public google::protobuf::DescriptorPool::ErrorCollector {
- public:
- BuildFileErrorCollector() : error_message(""), had_errors(false) {}
-
- void AddError(const string& filename, const string& element_name,
- const Message* descriptor, ErrorLocation location,
- const string& message) {
- // Replicates the logging behavior that happens in the C++ implementation
- // when an error collector is not passed in.
- if (!had_errors) {
- error_message +=
- ("Invalid proto descriptor for file \"" + filename + "\":\n");
- }
- // As this only happens on failure and will result in the program not
- // running at all, no effort is made to optimize this string manipulation.
- error_message += (" " + element_name + ": " + message + "\n");
+PyObject* PyFileDescriptor_NewWithPb(
+ const FileDescriptor* file_descriptor, PyObject *serialized_pb) {
+ PyObject* py_descriptor = PyFileDescriptor_New(file_descriptor);
+ if (py_descriptor == NULL) {
+ return NULL;
+ }
+ if (serialized_pb != NULL) {
+ PyFileDescriptor* cfile_descriptor =
+ reinterpret_cast<PyFileDescriptor*>(py_descriptor);
+ Py_XINCREF(serialized_pb);
+ cfile_descriptor->serialized_pb = serialized_pb;
}
- string error_message;
- bool had_errors;
-};
+ return py_descriptor;
+}
-PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) {
- char* message_type;
- Py_ssize_t message_len;
+namespace oneof_descriptor {
- if (PyBytes_AsStringAndSize(arg, &message_type, &message_len) < 0) {
- return NULL;
- }
+// Unchecked accessor to the C++ pointer.
+static const OneofDescriptor* _GetDescriptor(
+ PyBaseDescriptor *self) {
+ return reinterpret_cast<const OneofDescriptor*>(self->descriptor);
+}
- google::protobuf::FileDescriptorProto file_proto;
- if (!file_proto.ParseFromArray(message_type, message_len)) {
- PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
- return NULL;
- }
+static PyObject* GetName(PyBaseDescriptor* self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->name());
+}
+
+static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) {
+ return PyString_FromCppString(_GetDescriptor(self)->full_name());
+}
+
+static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
+ return PyInt_FromLong(_GetDescriptor(self)->index());
+}
- // If the file was already part of a C++ library, all its descriptors are in
- // the underlying pool. No need to do anything else.
- if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
- file_proto.name()) != NULL) {
+static PyObject* GetFields(PyBaseDescriptor* self, void *closure) {
+ return NewOneofFieldsSeq(_GetDescriptor(self));
+}
+
+static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
+ const Descriptor* containing_type =
+ _GetDescriptor(self)->containing_type();
+ if (containing_type) {
+ return PyMessageDescriptor_New(containing_type);
+ } else {
Py_RETURN_NONE;
}
+}
- BuildFileErrorCollector error_collector;
- const google::protobuf::FileDescriptor* descriptor =
- GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto,
- &error_collector);
- if (descriptor == NULL) {
- PyErr_Format(PyExc_TypeError,
- "Couldn't build proto file into descriptor pool!\n%s",
- error_collector.error_message.c_str());
- return NULL;
+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},
+
+ { C("containing_type"), (getter)GetContainingType, NULL, "Containing type", NULL},
+ { C("fields"), (getter)GetFields, NULL, "Fields", NULL},
+ {NULL}
+};
+
+} // namespace oneof_descriptor
+
+PyTypeObject PyOneofDescriptor_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ C("google.protobuf.internal."
+ "_message.OneofDescriptor"), // tp_name
+ sizeof(PyBaseDescriptor), // tp_basicsize
+ 0, // tp_itemsize
+ 0, // 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 Oneof Descriptor"), // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ 0, // tp_methods
+ 0, // tp_members
+ oneof_descriptor::Getters, // tp_getset
+ &descriptor::PyBaseDescriptor_Type, // tp_base
+};
+
+PyObject* PyOneofDescriptor_New(
+ const OneofDescriptor* oneof_descriptor) {
+ return descriptor::NewInternedDescriptor(
+ &PyOneofDescriptor_Type, oneof_descriptor);
+}
+
+// Add a enum values to a type dictionary.
+static bool AddEnumValues(PyTypeObject *type,
+ const EnumDescriptor* enum_descriptor) {
+ for (int i = 0; i < enum_descriptor->value_count(); ++i) {
+ const EnumValueDescriptor* value = enum_descriptor->value(i);
+ ScopedPyObjectPtr obj(PyInt_FromLong(value->number()));
+ if (obj == NULL) {
+ return false;
+ }
+ if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj) < 0) {
+ return false;
+ }
}
+ return true;
+}
- Py_RETURN_NONE;
+static bool AddIntConstant(PyTypeObject *type, const char* name, int value) {
+ ScopedPyObjectPtr obj(PyInt_FromLong(value));
+ if (PyDict_SetItemString(type->tp_dict, name, obj) < 0) {
+ return false;
+ }
+ return true;
}
+
bool InitDescriptor() {
- if (PyType_Ready(&CMessageDescriptor_Type) < 0)
+ if (PyType_Ready(&PyMessageDescriptor_Type) < 0)
+ return false;
+
+ if (PyType_Ready(&PyFieldDescriptor_Type) < 0)
+ return false;
+
+ if (!AddEnumValues(&PyFieldDescriptor_Type,
+ FieldDescriptorProto::Label_descriptor())) {
+ return false;
+ }
+ if (!AddEnumValues(&PyFieldDescriptor_Type,
+ FieldDescriptorProto::Type_descriptor())) {
+ return false;
+ }
+#define ADD_FIELDDESC_CONSTANT(NAME) AddIntConstant( \
+ &PyFieldDescriptor_Type, #NAME, FieldDescriptor::NAME)
+ if (!ADD_FIELDDESC_CONSTANT(CPPTYPE_INT32) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_INT64) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT32) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT64) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_DOUBLE) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_FLOAT) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_BOOL) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_ENUM) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_STRING) ||
+ !ADD_FIELDDESC_CONSTANT(CPPTYPE_MESSAGE)) {
return false;
- if (PyType_Ready(&CFieldDescriptor_Type) < 0)
+ }
+#undef ADD_FIELDDESC_CONSTANT
+
+ if (PyType_Ready(&PyEnumDescriptor_Type) < 0)
+ return false;
+
+ if (PyType_Ready(&PyEnumValueDescriptor_Type) < 0)
+ return false;
+
+ if (PyType_Ready(&PyFileDescriptor_Type) < 0)
+ return false;
+
+ if (PyType_Ready(&PyOneofDescriptor_Type) < 0)
return false;
- PyDescriptorPool_Type.tp_new = PyType_GenericNew;
- if (PyType_Ready(&PyDescriptorPool_Type) < 0)
+ if (!InitDescriptorMappingTypes())
return false;
return true;
diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h
index 9e5957b5..ba6e7298 100644
--- a/python/google/protobuf/pyext/descriptor.h
+++ b/python/google/protobuf/pyext/descriptor.h
@@ -34,105 +34,55 @@
#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__
#include <Python.h>
-#include <structmember.h>
-
-#include <google/protobuf/stubs/hash.h>
#include <google/protobuf/descriptor.h>
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-typedef int Py_ssize_t;
-#define PY_SSIZE_T_MAX INT_MAX
-#define PY_SSIZE_T_MIN INT_MIN
-#endif
-
namespace google {
namespace protobuf {
namespace python {
-typedef struct CMessageDescriptor {
- PyObject_HEAD
-
- // The proto2 descriptor that this object represents.
- const google::protobuf::Descriptor* descriptor;
-} CMessageDescriptor;
-
-
-typedef struct CFieldDescriptor {
- PyObject_HEAD
-
- // The proto2 descriptor that this object represents.
- const google::protobuf::FieldDescriptor* descriptor;
-} CFieldDescriptor;
-
-
-// Wraps operations to the global DescriptorPool which contains information
-// about all messages and fields.
-//
-// There is normally one pool per process. We make it a Python object only
-// because it contains many Python references.
-// TODO(amauryfa): See whether such objects can appear in reference cycles, and
-// consider adding support for the cyclic GC.
-//
-// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool
-// namespace.
-typedef struct PyDescriptorPool {
- PyObject_HEAD
-
- google::protobuf::DescriptorPool* pool;
-
- // Make our own mapping to retrieve Python classes from C++ descriptors.
- //
- // Descriptor pointers stored here are owned by the DescriptorPool above.
- // Python references to classes are owned by this PyDescriptorPool.
- typedef hash_map<const Descriptor *, PyObject *> ClassesByMessageMap;
- ClassesByMessageMap *classes_by_descriptor;
-} PyDescriptorPool;
-
-
-extern PyTypeObject CMessageDescriptor_Type;
-extern PyTypeObject CFieldDescriptor_Type;
-
-extern PyTypeObject PyDescriptorPool_Type;
-
-
-namespace cdescriptor_pool {
-
-// Builds a new DescriptorPool. Normally called only once per process.
-PyDescriptorPool* NewDescriptorPool();
-
-// Looks up a message by name.
-// Returns a message Descriptor, or NULL if not found.
-const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
- const string& name);
-
-// Registers a new Python class for the given message descriptor.
-// Returns the message Descriptor.
-// On error, returns NULL with a Python exception set.
-const google::protobuf::Descriptor* RegisterMessageClass(
- PyDescriptorPool* self, PyObject *message_class, PyObject *descriptor);
+extern PyTypeObject PyMessageDescriptor_Type;
+extern PyTypeObject PyFieldDescriptor_Type;
+extern PyTypeObject PyEnumDescriptor_Type;
+extern PyTypeObject PyEnumValueDescriptor_Type;
+extern PyTypeObject PyFileDescriptor_Type;
+extern PyTypeObject PyOneofDescriptor_Type;
+
+// Return a new reference to a Descriptor 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);
+
+// 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);
-// Retrieves the Python class registered with the given message descriptor.
-//
-// Returns a *borrowed* reference if found, otherwise returns NULL with an
+// Return the C++ descriptor pointer.
+// This function checks the parameter type; on error, return NULL with a Python
// exception set.
-PyObject *GetMessageClass(PyDescriptorPool* self,
- const Descriptor *message_descriptor);
+const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj);
+const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj);
-// Looks up a field by name. Returns a CDescriptor corresponding to
-// the field on success, or NULL on failure.
-//
-// Returns a new reference.
-PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name);
+// Returns the raw C++ pointer.
+const void* PyDescriptor_AsVoidPtr(PyObject* obj);
-// Looks up an extension by name. Returns a CDescriptor corresponding
-// to the field on success, or NULL on failure.
+// Check that the calling Python code is the global scope of a _pb2.py module.
+// This function is used to support the current code generated by the proto
+// compiler, which insists on modifying descriptors after they have been
+// created.
//
-// Returns a new reference.
-PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg);
-} // namespace cdescriptor_pool
+// stacklevel indicates which Python frame should be the _pb2.py module.
+//
+// Don't use this function outside descriptor classes.
+bool _CalledFromGeneratedFile(int stacklevel);
-PyObject* Python_BuildFile(PyObject* ignored, PyObject* args);
bool InitDescriptor();
} // namespace python
diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc
new file mode 100644
index 00000000..06edebf8
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_containers.cc
@@ -0,0 +1,1564 @@
+// 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.
+
+// Mappings and Sequences of descriptors.
+// Used by Descriptor.fields_by_name, EnumDescriptor.values...
+//
+// They avoid the allocation of a full dictionary or a full list: they simply
+// store a pointer to the parent descriptor, use the C++ Descriptor methods (see
+// google/protobuf/descriptor.h) to retrieve other descriptors, and create
+// Python objects on the fly.
+//
+// The containers fully conform to abc.Mapping and abc.Sequence, and behave just
+// like read-only dictionaries and lists.
+//
+// Because the interface of C++ Descriptors is quite regular, this file actually
+// defines only three types, the exact behavior of a container is controlled by
+// a DescriptorContainerDef structure, which contains functions that uses the
+// public Descriptor API.
+//
+// Note: This DescriptorContainerDef is similar to the "virtual methods table"
+// that a C++ compiler generates for a class. We have to make it explicit
+// because the Python API is based on C, and does not play well with C++
+// inheritance.
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/pyext/descriptor_containers.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+
+#if PY_MAJOR_VERSION >= 3
+ #define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+ #define PyString_FromFormat PyUnicode_FromFormat
+ #define PyInt_FromLong PyLong_FromLong
+ #if PY_VERSION_HEX < 0x03030000
+ #error "Python 3.0 - 3.2 are not supported."
+ #endif
+ #define PyString_AsStringAndSize(ob, charpp, sizep) \
+ (PyUnicode_Check(ob)? \
+ ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+ PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+struct PyContainer;
+
+typedef int (*CountMethod)(PyContainer* self);
+typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
+typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name);
+typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
+typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
+typedef const string& (*GetItemNameMethod)(const void* descriptor);
+typedef int (*GetItemNumberMethod)(const void* descriptor);
+typedef int (*GetItemIndexMethod)(const void* descriptor);
+
+struct DescriptorContainerDef {
+ const char* mapping_name;
+ // Returns the number of items in the container.
+ CountMethod count_fn;
+ // Retrieve item by index (usually the order of declaration in the proto file)
+ // Used by sequences, but also iterators. 0 <= index < Count().
+ GetByIndexMethod get_by_index_fn;
+ // Retrieve item by name (usually a call to some 'FindByName' method).
+ // Used by "by_name" mappings.
+ GetByNameMethod get_by_name_fn;
+ // Retrieve item by declared number (field tag, or enum value).
+ // Used by "by_number" mappings.
+ GetByNumberMethod get_by_number_fn;
+ // Converts a item C++ descriptor to a Python object. Returns a new reference.
+ NewObjectFromItemMethod new_object_from_item_fn;
+ // Retrieve the name of an item. Used by iterators on "by_name" mappings.
+ GetItemNameMethod get_item_name_fn;
+ // Retrieve the number of an item. Used by iterators on "by_number" mappings.
+ GetItemNumberMethod get_item_number_fn;
+ // Retrieve the index of an item for the container type.
+ // Used by "__contains__".
+ // If not set, "x in sequence" will do a linear search.
+ GetItemIndexMethod get_item_index_fn;
+};
+
+struct PyContainer {
+ PyObject_HEAD
+
+ // The proto2 descriptor this container belongs to the global DescriptorPool.
+ const void* descriptor;
+
+ // A pointer to a static structure with function pointers that control the
+ // behavior of the container. Very similar to the table of virtual functions
+ // of a C++ class.
+ const DescriptorContainerDef* container_def;
+
+ // The kind of container: list, or dict by name or value.
+ enum ContainerKind {
+ KIND_SEQUENCE,
+ KIND_BYNAME,
+ KIND_BYNUMBER,
+ } kind;
+};
+
+struct PyContainerIterator {
+ PyObject_HEAD
+
+ // The container we are iterating over. Own a reference.
+ PyContainer* container;
+
+ // The current index in the iterator.
+ int index;
+
+ // The kind of container: list, or dict by name or value.
+ enum IterKind {
+ KIND_ITERKEY,
+ KIND_ITERVALUE,
+ KIND_ITERITEM,
+ KIND_ITERVALUE_REVERSED, // For sequences
+ } kind;
+};
+
+namespace descriptor {
+
+// Returns the C++ item descriptor for a given Python key.
+// When the descriptor is found, return true and set *item.
+// When the descriptor is not found, return true, but set *item to NULL.
+// On error, returns false with an exception set.
+static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) {
+ switch (self->kind) {
+ case PyContainer::KIND_BYNAME:
+ {
+ char* name;
+ Py_ssize_t name_size;
+ if (PyString_AsStringAndSize(key, &name, &name_size) < 0) {
+ if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+ // Not a string, cannot be in the container.
+ PyErr_Clear();
+ *item = NULL;
+ return true;
+ }
+ return false;
+ }
+ *item = self->container_def->get_by_name_fn(
+ self, string(name, name_size));
+ return true;
+ }
+ case PyContainer::KIND_BYNUMBER:
+ {
+ Py_ssize_t number = PyNumber_AsSsize_t(key, NULL);
+ if (number == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+ // Not a number, cannot be in the container.
+ PyErr_Clear();
+ *item = NULL;
+ return true;
+ }
+ return false;
+ }
+ *item = self->container_def->get_by_number_fn(self, number);
+ return true;
+ }
+ default:
+ PyErr_SetNone(PyExc_NotImplementedError);
+ return false;
+ }
+}
+
+// Returns the key of the object at the given index.
+// Used when iterating over mappings.
+static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) {
+ const void* item = self->container_def->get_by_index_fn(self, index);
+ switch (self->kind) {
+ case PyContainer::KIND_BYNAME:
+ {
+ const string& name(self->container_def->get_item_name_fn(item));
+ return PyString_FromStringAndSize(name.c_str(), name.size());
+ }
+ case PyContainer::KIND_BYNUMBER:
+ {
+ int value = self->container_def->get_item_number_fn(item);
+ return PyInt_FromLong(value);
+ }
+ default:
+ PyErr_SetNone(PyExc_NotImplementedError);
+ return NULL;
+ }
+}
+
+// Returns the object at the given index.
+// Also used when iterating over mappings.
+static PyObject* _NewObj_ByIndex(PyContainer* self, Py_ssize_t index) {
+ return self->container_def->new_object_from_item_fn(
+ self->container_def->get_by_index_fn(self, index));
+}
+
+static Py_ssize_t Length(PyContainer* self) {
+ return self->container_def->count_fn(self);
+}
+
+// The DescriptorMapping type.
+
+static PyObject* Subscript(PyContainer* self, PyObject* key) {
+ const void* item = NULL;
+ if (!_GetItemByKey(self, key, &item)) {
+ return NULL;
+ }
+ if (!item) {
+ PyErr_SetObject(PyExc_KeyError, key);
+ return NULL;
+ }
+ return self->container_def->new_object_from_item_fn(item);
+}
+
+static int AssSubscript(PyContainer* self, PyObject* key, PyObject* value) {
+ if (_CalledFromGeneratedFile(0)) {
+ return 0;
+ }
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object does not support item assignment",
+ Py_TYPE(self)->tp_name);
+ return -1;
+}
+
+static PyMappingMethods MappingMappingMethods = {
+ (lenfunc)Length, // mp_length
+ (binaryfunc)Subscript, // mp_subscript
+ (objobjargproc)AssSubscript, // mp_ass_subscript
+};
+
+static int Contains(PyContainer* self, PyObject* key) {
+ const void* item = NULL;
+ if (!_GetItemByKey(self, key, &item)) {
+ return -1;
+ }
+ if (item) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static PyObject* ContainerRepr(PyContainer* self) {
+ const char* kind = "";
+ switch (self->kind) {
+ case PyContainer::KIND_SEQUENCE:
+ kind = "sequence";
+ break;
+ case PyContainer::KIND_BYNAME:
+ kind = "mapping by name";
+ break;
+ case PyContainer::KIND_BYNUMBER:
+ kind = "mapping by number";
+ break;
+ }
+ return PyString_FromFormat(
+ "<%s %s>", self->container_def->mapping_name, kind);
+}
+
+extern PyTypeObject DescriptorMapping_Type;
+extern PyTypeObject DescriptorSequence_Type;
+
+// A sequence container can only be equal to another sequence container, or (for
+// backward compatibility) to a list containing the same items.
+// Returns 1 if equal, 0 if unequal, -1 on error.
+static int DescriptorSequence_Equal(PyContainer* self, PyObject* other) {
+ // Check the identity of C++ pointers.
+ if (PyObject_TypeCheck(other, &DescriptorSequence_Type)) {
+ PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
+ if (self->descriptor == other_container->descriptor &&
+ self->container_def == other_container->container_def &&
+ self->kind == other_container->kind) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ // If other is a list
+ if (PyList_Check(other)) {
+ // return list(self) == other
+ int size = Length(self);
+ if (size != PyList_Size(other)) {
+ return false;
+ }
+ for (int index = 0; index < size; index++) {
+ ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
+ if (value1 == NULL) {
+ return -1;
+ }
+ PyObject* value2 = PyList_GetItem(other, index);
+ if (value2 == NULL) {
+ return -1;
+ }
+ int cmp = PyObject_RichCompareBool(value1, value2, Py_EQ);
+ if (cmp != 1) // error or not equal
+ return cmp;
+ }
+ // All items were found and equal
+ return 1;
+ }
+
+ // Any other object is different.
+ return 0;
+}
+
+// A mapping container can only be equal to another mapping container, or (for
+// backward compatibility) to a dict containing the same items.
+// Returns 1 if equal, 0 if unequal, -1 on error.
+static int DescriptorMapping_Equal(PyContainer* self, PyObject* other) {
+ // Check the identity of C++ pointers.
+ if (PyObject_TypeCheck(other, &DescriptorMapping_Type)) {
+ PyContainer* other_container = reinterpret_cast<PyContainer*>(other);
+ if (self->descriptor == other_container->descriptor &&
+ self->container_def == other_container->container_def &&
+ self->kind == other_container->kind) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ // If other is a dict
+ if (PyDict_Check(other)) {
+ // equivalent to dict(self.items()) == other
+ int size = Length(self);
+ if (size != PyDict_Size(other)) {
+ return false;
+ }
+ for (int index = 0; index < size; index++) {
+ ScopedPyObjectPtr key(_NewKey_ByIndex(self, index));
+ if (key == NULL) {
+ return -1;
+ }
+ ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index));
+ if (value1 == NULL) {
+ return -1;
+ }
+ PyObject* value2 = PyDict_GetItem(other, key);
+ if (value2 == NULL) {
+ // Not found in the other dictionary
+ return 0;
+ }
+ int cmp = PyObject_RichCompareBool(value1, value2, Py_EQ);
+ if (cmp != 1) // error or not equal
+ return cmp;
+ }
+ // All items were found and equal
+ return 1;
+ }
+
+ // Any other object is different.
+ return 0;
+}
+
+static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) {
+ if (opid != Py_EQ && opid != Py_NE) {
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+ }
+
+ int result;
+
+ if (self->kind == PyContainer::KIND_SEQUENCE) {
+ result = DescriptorSequence_Equal(self, other);
+ } else {
+ result = DescriptorMapping_Equal(self, other);
+ }
+ if (result < 0) {
+ return NULL;
+ }
+ if (result ^ (opid == Py_NE)) {
+ Py_RETURN_TRUE;
+ } else {
+ Py_RETURN_FALSE;
+ }
+}
+
+static PySequenceMethods MappingSequenceMethods = {
+ 0, // sq_length
+ 0, // sq_concat
+ 0, // sq_repeat
+ 0, // sq_item
+ 0, // sq_slice
+ 0, // sq_ass_item
+ 0, // sq_ass_slice
+ (objobjproc)Contains, // sq_contains
+};
+
+static PyObject* Get(PyContainer* self, PyObject* args) {
+ PyObject* key;
+ PyObject* default_value = Py_None;
+ if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) {
+ return NULL;
+ }
+
+ const void* item;
+ if (!_GetItemByKey(self, key, &item)) {
+ return NULL;
+ }
+ if (item == NULL) {
+ Py_INCREF(default_value);
+ return default_value;
+ }
+ return self->container_def->new_object_from_item_fn(item);
+}
+
+static PyObject* Keys(PyContainer* self, PyObject* args) {
+ Py_ssize_t count = Length(self);
+ ScopedPyObjectPtr list(PyList_New(count));
+ if (list == NULL) {
+ return NULL;
+ }
+ for (Py_ssize_t index = 0; index < count; ++index) {
+ PyObject* key = _NewKey_ByIndex(self, index);
+ if (key == NULL) {
+ return NULL;
+ }
+ PyList_SET_ITEM(list.get(), index, key);
+ }
+ return list.release();
+}
+
+static PyObject* Values(PyContainer* self, PyObject* args) {
+ Py_ssize_t count = Length(self);
+ ScopedPyObjectPtr list(PyList_New(count));
+ if (list == NULL) {
+ return NULL;
+ }
+ for (Py_ssize_t index = 0; index < count; ++index) {
+ PyObject* value = _NewObj_ByIndex(self, index);
+ if (value == NULL) {
+ return NULL;
+ }
+ PyList_SET_ITEM(list.get(), index, value);
+ }
+ return list.release();
+}
+
+static PyObject* Items(PyContainer* self, PyObject* args) {
+ Py_ssize_t count = Length(self);
+ ScopedPyObjectPtr list(PyList_New(count));
+ if (list == NULL) {
+ return NULL;
+ }
+ for (Py_ssize_t index = 0; index < count; ++index) {
+ ScopedPyObjectPtr obj(PyTuple_New(2));
+ if (obj == NULL) {
+ return NULL;
+ }
+ PyObject* key = _NewKey_ByIndex(self, index);
+ if (key == NULL) {
+ return NULL;
+ }
+ PyTuple_SET_ITEM(obj.get(), 0, key);
+ PyObject* value = _NewObj_ByIndex(self, index);
+ if (value == NULL) {
+ return NULL;
+ }
+ PyTuple_SET_ITEM(obj.get(), 1, value);
+ PyList_SET_ITEM(list.get(), index, obj.release());
+ }
+ return list.release();
+}
+
+static PyObject* NewContainerIterator(PyContainer* mapping,
+ PyContainerIterator::IterKind kind);
+
+static PyObject* Iter(PyContainer* self) {
+ return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
+}
+static PyObject* IterKeys(PyContainer* self, PyObject* args) {
+ return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY);
+}
+static PyObject* IterValues(PyContainer* self, PyObject* args) {
+ return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE);
+}
+static PyObject* IterItems(PyContainer* self, PyObject* args) {
+ return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM);
+}
+
+static PyMethodDef MappingMethods[] = {
+ { "get", (PyCFunction)Get, METH_VARARGS, },
+ { "keys", (PyCFunction)Keys, METH_NOARGS, },
+ { "values", (PyCFunction)Values, METH_NOARGS, },
+ { "items", (PyCFunction)Items, METH_NOARGS, },
+ { "iterkeys", (PyCFunction)IterKeys, METH_NOARGS, },
+ { "itervalues", (PyCFunction)IterValues, METH_NOARGS, },
+ { "iteritems", (PyCFunction)IterItems, METH_NOARGS, },
+ {NULL}
+};
+
+PyTypeObject DescriptorMapping_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "DescriptorMapping", // tp_name
+ sizeof(PyContainer), // tp_basicsize
+ 0, // tp_itemsize
+ 0, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ (reprfunc)ContainerRepr, // tp_repr
+ 0, // tp_as_number
+ &MappingSequenceMethods, // tp_as_sequence
+ &MappingMappingMethods, // 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
+ 0, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ (richcmpfunc)RichCompare, // tp_richcompare
+ 0, // tp_weaklistoffset
+ (getiterfunc)Iter, // tp_iter
+ 0, // tp_iternext
+ MappingMethods, // 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
+ 0, // tp_free
+};
+
+// The DescriptorSequence type.
+
+static PyObject* GetItem(PyContainer* self, Py_ssize_t index) {
+ if (index < 0) {
+ index += Length(self);
+ }
+ if (index < 0 || index >= Length(self)) {
+ PyErr_SetString(PyExc_IndexError, "index out of range");
+ return NULL;
+ }
+ return _NewObj_ByIndex(self, index);
+}
+
+// Returns the position of the item in the sequence, of -1 if not found.
+// This function never fails.
+int Find(PyContainer* self, PyObject* item) {
+ // The item can only be in one position: item.index.
+ // Check that self[item.index] == item, it's faster than a linear search.
+ //
+ // This assumes that sequences are only defined by syntax of the .proto file:
+ // a specific item belongs to only one sequence, depending on its position in
+ // the .proto file definition.
+ const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item);
+ if (descriptor_ptr == NULL) {
+ // Not a descriptor, it cannot be in the list.
+ return -1;
+ }
+ if (self->container_def->get_item_index_fn) {
+ int index = self->container_def->get_item_index_fn(descriptor_ptr);
+ if (index < 0 || index >= Length(self)) {
+ // This index is not from this collection.
+ return -1;
+ }
+ if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) {
+ // The descriptor at this index is not the same.
+ return -1;
+ }
+ // self[item.index] == item, so return the index.
+ return index;
+ } else {
+ // Fall back to linear search.
+ int length = Length(self);
+ for (int index=0; index < length; index++) {
+ if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) {
+ return index;
+ }
+ }
+ // Not found
+ return -1;
+ }
+}
+
+// Implements list.index(): the position of the item is in the sequence.
+static PyObject* Index(PyContainer* self, PyObject* item) {
+ int position = Find(self, item);
+ if (position < 0) {
+ // Not found
+ PyErr_SetNone(PyExc_ValueError);
+ return NULL;
+ } else {
+ return PyInt_FromLong(position);
+ }
+}
+// Implements "list.__contains__()": is the object in the sequence.
+static int SeqContains(PyContainer* self, PyObject* item) {
+ int position = Find(self, item);
+ if (position < 0) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+// Implements list.count(): number of occurrences of the item in the sequence.
+// An item can only appear once in a sequence. If it exists, return 1.
+static PyObject* Count(PyContainer* self, PyObject* item) {
+ int position = Find(self, item);
+ if (position < 0) {
+ return PyInt_FromLong(0);
+ } else {
+ return PyInt_FromLong(1);
+ }
+}
+
+static PyObject* Append(PyContainer* self, PyObject* args) {
+ if (_CalledFromGeneratedFile(0)) {
+ Py_RETURN_NONE;
+ }
+ PyErr_Format(PyExc_TypeError,
+ "'%.200s' object is not a mutable sequence",
+ Py_TYPE(self)->tp_name);
+ return NULL;
+}
+
+static PyObject* Reversed(PyContainer* self, PyObject* args) {
+ return NewContainerIterator(self,
+ PyContainerIterator::KIND_ITERVALUE_REVERSED);
+}
+
+static PyMethodDef SeqMethods[] = {
+ { "index", (PyCFunction)Index, METH_O, },
+ { "count", (PyCFunction)Count, METH_O, },
+ { "append", (PyCFunction)Append, METH_O, },
+ { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, },
+ {NULL}
+};
+
+static PySequenceMethods SeqSequenceMethods = {
+ (lenfunc)Length, // sq_length
+ 0, // sq_concat
+ 0, // sq_repeat
+ (ssizeargfunc)GetItem, // sq_item
+ 0, // sq_slice
+ 0, // sq_ass_item
+ 0, // sq_ass_slice
+ (objobjproc)SeqContains, // sq_contains
+};
+
+PyTypeObject DescriptorSequence_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "DescriptorSequence", // tp_name
+ sizeof(PyContainer), // tp_basicsize
+ 0, // tp_itemsize
+ 0, // tp_dealloc
+ 0, // tp_print
+ 0, // tp_getattr
+ 0, // tp_setattr
+ 0, // tp_compare
+ (reprfunc)ContainerRepr, // tp_repr
+ 0, // tp_as_number
+ &SeqSequenceMethods, // 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
+ 0, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ (richcmpfunc)RichCompare, // tp_richcompare
+ 0, // tp_weaklistoffset
+ 0, // tp_iter
+ 0, // tp_iternext
+ SeqMethods, // 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
+ 0, // tp_free
+};
+
+static PyObject* NewMappingByName(
+ DescriptorContainerDef* container_def, const void* descriptor) {
+ PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
+ if (self == NULL) {
+ return NULL;
+ }
+ self->descriptor = descriptor;
+ self->container_def = container_def;
+ self->kind = PyContainer::KIND_BYNAME;
+ return reinterpret_cast<PyObject*>(self);
+}
+
+static PyObject* NewMappingByNumber(
+ DescriptorContainerDef* container_def, const void* descriptor) {
+ if (container_def->get_by_number_fn == NULL ||
+ container_def->get_item_number_fn == NULL) {
+ PyErr_SetNone(PyExc_NotImplementedError);
+ return NULL;
+ }
+ PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type);
+ if (self == NULL) {
+ return NULL;
+ }
+ self->descriptor = descriptor;
+ self->container_def = container_def;
+ self->kind = PyContainer::KIND_BYNUMBER;
+ return reinterpret_cast<PyObject*>(self);
+}
+
+static PyObject* NewSequence(
+ DescriptorContainerDef* container_def, const void* descriptor) {
+ PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type);
+ if (self == NULL) {
+ return NULL;
+ }
+ self->descriptor = descriptor;
+ self->container_def = container_def;
+ self->kind = PyContainer::KIND_SEQUENCE;
+ return reinterpret_cast<PyObject*>(self);
+}
+
+// Implement iterators over PyContainers.
+
+static void Iterator_Dealloc(PyContainerIterator* self) {
+ Py_CLEAR(self->container);
+ Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyObject* Iterator_Next(PyContainerIterator* self) {
+ int count = self->container->container_def->count_fn(self->container);
+ if (self->index >= count) {
+ // Return NULL with no exception to indicate the end.
+ return NULL;
+ }
+ int index = self->index;
+ self->index += 1;
+ switch (self->kind) {
+ case PyContainerIterator::KIND_ITERKEY:
+ return _NewKey_ByIndex(self->container, index);
+ case PyContainerIterator::KIND_ITERVALUE:
+ return _NewObj_ByIndex(self->container, index);
+ case PyContainerIterator::KIND_ITERVALUE_REVERSED:
+ return _NewObj_ByIndex(self->container, count - index - 1);
+ case PyContainerIterator::KIND_ITERITEM:
+ {
+ PyObject* obj = PyTuple_New(2);
+ if (obj == NULL) {
+ return NULL;
+ }
+ PyObject* key = _NewKey_ByIndex(self->container, index);
+ if (key == NULL) {
+ Py_DECREF(obj);
+ return NULL;
+ }
+ PyTuple_SET_ITEM(obj, 0, key);
+ PyObject* value = _NewObj_ByIndex(self->container, index);
+ if (value == NULL) {
+ Py_DECREF(obj);
+ return NULL;
+ }
+ PyTuple_SET_ITEM(obj, 1, value);
+ return obj;
+ }
+ default:
+ PyErr_SetNone(PyExc_NotImplementedError);
+ return NULL;
+ }
+}
+
+static PyTypeObject ContainerIterator_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "DescriptorContainerIterator", // tp_name
+ sizeof(PyContainerIterator), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)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
+ 0, // tp_doc
+ 0, // tp_traverse
+ 0, // tp_clear
+ 0, // tp_richcompare
+ 0, // tp_weaklistoffset
+ PyObject_SelfIter, // tp_iter
+ (iternextfunc)Iterator_Next, // 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
+ 0, // tp_alloc
+ 0, // tp_new
+ 0, // tp_free
+};
+
+static PyObject* NewContainerIterator(PyContainer* container,
+ PyContainerIterator::IterKind kind) {
+ PyContainerIterator* self = PyObject_New(PyContainerIterator,
+ &ContainerIterator_Type);
+ if (self == NULL) {
+ return NULL;
+ }
+ Py_INCREF(container);
+ self->container = container;
+ self->kind = kind;
+ self->index = 0;
+
+ return reinterpret_cast<PyObject*>(self);
+}
+
+} // namespace descriptor
+
+// Now define the real collections!
+
+namespace message_descriptor {
+
+typedef const Descriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+ return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace fields {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->field_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindFieldByName(name);
+}
+
+static ItemDescriptor GetByNumber(PyContainer* self, int number) {
+ return GetDescriptor(self)->FindFieldByNumber(number);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->field(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyFieldDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemNumber(ItemDescriptor item) {
+ return item->number();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "MessageFields",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)GetByNumber,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)GetItemNumber,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace fields
+
+PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByName(&fields::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) {
+ return descriptor::NewSequence(&fields::ContainerDef, descriptor);
+}
+
+namespace nested_types {
+
+typedef const Descriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->nested_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindNestedTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->nested_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyMessageDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "MessageNestedTypes",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace nested_types
+
+PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) {
+ return descriptor::NewSequence(&nested_types::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor);
+}
+
+namespace enums {
+
+typedef const EnumDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->enum_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindEnumTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->enum_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyEnumDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "MessageNestedEnums",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace enums
+
+PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) {
+ return descriptor::NewSequence(&enums::ContainerDef, descriptor);
+}
+
+namespace enumvalues {
+
+// This is the "enum_values_by_name" mapping, which collects values from all
+// enum types in a message.
+//
+// Note that the behavior of the C++ descriptor is different: it will search and
+// return the first value that matches the name, whereas the Python
+// implementation retrieves the last one.
+
+typedef const EnumValueDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ int count = 0;
+ for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) {
+ count += GetDescriptor(self)->enum_type(i)->value_count();
+ }
+ return count;
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindEnumValueByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ // This is not optimal, but the number of enums *types* in a given message
+ // is small. This function is only used when iterating over the mapping.
+ const EnumDescriptor* enum_type = NULL;
+ int enum_type_count = GetDescriptor(self)->enum_type_count();
+ for (int i = 0; i < enum_type_count; ++i) {
+ enum_type = GetDescriptor(self)->enum_type(i);
+ int enum_value_count = enum_type->value_count();
+ if (index < enum_value_count) {
+ // Found it!
+ break;
+ }
+ index -= enum_value_count;
+ }
+ // The next statement cannot overflow, because this function is only called by
+ // internal iterators which ensure that 0 <= index < Count().
+ return enum_type->value(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyEnumValueDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "MessageEnumValues",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)NULL,
+};
+
+} // namespace enumvalues
+
+PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
+}
+
+namespace extensions {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->extension_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindExtensionByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->extension(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyFieldDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "MessageExtensions",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace extensions
+
+PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) {
+ return descriptor::NewSequence(&extensions::ContainerDef, descriptor);
+}
+
+namespace oneofs {
+
+typedef const OneofDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->oneof_decl_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindOneofByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->oneof_decl(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyOneofDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "MessageOneofs",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace oneofs
+
+PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor);
+}
+
+PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) {
+ return descriptor::NewSequence(&oneofs::ContainerDef, descriptor);
+}
+
+} // namespace message_descriptor
+
+namespace enum_descriptor {
+
+typedef const EnumDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+ return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace enumvalues {
+
+typedef const EnumValueDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->value_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->value(index);
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindValueByName(name);
+}
+
+static ItemDescriptor GetByNumber(PyContainer* self, int number) {
+ return GetDescriptor(self)->FindValueByNumber(number);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyEnumValueDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemNumber(ItemDescriptor item) {
+ return item->number();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "EnumValues",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)GetByNumber,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)GetItemNumber,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace enumvalues
+
+PyObject* NewEnumValuesByName(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor);
+}
+
+PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) {
+ return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor);
+}
+
+PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) {
+ return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor);
+}
+
+} // namespace enum_descriptor
+
+namespace oneof_descriptor {
+
+typedef const OneofDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+ return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace fields {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->field_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->field(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyFieldDescriptor_New(item);
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index_in_oneof();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "OneofFields",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)NULL,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)NULL,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace fields
+
+PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) {
+ return descriptor::NewSequence(&fields::ContainerDef, descriptor);
+}
+
+} // namespace oneof_descriptor
+
+namespace file_descriptor {
+
+typedef const FileDescriptor* ParentDescriptor;
+
+static ParentDescriptor GetDescriptor(PyContainer* self) {
+ return reinterpret_cast<ParentDescriptor>(self->descriptor);
+}
+
+namespace messages {
+
+typedef const Descriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->message_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindMessageTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->message_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyMessageDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "FileMessages",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace messages
+
+PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor) {
+ return descriptor::NewMappingByName(&messages::ContainerDef, descriptor);
+}
+
+namespace enums {
+
+typedef const EnumDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->enum_type_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindEnumTypeByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->enum_type(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyEnumDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "FileEnums",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace enums
+
+PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor) {
+ return descriptor::NewMappingByName(&enums::ContainerDef, descriptor);
+}
+
+namespace extensions {
+
+typedef const FieldDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->extension_count();
+}
+
+static ItemDescriptor GetByName(PyContainer* self, const string& name) {
+ return GetDescriptor(self)->FindExtensionByName(name);
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->extension(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyFieldDescriptor_New(item);
+}
+
+static const string& GetItemName(ItemDescriptor item) {
+ return item->name();
+}
+
+static int GetItemIndex(ItemDescriptor item) {
+ return item->index();
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "FileExtensions",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)GetByName,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)GetItemName,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)GetItemIndex,
+};
+
+} // namespace extensions
+
+PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor) {
+ return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor);
+}
+
+namespace dependencies {
+
+typedef const FileDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->dependency_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->dependency(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyFileDescriptor_New(item);
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "FileDependencies",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)NULL,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)NULL,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)NULL,
+};
+
+} // namespace dependencies
+
+PyObject* NewFileDependencies(const FileDescriptor* descriptor) {
+ return descriptor::NewSequence(&dependencies::ContainerDef, descriptor);
+}
+
+namespace public_dependencies {
+
+typedef const FileDescriptor* ItemDescriptor;
+
+static int Count(PyContainer* self) {
+ return GetDescriptor(self)->public_dependency_count();
+}
+
+static ItemDescriptor GetByIndex(PyContainer* self, int index) {
+ return GetDescriptor(self)->public_dependency(index);
+}
+
+static PyObject* NewObjectFromItem(ItemDescriptor item) {
+ return PyFileDescriptor_New(item);
+}
+
+static DescriptorContainerDef ContainerDef = {
+ "FilePublicDependencies",
+ (CountMethod)Count,
+ (GetByIndexMethod)GetByIndex,
+ (GetByNameMethod)NULL,
+ (GetByNumberMethod)NULL,
+ (NewObjectFromItemMethod)NewObjectFromItem,
+ (GetItemNameMethod)NULL,
+ (GetItemNumberMethod)NULL,
+ (GetItemIndexMethod)NULL,
+};
+
+} // namespace public_dependencies
+
+PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) {
+ return descriptor::NewSequence(&public_dependencies::ContainerDef,
+ descriptor);
+}
+
+} // namespace file_descriptor
+
+
+// Register all implementations
+
+bool InitDescriptorMappingTypes() {
+ if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0)
+ return false;
+ if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0)
+ return false;
+ if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0)
+ return false;
+ return true;
+}
+
+} // namespace python
+} // namespace protobuf
+} // namespace google
diff --git a/python/google/protobuf/pyext/descriptor_containers.h b/python/google/protobuf/pyext/descriptor_containers.h
new file mode 100644
index 00000000..d81537de
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_containers.h
@@ -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.
+
+// Mappings and Sequences of descriptors.
+// They implement containers like fields_by_name, EnumDescriptor.values...
+// See descriptor_containers.cc for more description.
+#include <Python.h>
+
+namespace google {
+namespace protobuf {
+
+class Descriptor;
+class FileDescriptor;
+class EnumDescriptor;
+class OneofDescriptor;
+
+namespace python {
+
+// Initialize the various types and objects.
+bool InitDescriptorMappingTypes();
+
+// Each function below returns a Mapping, or a Sequence of descriptors.
+// They all return a new reference.
+
+namespace message_descriptor {
+PyObject* NewMessageFieldsByName(const Descriptor* descriptor);
+PyObject* NewMessageFieldsByNumber(const Descriptor* descriptor);
+PyObject* NewMessageFieldsSeq(const Descriptor* descriptor);
+
+PyObject* NewMessageNestedTypesSeq(const Descriptor* descriptor);
+PyObject* NewMessageNestedTypesByName(const Descriptor* descriptor);
+
+PyObject* NewMessageEnumsByName(const Descriptor* descriptor);
+PyObject* NewMessageEnumsSeq(const Descriptor* descriptor);
+PyObject* NewMessageEnumValuesByName(const Descriptor* descriptor);
+
+PyObject* NewMessageExtensionsByName(const Descriptor* descriptor);
+PyObject* NewMessageExtensionsSeq(const Descriptor* descriptor);
+
+PyObject* NewMessageOneofsByName(const Descriptor* descriptor);
+PyObject* NewMessageOneofsSeq(const Descriptor* descriptor);
+} // namespace message_descriptor
+
+namespace enum_descriptor {
+PyObject* NewEnumValuesByName(const EnumDescriptor* descriptor);
+PyObject* NewEnumValuesByNumber(const EnumDescriptor* descriptor);
+PyObject* NewEnumValuesSeq(const EnumDescriptor* descriptor);
+} // namespace enum_descriptor
+
+namespace oneof_descriptor {
+PyObject* NewOneofFieldsSeq(const OneofDescriptor* descriptor);
+} // namespace oneof_descriptor
+
+namespace file_descriptor {
+PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor);
+
+PyObject* NewFileDependencies(const FileDescriptor* descriptor);
+PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor);
+} // namespace file_descriptor
+
+
+} // namespace python
+} // namespace protobuf
+} // namespace google
diff --git a/python/google/protobuf/pyext/descriptor_cpp2_test.py b/python/google/protobuf/pyext/descriptor_cpp2_test.py
deleted file mode 100644
index 3cf45a22..00000000
--- a/python/google/protobuf/pyext/descriptor_cpp2_test.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc. All rights reserved.
-# https://developers.google.com/protocol-buffers/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests for google.protobuf.pyext behavior."""
-
-__author__ = 'anuraag@google.com (Anuraag Agrawal)'
-
-import os
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2'
-
-# We must set the implementation version above before the google3 imports.
-# pylint: disable=g-import-not-at-top
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-# Run all tests from the original module by putting them in our namespace.
-# pylint: disable=wildcard-import
-from google.protobuf.internal.descriptor_test import *
-
-
-class ConfirmCppApi2Test(basetest.TestCase):
-
- def testImplementationSetting(self):
- self.assertEqual('cpp', api_implementation.Type())
- self.assertEqual(2, api_implementation.Version())
-
-
-if __name__ == '__main__':
- basetest.main()
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
new file mode 100644
index 00000000..bc3077bc
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -0,0 +1,370 @@
+// 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.
+
+// Implements the DescriptorPool, which collects all descriptors.
+
+#include <Python.h>
+
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
+#include <google/protobuf/pyext/descriptor.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
+ #error "Python 3.0 - 3.2 are not supported."
+ #endif
+ #define PyString_AsStringAndSize(ob, charpp, sizep) \
+ (PyUnicode_Check(ob)? \
+ ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+ PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
+#endif
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+namespace cdescriptor_pool {
+
+PyDescriptorPool* NewDescriptorPool() {
+ PyDescriptorPool* cdescriptor_pool = PyObject_New(
+ PyDescriptorPool, &PyDescriptorPool_Type);
+ if (cdescriptor_pool == NULL) {
+ return NULL;
+ }
+
+ // Build a DescriptorPool for messages only declared in Python libraries.
+ // generated_pool() contains all messages linked in C++ libraries, and is used
+ // as underlay.
+ cdescriptor_pool->pool = new DescriptorPool(DescriptorPool::generated_pool());
+
+ // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
+ // storage.
+ cdescriptor_pool->classes_by_descriptor =
+ new PyDescriptorPool::ClassesByMessageMap();
+ cdescriptor_pool->interned_descriptors =
+ new hash_map<const void*, PyObject *>();
+ cdescriptor_pool->descriptor_options =
+ new hash_map<const void*, PyObject *>();
+
+ return cdescriptor_pool;
+}
+
+static void Dealloc(PyDescriptorPool* self) {
+ typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+ for (iterator it = self->classes_by_descriptor->begin();
+ it != self->classes_by_descriptor->end(); ++it) {
+ Py_DECREF(it->second);
+ }
+ delete self->classes_by_descriptor;
+ delete self->interned_descriptors; // its references were borrowed.
+ for (hash_map<const void*, PyObject*>::iterator it =
+ self->descriptor_options->begin();
+ it != self->descriptor_options->end(); ++it) {
+ Py_DECREF(it->second);
+ }
+ delete self->descriptor_options;
+ Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) {
+ Py_ssize_t name_size;
+ char* name;
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+ return NULL;
+ }
+
+ const Descriptor* message_descriptor =
+ self->pool->FindMessageTypeByName(string(name, name_size));
+
+ if (message_descriptor == NULL) {
+ PyErr_Format(PyExc_TypeError, "Couldn't find message %.200s", name);
+ return NULL;
+ }
+
+ return PyMessageDescriptor_New(message_descriptor);
+}
+
+// Add a message class to our database.
+const Descriptor* RegisterMessageClass(
+ PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) {
+ ScopedPyObjectPtr full_message_name(
+ PyObject_GetAttrString(descriptor, "full_name"));
+ Py_ssize_t name_size;
+ char* name;
+ if (PyString_AsStringAndSize(full_message_name, &name, &name_size) < 0) {
+ return NULL;
+ }
+ const Descriptor *message_descriptor =
+ self->pool->FindMessageTypeByName(string(name, name_size));
+ if (!message_descriptor) {
+ PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'",
+ name);
+ return NULL;
+ }
+ Py_INCREF(message_class);
+ typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+ std::pair<iterator, bool> ret = self->classes_by_descriptor->insert(
+ std::make_pair(message_descriptor, message_class));
+ if (!ret.second) {
+ // Update case: DECREF the previous value.
+ Py_DECREF(ret.first->second);
+ ret.first->second = message_class;
+ }
+ return message_descriptor;
+}
+
+// Retrieve the message class added to our database.
+PyObject *GetMessageClass(PyDescriptorPool* self,
+ const Descriptor *message_descriptor) {
+ typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator;
+ iterator ret = self->classes_by_descriptor->find(message_descriptor);
+ if (ret == self->classes_by_descriptor->end()) {
+ PyErr_Format(PyExc_TypeError, "No message class registered for '%s'",
+ message_descriptor->full_name().c_str());
+ return NULL;
+ } else {
+ return ret->second;
+ }
+}
+
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) {
+ Py_ssize_t name_size;
+ char* name;
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+ return NULL;
+ }
+
+ const FieldDescriptor* field_descriptor =
+ self->pool->FindFieldByName(string(name, name_size));
+ if (field_descriptor == NULL) {
+ PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s",
+ name);
+ return NULL;
+ }
+
+ return PyFieldDescriptor_New(field_descriptor);
+}
+
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) {
+ Py_ssize_t name_size;
+ char* name;
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+ return NULL;
+ }
+
+ 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);
+ return NULL;
+ }
+
+ return PyFieldDescriptor_New(field_descriptor);
+}
+
+PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) {
+ Py_ssize_t name_size;
+ char* name;
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+ return NULL;
+ }
+
+ 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);
+ return NULL;
+ }
+
+ return PyEnumDescriptor_New(enum_descriptor);
+}
+
+PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) {
+ Py_ssize_t name_size;
+ char* name;
+ if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) {
+ return NULL;
+ }
+
+ 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);
+ return NULL;
+ }
+
+ return PyOneofDescriptor_New(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.
+
+
+// Collects errors that occur during proto file building to allow them to be
+// propagated in the python exception instead of only living in ERROR logs.
+class BuildFileErrorCollector : public DescriptorPool::ErrorCollector {
+ public:
+ BuildFileErrorCollector() : error_message(""), had_errors(false) {}
+
+ void AddError(const string& filename, const string& element_name,
+ const Message* descriptor, ErrorLocation location,
+ const string& message) {
+ // Replicates the logging behavior that happens in the C++ implementation
+ // when an error collector is not passed in.
+ if (!had_errors) {
+ error_message +=
+ ("Invalid proto descriptor for file \"" + filename + "\":\n");
+ }
+ // As this only happens on failure and will result in the program not
+ // running at all, no effort is made to optimize this string manipulation.
+ error_message += (" " + element_name + ": " + message + "\n");
+ }
+
+ string error_message;
+ bool had_errors;
+};
+
+PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) {
+ char* message_type;
+ Py_ssize_t message_len;
+
+ if (PyBytes_AsStringAndSize(serialized_pb, &message_type, &message_len) < 0) {
+ return NULL;
+ }
+
+ FileDescriptorProto file_proto;
+ if (!file_proto.ParseFromArray(message_type, message_len)) {
+ PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!");
+ return NULL;
+ }
+
+ // If the file was already part of a C++ library, all its descriptors are in
+ // the underlying pool. No need to do anything else.
+ const FileDescriptor* generated_file =
+ DescriptorPool::generated_pool()->FindFileByName(file_proto.name());
+ if (generated_file != NULL) {
+ return PyFileDescriptor_NewWithPb(generated_file, serialized_pb);
+ }
+
+ BuildFileErrorCollector error_collector;
+ const FileDescriptor* descriptor =
+ GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto,
+ &error_collector);
+ if (descriptor == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "Couldn't build proto file into descriptor pool!\n%s",
+ error_collector.error_message.c_str());
+ return NULL;
+ }
+
+ return PyFileDescriptor_NewWithPb(descriptor, serialized_pb);
+}
+
+static PyDescriptorPool* global_cdescriptor_pool = NULL;
+
+bool InitDescriptorPool() {
+ if (PyType_Ready(&PyDescriptorPool_Type) < 0)
+ return false;
+
+ global_cdescriptor_pool = cdescriptor_pool::NewDescriptorPool();
+ if (global_cdescriptor_pool == NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+PyDescriptorPool* GetDescriptorPool() {
+ return global_cdescriptor_pool;
+}
+
+} // namespace python
+} // namespace protobuf
+} // namespace google
diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h
new file mode 100644
index 00000000..4e494b89
--- /dev/null
+++ b/python/google/protobuf/pyext/descriptor_pool.h
@@ -0,0 +1,152 @@
+// 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_DESCRIPTOR_POOL_H__
+#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__
+
+#include <Python.h>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace python {
+
+// Wraps operations to the global DescriptorPool which contains information
+// about all messages and fields.
+//
+// There is normally one pool per process. We make it a Python object only
+// because it contains many Python references.
+// TODO(amauryfa): See whether such objects can appear in reference cycles, and
+// consider adding support for the cyclic GC.
+//
+// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool
+// namespace.
+typedef struct PyDescriptorPool {
+ PyObject_HEAD
+
+ DescriptorPool* pool;
+
+ // Make our own mapping to retrieve Python classes from C++ descriptors.
+ //
+ // Descriptor pointers stored here are owned by the DescriptorPool above.
+ // Python references to classes are owned by this PyDescriptorPool.
+ typedef hash_map<const Descriptor*, PyObject*> ClassesByMessageMap;
+ ClassesByMessageMap* classes_by_descriptor;
+
+ // Store interned descriptors, so that the same C++ descriptor yields the same
+ // Python object. Objects are not immortal: this map does not own the
+ // references, and items are deleted when the last reference to the object is
+ // released.
+ // This is enough to support the "is" operator on live objects.
+ // All descriptors are stored here.
+ hash_map<const void*, PyObject*>* interned_descriptors;
+
+ // Cache the options for any kind of descriptor.
+ // Descriptor pointers are owned by the DescriptorPool above.
+ // Python objects are owned by the map.
+ hash_map<const void*, PyObject*>* descriptor_options;
+} PyDescriptorPool;
+
+
+extern PyTypeObject PyDescriptorPool_Type;
+
+namespace cdescriptor_pool {
+
+// Builds a new DescriptorPool. Normally called only once per process.
+PyDescriptorPool* NewDescriptorPool();
+
+// Looks up a message by name.
+// Returns a message Descriptor, or NULL if not found.
+const Descriptor* FindMessageTypeByName(PyDescriptorPool* self,
+ const string& name);
+
+// Registers a new Python class for the given message descriptor.
+// Returns the message Descriptor.
+// On error, returns NULL with a Python exception set.
+const Descriptor* RegisterMessageClass(
+ PyDescriptorPool* self, PyObject* message_class, PyObject* descriptor);
+
+// Retrieves the Python class registered with the given message descriptor.
+//
+// Returns a *borrowed* reference if found, otherwise returns NULL with an
+// exception set.
+PyObject* GetMessageClass(PyDescriptorPool* self,
+ const Descriptor* message_descriptor);
+
+// Looks up a message by name. Returns a PyMessageDescriptor corresponding to
+// the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* name);
+
+// Looks up a field by name. Returns a PyFieldDescriptor corresponding to
+// the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name);
+
+// Looks up an extension by name. Returns a PyFieldDescriptor corresponding
+// to the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg);
+
+// Looks up an enum type by name. Returns a PyEnumDescriptor corresponding
+// to the field on success, or NULL on failure.
+//
+// Returns a new reference.
+PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg);
+
+// Looks up a oneof by name. Returns a COneofDescriptor corresponding
+// to the oneof on success, or NULL on failure.
+//
+// Returns a new reference.
+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.
+PyDescriptorPool* GetDescriptorPool();
+
+// Initialize objects used by this module.
+bool InitDescriptorPool();
+
+} // namespace python
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index d83b57d5..8e38fc42 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/message.h>
#include <google/protobuf/pyext/repeated_composite_container.h>
#include <google/protobuf/pyext/repeated_scalar_container.h>
@@ -48,13 +49,11 @@ namespace google {
namespace protobuf {
namespace python {
-extern google::protobuf::DynamicMessageFactory* global_message_factory;
-
namespace extension_dict {
// TODO(tibell): Always use self->message for clarity, just like in
// RepeatedCompositeContainer.
-static google::protobuf::Message* GetMessage(ExtensionDict* self) {
+static Message* GetMessage(ExtensionDict* self) {
if (self->parent != NULL) {
return self->parent->message;
} else {
@@ -73,10 +72,9 @@ PyObject* len(ExtensionDict* self) {
// TODO(tibell): Use VisitCompositeField.
int ReleaseExtension(ExtensionDict* self,
PyObject* extension,
- const google::protobuf::FieldDescriptor* descriptor) {
- if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
- if (descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ const FieldDescriptor* descriptor) {
+ if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+ if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (repeated_composite_container::Release(
reinterpret_cast<RepeatedCompositeContainer*>(
extension)) < 0) {
@@ -89,8 +87,7 @@ int ReleaseExtension(ExtensionDict* self,
return -1;
}
}
- } else if (descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (cmessage::ReleaseSubMessage(
GetMessage(self), descriptor,
reinterpret_cast<CMessage*>(extension)) < 0) {
@@ -102,8 +99,7 @@ int ReleaseExtension(ExtensionDict* self,
}
PyObject* subscript(ExtensionDict* self, PyObject* key) {
- const google::protobuf::FieldDescriptor* descriptor =
- cmessage::GetExtensionDescriptor(key);
+ const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
if (descriptor == NULL) {
return NULL;
}
@@ -162,8 +158,7 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) {
}
int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
- const google::protobuf::FieldDescriptor* descriptor =
- cmessage::GetExtensionDescriptor(key);
+ const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
if (descriptor == NULL) {
return -1;
}
@@ -187,7 +182,7 @@ int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) {
}
PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
- const google::protobuf::FieldDescriptor* descriptor =
+ const FieldDescriptor* descriptor =
cmessage::GetExtensionDescriptor(extension);
if (descriptor == NULL) {
return NULL;
@@ -208,7 +203,7 @@ PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
}
PyObject* HasExtension(ExtensionDict* self, PyObject* extension) {
- const google::protobuf::FieldDescriptor* descriptor =
+ const FieldDescriptor* descriptor =
cmessage::GetExtensionDescriptor(extension);
if (descriptor == NULL) {
return NULL;
diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h
index 47625e23..7e1049f1 100644
--- a/python/google/protobuf/pyext/extension_dict.h
+++ b/python/google/protobuf/pyext/extension_dict.h
@@ -41,7 +41,6 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
-
namespace google {
namespace protobuf {
@@ -94,7 +93,7 @@ PyObject* len(ExtensionDict* self);
// Returns 0 on success, -1 on failure.
int ReleaseExtension(ExtensionDict* self,
PyObject* extension,
- const google::protobuf::FieldDescriptor* descriptor);
+ const FieldDescriptor* descriptor);
// Gets an extension from the dict for the given extension descriptor.
//
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index cd956e0e..a2b357b2 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -39,6 +39,7 @@
#endif
#include <string>
#include <vector>
+#include <structmember.h> // A Python header file.
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
@@ -54,10 +55,12 @@
#include <google/protobuf/message.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/pyext/descriptor.h>
+#include <google/protobuf/pyext/descriptor_pool.h>
#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/scoped_pyobject_ptr.h>
+#include <google/protobuf/stubs/strutil.h>
#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
@@ -72,6 +75,10 @@
#else
#define PyString_AsString(ob) \
(PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob))
+ #define PyString_AsStringAndSize(ob, charpp, sizep) \
+ (PyUnicode_Check(ob)? \
+ ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \
+ PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
#endif
#endif
@@ -81,14 +88,14 @@ namespace python {
// Forward declarations
namespace cmessage {
-static const google::protobuf::FieldDescriptor* GetFieldDescriptor(
+static const FieldDescriptor* GetFieldDescriptor(
CMessage* self, PyObject* name);
-static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls);
+static const Descriptor* GetMessageDescriptor(PyTypeObject* cls);
static string GetMessageName(CMessage* self);
int InternalReleaseFieldByDescriptor(
- const google::protobuf::FieldDescriptor* field_descriptor,
+ const FieldDescriptor* field_descriptor,
PyObject* composite_field,
- google::protobuf::Message* parent_message);
+ Message* parent_message);
} // namespace cmessage
// ---------------------------------------------------------------------
@@ -107,7 +114,7 @@ struct ChildVisitor {
// Returns 0 on success, -1 on failure.
int VisitCMessage(CMessage* cmessage,
- const google::protobuf::FieldDescriptor* field_descriptor) {
+ const FieldDescriptor* field_descriptor) {
return 0;
}
};
@@ -118,8 +125,8 @@ template<class Visitor>
static int VisitCompositeField(const FieldDescriptor* descriptor,
PyObject* child,
Visitor visitor) {
- if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
- if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+ if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
RepeatedCompositeContainer* container =
reinterpret_cast<RepeatedCompositeContainer*>(child);
if (visitor.VisitRepeatedCompositeContainer(container) == -1)
@@ -130,8 +137,7 @@ static int VisitCompositeField(const FieldDescriptor* descriptor,
if (visitor.VisitRepeatedScalarContainer(container) == -1)
return -1;
}
- } else if (descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
CMessage* cmsg = reinterpret_cast<CMessage*>(child);
if (visitor.VisitCMessage(cmsg, descriptor) == -1)
return -1;
@@ -149,25 +155,31 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
PyObject* key;
PyObject* field;
- // Never use self->message in this function, it may be already freed.
- const google::protobuf::Descriptor* message_descriptor =
- cmessage::GetMessageDescriptor(Py_TYPE(self));
-
// Visit normal fields.
- while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
- const google::protobuf::FieldDescriptor* descriptor =
- message_descriptor->FindFieldByName(PyString_AsString(key));
- if (descriptor != NULL) {
- if (VisitCompositeField(descriptor, field, visitor) == -1)
+ if (self->composite_fields) {
+ // Never use self->message in this function, it may be already freed.
+ const Descriptor* message_descriptor =
+ cmessage::GetMessageDescriptor(Py_TYPE(self));
+ while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
+ Py_ssize_t key_str_size;
+ char *key_str_data;
+ if (PyString_AsStringAndSize(key, &key_str_data, &key_str_size) != 0)
return -1;
+ const string key_str(key_str_data, key_str_size);
+ const FieldDescriptor* descriptor =
+ message_descriptor->FindFieldByName(key_str);
+ if (descriptor != NULL) {
+ if (VisitCompositeField(descriptor, field, visitor) == -1)
+ return -1;
+ }
}
}
// Visit extension fields.
if (self->extensions != NULL) {
+ pos = 0;
while (PyDict_Next(self->extensions->values, &pos, &key, &field)) {
- const google::protobuf::FieldDescriptor* descriptor =
- cmessage::GetExtensionDescriptor(key);
+ const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key);
if (descriptor == NULL)
return -1;
if (VisitCompositeField(descriptor, field, visitor) == -1)
@@ -180,6 +192,8 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
// ---------------------------------------------------------------------
+static DynamicMessageFactory* message_factory;
+
// Constants used for integer type range checking.
PyObject* kPythonZero;
PyObject* kint32min_py;
@@ -198,17 +212,8 @@ PyObject* PickleError_class;
static PyObject* kDESCRIPTOR;
static PyObject* k_cdescriptor;
static PyObject* kfull_name;
-static PyObject* kname;
-static PyObject* kextensions_by_name;
static PyObject* k_extensions_by_name;
static PyObject* k_extensions_by_number;
-static PyObject* kfields_by_name;
-
-static PyDescriptorPool* descriptor_pool;
-
-PyDescriptorPool* GetDescriptorPool() {
- return descriptor_pool;
-}
/* Is 64bit */
void FormatTypeError(PyObject* arg, char* expected_types) {
@@ -305,14 +310,14 @@ bool CheckAndGetBool(PyObject* arg, bool* value) {
}
bool CheckAndSetString(
- PyObject* arg, google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* descriptor,
- const google::protobuf::Reflection* reflection,
+ PyObject* arg, Message* message,
+ const FieldDescriptor* descriptor,
+ const Reflection* reflection,
bool append,
int index) {
- GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING ||
- descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES);
- if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+ GOOGLE_DCHECK(descriptor->type() == FieldDescriptor::TYPE_STRING ||
+ descriptor->type() == FieldDescriptor::TYPE_BYTES);
+ if (descriptor->type() == FieldDescriptor::TYPE_STRING) {
if (!PyBytes_Check(arg) && !PyUnicode_Check(arg)) {
FormatTypeError(arg, "bytes, unicode");
return false;
@@ -339,7 +344,7 @@ bool CheckAndSetString(
}
PyObject* encoded_string = NULL;
- if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) {
+ if (descriptor->type() == FieldDescriptor::TYPE_STRING) {
if (PyBytes_Check(arg)) {
// The bytes were already validated as correctly encoded UTF-8 above.
encoded_string = arg; // Already encoded.
@@ -376,9 +381,8 @@ bool CheckAndSetString(
return true;
}
-PyObject* ToStringObject(
- const google::protobuf::FieldDescriptor* descriptor, string value) {
- if (descriptor->type() != google::protobuf::FieldDescriptor::TYPE_STRING) {
+PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) {
+ if (descriptor->type() != FieldDescriptor::TYPE_STRING) {
return PyBytes_FromStringAndSize(value.c_str(), value.length());
}
@@ -394,8 +398,8 @@ PyObject* ToStringObject(
return result;
}
-bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor,
- const google::protobuf::Message* message) {
+bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
+ const Message* message) {
if (message->GetDescriptor() == field_descriptor->containing_type()) {
return true;
}
@@ -405,16 +409,18 @@ bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_d
return false;
}
-google::protobuf::DynamicMessageFactory* global_message_factory;
-
namespace cmessage {
+DynamicMessageFactory* GetMessageFactory() {
+ return message_factory;
+}
+
static int MaybeReleaseOverlappingOneofField(
CMessage* cmessage,
- const google::protobuf::FieldDescriptor* field) {
+ const FieldDescriptor* field) {
#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
- google::protobuf::Message* message = cmessage->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ Message* message = cmessage->message;
+ const Reflection* reflection = message->GetReflection();
if (!field->containing_oneof() ||
!reflection->HasOneof(*message, field->containing_oneof()) ||
reflection->HasField(*message, field)) {
@@ -425,13 +431,13 @@ static int MaybeReleaseOverlappingOneofField(
const OneofDescriptor* oneof = field->containing_oneof();
const FieldDescriptor* existing_field =
reflection->GetOneofFieldDescriptor(*message, oneof);
- if (existing_field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (existing_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
// Non-message fields don't need to be released.
return 0;
}
const char* field_name = existing_field->name().c_str();
- PyObject* child_message = PyDict_GetItemString(
- cmessage->composite_fields, field_name);
+ PyObject* child_message = cmessage->composite_fields ?
+ PyDict_GetItemString(cmessage->composite_fields, field_name) : NULL;
if (child_message == NULL) {
// No python reference to this field so no need to release.
return 0;
@@ -450,21 +456,21 @@ static int MaybeReleaseOverlappingOneofField(
// ---------------------------------------------------------------------
// Making a message writable
-static google::protobuf::Message* GetMutableMessage(
+static Message* GetMutableMessage(
CMessage* parent,
- const google::protobuf::FieldDescriptor* parent_field) {
- google::protobuf::Message* parent_message = parent->message;
- const google::protobuf::Reflection* reflection = parent_message->GetReflection();
+ const FieldDescriptor* parent_field) {
+ Message* parent_message = parent->message;
+ const Reflection* reflection = parent_message->GetReflection();
if (MaybeReleaseOverlappingOneofField(parent, parent_field) < 0) {
return NULL;
}
return reflection->MutableMessage(
- parent_message, parent_field, global_message_factory);
+ parent_message, parent_field, message_factory);
}
struct FixupMessageReference : public ChildVisitor {
// message must outlive this object.
- explicit FixupMessageReference(google::protobuf::Message* message) :
+ explicit FixupMessageReference(Message* message) :
message_(message) {}
int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
@@ -478,7 +484,7 @@ struct FixupMessageReference : public ChildVisitor {
}
private:
- google::protobuf::Message* message_;
+ Message* message_;
};
int AssureWritable(CMessage* self) {
@@ -490,7 +496,7 @@ int AssureWritable(CMessage* self) {
// If parent is NULL but we are trying to modify a read-only message, this
// is a reference to a constant default instance that needs to be replaced
// with a mutable top-level message.
- const Message* prototype = global_message_factory->GetPrototype(
+ const Message* prototype = message_factory->GetPrototype(
self->message->GetDescriptor());
self->message = prototype->New();
self->owner.reset(self->message);
@@ -500,8 +506,8 @@ int AssureWritable(CMessage* self) {
return -1;
// Make self->message writable.
- google::protobuf::Message* parent_message = self->parent->message;
- google::protobuf::Message* mutable_message = GetMutableMessage(
+ Message* parent_message = self->parent->message;
+ Message* mutable_message = GetMutableMessage(
self->parent,
self->parent_field_descriptor);
if (mutable_message == NULL) {
@@ -528,38 +534,35 @@ int AssureWritable(CMessage* self) {
// Retrieve the C++ Descriptor of a message class.
// On error, returns NULL with an exception set.
-static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
+static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
ScopedPyObjectPtr descriptor(PyObject_GetAttr(
reinterpret_cast<PyObject*>(cls), kDESCRIPTOR));
if (descriptor == NULL) {
PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
return NULL;
}
- ScopedPyObjectPtr cdescriptor(PyObject_GetAttr(descriptor, k_cdescriptor));
- if (cdescriptor == NULL) {
- PyErr_SetString(PyExc_TypeError, "Unregistered message.");
+ if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
+ PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+ descriptor->ob_type->tp_name);
return NULL;
}
- if (!PyObject_TypeCheck(cdescriptor, &CMessageDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Not a CMessageDescriptor");
- return NULL;
- }
- return reinterpret_cast<CMessageDescriptor*>(cdescriptor.get())->descriptor;
+ return PyMessageDescriptor_AsDescriptor(descriptor);
}
// Retrieve a C++ FieldDescriptor for a message attribute.
// The C++ message must be valid.
// TODO(amauryfa): This function should stay internal, because exception
// handling is not consistent.
-static const google::protobuf::FieldDescriptor* GetFieldDescriptor(
+static const FieldDescriptor* GetFieldDescriptor(
CMessage* self, PyObject* name) {
- const google::protobuf::Descriptor *message_descriptor = self->message->GetDescriptor();
- const char* field_name = PyString_AsString(name);
- if (field_name == NULL) {
+ const Descriptor *message_descriptor = self->message->GetDescriptor();
+ char* field_name;
+ Py_ssize_t size;
+ if (PyString_AsStringAndSize(name, &field_name, &size) < 0) {
return NULL;
}
- const google::protobuf::FieldDescriptor *field_descriptor =
- message_descriptor->FindFieldByName(field_name);
+ const FieldDescriptor *field_descriptor =
+ message_descriptor->FindFieldByName(string(field_name, size));
if (field_descriptor == NULL) {
// Note: No exception is set!
return NULL;
@@ -568,19 +571,16 @@ static const google::protobuf::FieldDescriptor* GetFieldDescriptor(
}
// Retrieve a C++ FieldDescriptor for an extension handle.
-const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
- ScopedPyObjectPtr cdescriptor(
- PyObject_GetAttrString(extension, "_cdescriptor"));
- if (cdescriptor == NULL) {
- PyErr_SetString(PyExc_KeyError, "Unregistered extension.");
+const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) {
+ ScopedPyObjectPtr cdescriptor;
+ if (!PyObject_TypeCheck(extension, &PyFieldDescriptor_Type)) {
+ // Most callers consider extensions as a plain dictionary. We should
+ // allow input which is not a field descriptor, and simply pretend it does
+ // not exist.
+ PyErr_SetObject(PyExc_KeyError, extension);
return NULL;
}
- if (!PyObject_TypeCheck(cdescriptor, &CFieldDescriptor_Type)) {
- PyErr_SetString(PyExc_TypeError, "Not a CFieldDescriptor");
- Py_DECREF(cdescriptor);
- return NULL;
- }
- return reinterpret_cast<CFieldDescriptor*>(cdescriptor.get())->descriptor;
+ return PyFieldDescriptor_AsDescriptor(extension);
}
// If cmessage_list is not NULL, this function releases values into the
@@ -588,12 +588,12 @@ const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extens
// needs to do this to make sure CMessages stay alive if they're still
// referenced after deletion. Repeated scalar container doesn't need to worry.
int InternalDeleteRepeatedField(
- google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* field_descriptor,
+ Message* message,
+ const FieldDescriptor* field_descriptor,
PyObject* slice,
PyObject* cmessage_list) {
Py_ssize_t length, from, to, step, slice_length;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ const Reflection* reflection = message->GetReflection();
int min, max;
length = reflection->FieldSize(*message, field_descriptor);
@@ -690,18 +690,18 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
PyErr_SetString(PyExc_ValueError, "Field name must be a string");
return -1;
}
- const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
+ const FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
if (descriptor == NULL) {
PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.",
PyString_AsString(name));
return -1;
}
- if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
+ if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
ScopedPyObjectPtr container(GetAttr(self, name));
if (container == NULL) {
return -1;
}
- if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
if (repeated_composite_container::Extend(
reinterpret_cast<RepeatedCompositeContainer*>(container.get()),
value)
@@ -716,8 +716,7 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
return -1;
}
}
- } else if (descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
ScopedPyObjectPtr message(GetAttr(self, name));
if (message == NULL) {
return -1;
@@ -737,8 +736,7 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
// Allocates an incomplete Python Message: the caller must fill self->message,
// self->owner and eventually self->parent.
-CMessage* NewEmptyMessage(PyObject* type,
- const google::protobuf::Descriptor *descriptor) {
+CMessage* NewEmptyMessage(PyObject* type, const Descriptor *descriptor) {
CMessage* self = reinterpret_cast<CMessage*>(
PyType_GenericAlloc(reinterpret_cast<PyTypeObject*>(type), 0));
if (self == NULL) {
@@ -751,10 +749,7 @@ CMessage* NewEmptyMessage(PyObject* type,
self->read_only = false;
self->extensions = NULL;
- self->composite_fields = PyDict_New();
- if (self->composite_fields == NULL) {
- return NULL;
- }
+ self->composite_fields = NULL;
// If there are extension_ranges, the message is "extendable". Allocate a
// dictionary to store the extension fields.
@@ -776,12 +771,12 @@ CMessage* NewEmptyMessage(PyObject* type,
static PyObject* New(PyTypeObject* type,
PyObject* unused_args, PyObject* unused_kwargs) {
// Retrieve the message descriptor and the default instance (=prototype).
- const google::protobuf::Descriptor* message_descriptor = GetMessageDescriptor(type);
+ const Descriptor* message_descriptor = GetMessageDescriptor(type);
if (message_descriptor == NULL) {
return NULL;
}
- const google::protobuf::Message* default_message =
- global_message_factory->GetPrototype(message_descriptor);
+ const Message* default_message =
+ message_factory->GetPrototype(message_descriptor);
if (default_message == NULL) {
PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
return NULL;
@@ -836,7 +831,7 @@ struct ClearWeakReferences : public ChildVisitor {
}
int VisitCMessage(CMessage* cmessage,
- const google::protobuf::FieldDescriptor* field_descriptor) {
+ const FieldDescriptor* field_descriptor) {
cmessage->parent = NULL;
return 0;
}
@@ -886,12 +881,12 @@ PyObject* IsInitialized(CMessage* self, PyObject* args) {
}
PyObject* HasFieldByDescriptor(
- CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) {
- google::protobuf::Message* message = self->message;
+ CMessage* self, const FieldDescriptor* field_descriptor) {
+ Message* message = self->message;
if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
return NULL;
}
- if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
+ if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
PyErr_SetString(PyExc_KeyError,
"Field is repeated. A singular method is required.");
return NULL;
@@ -901,42 +896,78 @@ PyObject* HasFieldByDescriptor(
return PyBool_FromLong(has_field ? 1 : 0);
}
-const google::protobuf::FieldDescriptor* FindFieldWithOneofs(
- const google::protobuf::Message* message, const char* field_name, bool* in_oneof) {
- const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
- const google::protobuf::FieldDescriptor* field_descriptor =
+const FieldDescriptor* FindFieldWithOneofs(
+ const Message* message, const string& field_name, bool* in_oneof) {
+ *in_oneof = false;
+ const Descriptor* descriptor = message->GetDescriptor();
+ const FieldDescriptor* field_descriptor =
descriptor->FindFieldByName(field_name);
- if (field_descriptor == NULL) {
- const google::protobuf::OneofDescriptor* oneof_desc =
- message->GetDescriptor()->FindOneofByName(field_name);
- if (oneof_desc == NULL) {
- *in_oneof = false;
- return NULL;
- } else {
- *in_oneof = true;
- return message->GetReflection()->GetOneofFieldDescriptor(
- *message, oneof_desc);
+ if (field_descriptor != NULL) {
+ return field_descriptor;
+ }
+ const OneofDescriptor* oneof_desc =
+ descriptor->FindOneofByName(field_name);
+ if (oneof_desc != NULL) {
+ *in_oneof = true;
+ return message->GetReflection()->GetOneofFieldDescriptor(*message,
+ oneof_desc);
+ }
+ return NULL;
+}
+
+bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) {
+ if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+ PyErr_Format(PyExc_ValueError,
+ "Protocol message has no singular \"%s\" field.",
+ field_descriptor->name().c_str());
+ return false;
+ }
+
+ if (field_descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ // HasField() for a oneof *itself* isn't supported.
+ if (in_oneof) {
+ PyErr_Format(PyExc_ValueError,
+ "Can't test oneof field \"%s\" for presence in proto3, use "
+ "WhichOneof instead.",
+ field_descriptor->containing_oneof()->name().c_str());
+ return false;
+ }
+
+ // ...but HasField() for fields *in* a oneof is supported.
+ if (field_descriptor->containing_oneof() != NULL) {
+ return true;
+ }
+
+ if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ PyErr_Format(
+ PyExc_ValueError,
+ "Can't test non-submessage field \"%s\" for presence in proto3.",
+ field_descriptor->name().c_str());
+ return false;
}
}
- return field_descriptor;
+
+ return true;
}
PyObject* HasField(CMessage* self, PyObject* arg) {
-#if PY_MAJOR_VERSION < 3
char* field_name;
- if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
+ Py_ssize_t size;
+#if PY_MAJOR_VERSION < 3
+ if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) {
+ return NULL;
+ }
#else
- char* field_name = PyUnicode_AsUTF8(arg);
+ field_name = PyUnicode_AsUTF8AndSize(arg, &size);
if (!field_name) {
-#endif
return NULL;
}
+#endif
- google::protobuf::Message* message = self->message;
- const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+ Message* message = self->message;
bool is_in_oneof;
- const google::protobuf::FieldDescriptor* field_descriptor =
- FindFieldWithOneofs(message, field_name, &is_in_oneof);
+ const FieldDescriptor* field_descriptor =
+ FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
if (field_descriptor == NULL) {
if (!is_in_oneof) {
PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name);
@@ -946,28 +977,28 @@ PyObject* HasField(CMessage* self, PyObject* arg) {
}
}
- if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
- PyErr_Format(PyExc_ValueError,
- "Protocol message has no singular \"%s\" field.", field_name);
+ if (!CheckHasPresence(field_descriptor, is_in_oneof)) {
return NULL;
}
- bool has_field =
- message->GetReflection()->HasField(*message, field_descriptor);
- if (!has_field && field_descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_ENUM) {
- // We may have an invalid enum value stored in the UnknownFieldSet and need
- // to check presence in there as well.
- const google::protobuf::UnknownFieldSet& unknown_field_set =
+ if (message->GetReflection()->HasField(*message, field_descriptor)) {
+ Py_RETURN_TRUE;
+ }
+ if (!message->GetReflection()->SupportsUnknownEnumValues() &&
+ field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ // Special case: Python HasField() differs in semantics from C++
+ // slightly: we return HasField('enum_field') == true if there is
+ // an unknown enum value present. To implement this we have to
+ // look in the UnknownFieldSet.
+ 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()) {
Py_RETURN_TRUE;
}
}
- Py_RETURN_FALSE;
}
- return PyBool_FromLong(has_field ? 1 : 0);
+ Py_RETURN_FALSE;
}
PyObject* ClearExtension(CMessage* self, PyObject* arg) {
@@ -1034,7 +1065,7 @@ struct SetOwnerVisitor : public ChildVisitor {
}
int VisitCMessage(CMessage* cmessage,
- const google::protobuf::FieldDescriptor* field_descriptor) {
+ const FieldDescriptor* field_descriptor) {
return SetOwner(cmessage, new_owner_);
}
@@ -1053,18 +1084,17 @@ 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(google::protobuf::Message* message,
- const google::protobuf::Descriptor* descriptor,
- const google::protobuf::FieldDescriptor* field_descriptor) {
+Message* ReleaseMessage(Message* message,
+ const Descriptor* descriptor,
+ const FieldDescriptor* field_descriptor) {
Message* released_message = message->GetReflection()->ReleaseMessage(
- message, field_descriptor, global_message_factory);
+ 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
// have to reset it to a new mutable object since we are taking ownership.
if (released_message == NULL) {
- const Message* prototype = global_message_factory->GetPrototype(
- descriptor);
+ const Message* prototype = message_factory->GetPrototype(descriptor);
GOOGLE_DCHECK(prototype != NULL);
released_message = prototype->New();
}
@@ -1072,8 +1102,8 @@ Message* ReleaseMessage(google::protobuf::Message* message,
return released_message;
}
-int ReleaseSubMessage(google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* field_descriptor,
+int ReleaseSubMessage(Message* message,
+ const FieldDescriptor* field_descriptor,
CMessage* child_cmessage) {
// Release the Message
shared_ptr<Message> released_message(ReleaseMessage(
@@ -1089,7 +1119,7 @@ int ReleaseSubMessage(google::protobuf::Message* message,
struct ReleaseChild : public ChildVisitor {
// message must outlive this object.
- explicit ReleaseChild(google::protobuf::Message* parent_message) :
+ explicit ReleaseChild(Message* parent_message) :
parent_message_(parent_message) {}
int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) {
@@ -1103,38 +1133,27 @@ struct ReleaseChild : public ChildVisitor {
}
int VisitCMessage(CMessage* cmessage,
- const google::protobuf::FieldDescriptor* field_descriptor) {
+ const FieldDescriptor* field_descriptor) {
return ReleaseSubMessage(parent_message_, field_descriptor,
reinterpret_cast<CMessage*>(cmessage));
}
- google::protobuf::Message* parent_message_;
+ Message* parent_message_;
};
int InternalReleaseFieldByDescriptor(
- const google::protobuf::FieldDescriptor* field_descriptor,
+ const FieldDescriptor* field_descriptor,
PyObject* composite_field,
- google::protobuf::Message* parent_message) {
+ Message* parent_message) {
return VisitCompositeField(
field_descriptor,
composite_field,
ReleaseChild(parent_message));
}
-int InternalReleaseField(CMessage* self, PyObject* composite_field,
- PyObject* name) {
- const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name);
- if (descriptor != NULL) {
- return InternalReleaseFieldByDescriptor(
- descriptor, composite_field, self->message);
- }
-
- return 0;
-}
-
PyObject* ClearFieldByDescriptor(
CMessage* self,
- const google::protobuf::FieldDescriptor* descriptor) {
+ const FieldDescriptor* descriptor) {
if (!CheckFieldBelongsToMessage(descriptor, self->message)) {
return NULL;
}
@@ -1144,25 +1163,23 @@ PyObject* ClearFieldByDescriptor(
}
PyObject* ClearField(CMessage* self, PyObject* arg) {
- char* field_name;
if (!PyString_Check(arg)) {
PyErr_SetString(PyExc_TypeError, "field name must be a string");
return NULL;
}
#if PY_MAJOR_VERSION < 3
- if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) {
- return NULL;
- }
+ const char* field_name = PyString_AS_STRING(arg);
+ Py_ssize_t size = PyString_GET_SIZE(arg);
#else
- field_name = PyUnicode_AsUTF8(arg);
+ Py_ssize_t size;
+ const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size);
#endif
AssureWritable(self);
- google::protobuf::Message* message = self->message;
- const google::protobuf::Descriptor* descriptor = message->GetDescriptor();
+ Message* message = self->message;
ScopedPyObjectPtr arg_in_oneof;
bool is_in_oneof;
- const google::protobuf::FieldDescriptor* field_descriptor =
- FindFieldWithOneofs(message, field_name, &is_in_oneof);
+ const FieldDescriptor* field_descriptor =
+ FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof);
if (field_descriptor == NULL) {
if (!is_in_oneof) {
PyErr_Format(PyExc_ValueError,
@@ -1172,24 +1189,27 @@ PyObject* ClearField(CMessage* self, PyObject* arg) {
Py_RETURN_NONE;
}
} else if (is_in_oneof) {
- arg_in_oneof.reset(PyString_FromString(field_descriptor->name().c_str()));
+ const string& name = field_descriptor->name();
+ arg_in_oneof.reset(PyString_FromStringAndSize(name.c_str(), name.size()));
arg = arg_in_oneof.get();
}
- PyObject* composite_field = PyDict_GetItem(self->composite_fields,
- arg);
+ PyObject* composite_field = self->composite_fields ?
+ PyDict_GetItem(self->composite_fields, arg) : NULL;
// Only release the field if there's a possibility that there are
// references to it.
if (composite_field != NULL) {
- if (InternalReleaseField(self, composite_field, arg) < 0) {
+ if (InternalReleaseFieldByDescriptor(field_descriptor,
+ composite_field, message) < 0) {
return NULL;
}
PyDict_DelItem(self->composite_fields, arg);
}
message->GetReflection()->ClearField(message, field_descriptor);
- if (field_descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) {
- google::protobuf::UnknownFieldSet* unknown_field_set =
+ if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
+ !message->GetReflection()->SupportsUnknownEnumValues()) {
+ UnknownFieldSet* unknown_field_set =
message->GetReflection()->MutableUnknownFields(message);
unknown_field_set->DeleteByNumber(field_descriptor->number());
}
@@ -1212,7 +1232,9 @@ PyObject* Clear(CMessage* self) {
}
self->extensions = extension_dict;
}
- PyDict_Clear(self->composite_fields);
+ if (self->composite_fields) {
+ PyDict_Clear(self->composite_fields);
+ }
self->message->Clear();
Py_RETURN_NONE;
}
@@ -1242,7 +1264,27 @@ static PyObject* SerializeToString(CMessage* self, PyObject* args) {
if (joined == NULL) {
return NULL;
}
- PyErr_Format(EncodeError_class, "Message %s is missing required fields: %s",
+
+ // TODO(haberman): this is a (hopefully temporary) hack. The unit testing
+ // infrastructure reloads all pure-Python modules for every test, but not
+ // C++ modules (because that's generally impossible:
+ // http://bugs.python.org/issue1144263). But if we cache EncodeError, we'll
+ // return the EncodeError from a previous load of the module, which won't
+ // match a user's attempt to catch EncodeError. So we have to look it up
+ // again every time.
+ ScopedPyObjectPtr message_module(PyImport_ImportModule(
+ "google.protobuf.message"));
+ if (message_module.get() == NULL) {
+ return NULL;
+ }
+
+ ScopedPyObjectPtr encode_error(
+ PyObject_GetAttrString(message_module, "EncodeError"));
+ if (encode_error.get() == NULL) {
+ return NULL;
+ }
+ PyErr_Format(encode_error.get(),
+ "Message %s is missing required fields: %s",
GetMessageName(self).c_str(), PyString_AsString(joined));
return NULL;
}
@@ -1268,7 +1310,7 @@ static PyObject* SerializePartialToString(CMessage* self) {
// Formats proto fields for ascii dumps using python formatting functions where
// appropriate.
-class PythonFieldValuePrinter : public google::protobuf::TextFormat::FieldValuePrinter {
+class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter {
public:
PythonFieldValuePrinter() : float_holder_(PyFloat_FromDouble(0)) {}
@@ -1301,7 +1343,7 @@ class PythonFieldValuePrinter : public google::protobuf::TextFormat::FieldValueP
};
static PyObject* ToStr(CMessage* self) {
- google::protobuf::TextFormat::Printer printer;
+ TextFormat::Printer printer;
// Passes ownership
printer.SetDefaultFieldValuePrinter(new PythonFieldValuePrinter());
printer.SetHideUnknownFields(true);
@@ -1383,9 +1425,9 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
}
AssureWritable(self);
- google::protobuf::io::CodedInputStream input(
+ io::CodedInputStream input(
reinterpret_cast<const uint8*>(data), data_length);
- input.SetExtensionRegistry(descriptor_pool->pool, global_message_factory);
+ input.SetExtensionRegistry(GetDescriptorPool()->pool, message_factory);
bool success = self->message->MergePartialFromCodedStream(&input);
if (success) {
return PyInt_FromLong(input.CurrentPosition());
@@ -1412,10 +1454,22 @@ static PyObject* RegisterExtension(PyObject* cls,
if (message_descriptor == NULL) {
return NULL;
}
- if (PyObject_SetAttrString(extension_handle, "containing_type",
- message_descriptor) < 0) {
+
+ const FieldDescriptor* descriptor =
+ GetExtensionDescriptor(extension_handle);
+ if (descriptor == NULL) {
return NULL;
}
+ const Descriptor* cmessage_descriptor = GetMessageDescriptor(
+ reinterpret_cast<PyTypeObject*>(cls));
+
+ if (cmessage_descriptor != descriptor->containing_type()) {
+ if (PyObject_SetAttrString(extension_handle, "containing_type",
+ message_descriptor) < 0) {
+ return NULL;
+ }
+ }
+
ScopedPyObjectPtr extensions_by_name(
PyObject_GetAttr(cls, k_extensions_by_name));
if (extensions_by_name == NULL) {
@@ -1426,6 +1480,20 @@ static PyObject* RegisterExtension(PyObject* cls,
if (full_name == NULL) {
return NULL;
}
+
+ // If the extension was already registered, check that it is the same.
+ PyObject* existing_extension = PyDict_GetItem(extensions_by_name, full_name);
+ if (existing_extension != NULL) {
+ const FieldDescriptor* existing_extension_descriptor =
+ GetExtensionDescriptor(existing_extension);
+ if (existing_extension_descriptor != descriptor) {
+ PyErr_SetString(PyExc_ValueError, "Double registration of Extensions");
+ return NULL;
+ }
+ // Nothing else to do.
+ Py_RETURN_NONE;
+ }
+
if (PyDict_SetItem(extensions_by_name, full_name, extension_handle) < 0) {
return NULL;
}
@@ -1445,17 +1513,12 @@ static PyObject* RegisterExtension(PyObject* cls,
return NULL;
}
- const google::protobuf::FieldDescriptor* descriptor =
- GetExtensionDescriptor(extension_handle);
- if (descriptor == NULL) {
- return NULL;
- }
// Check if it's a message set
if (descriptor->is_extension() &&
descriptor->containing_type()->options().message_set_wire_format() &&
- descriptor->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE &&
+ descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
descriptor->message_type() == descriptor->extension_scope() &&
- descriptor->label() == google::protobuf::FieldDescriptor::LABEL_OPTIONAL) {
+ descriptor->label() == FieldDescriptor::LABEL_OPTIONAL) {
ScopedPyObjectPtr message_name(PyString_FromStringAndSize(
descriptor->message_type()->full_name().c_str(),
descriptor->message_type()->full_name().size()));
@@ -1474,53 +1537,36 @@ static PyObject* SetInParent(CMessage* self, PyObject* args) {
}
static PyObject* WhichOneof(CMessage* self, PyObject* arg) {
- char* oneof_name;
- if (!PyString_Check(arg)) {
- PyErr_SetString(PyExc_TypeError, "field name must be a string");
- return NULL;
- }
- oneof_name = PyString_AsString(arg);
- if (oneof_name == NULL) {
+ Py_ssize_t name_size;
+ char *name_data;
+ if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0)
return NULL;
- }
- const google::protobuf::OneofDescriptor* oneof_desc =
+ string oneof_name = string(name_data, name_size);
+ const OneofDescriptor* oneof_desc =
self->message->GetDescriptor()->FindOneofByName(oneof_name);
if (oneof_desc == NULL) {
PyErr_Format(PyExc_ValueError,
- "Protocol message has no oneof \"%s\" field.", oneof_name);
+ "Protocol message has no oneof \"%s\" field.",
+ oneof_name.c_str());
return NULL;
}
- const google::protobuf::FieldDescriptor* field_in_oneof =
+ const FieldDescriptor* field_in_oneof =
self->message->GetReflection()->GetOneofFieldDescriptor(
*self->message, oneof_desc);
if (field_in_oneof == NULL) {
Py_RETURN_NONE;
} else {
- return PyString_FromString(field_in_oneof->name().c_str());
+ const string& name = field_in_oneof->name();
+ return PyString_FromStringAndSize(name.c_str(), name.size());
}
}
static PyObject* ListFields(CMessage* self) {
- vector<const google::protobuf::FieldDescriptor*> fields;
+ vector<const FieldDescriptor*> fields;
self->message->GetReflection()->ListFields(*self->message, &fields);
- PyObject* descriptor = PyDict_GetItem(Py_TYPE(self)->tp_dict, kDESCRIPTOR);
- if (descriptor == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr fields_by_name(
- PyObject_GetAttr(descriptor, kfields_by_name));
- if (fields_by_name == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr extensions_by_name(PyObject_GetAttr(
- reinterpret_cast<PyObject*>(Py_TYPE(self)), k_extensions_by_name));
- if (extensions_by_name == NULL) {
- PyErr_SetString(PyExc_ValueError, "no extensionsbyname");
- return NULL;
- }
// Normally, the list will be exactly the size of the fields.
- PyObject* all_fields = PyList_New(fields.size());
+ ScopedPyObjectPtr all_fields(PyList_New(fields.size()));
if (all_fields == NULL) {
return NULL;
}
@@ -1532,35 +1578,34 @@ static PyObject* ListFields(CMessage* self) {
for (Py_ssize_t i = 0; i < fields.size(); ++i) {
ScopedPyObjectPtr t(PyTuple_New(2));
if (t == NULL) {
- Py_DECREF(all_fields);
return NULL;
}
if (fields[i]->is_extension()) {
- const string& field_name = fields[i]->full_name();
- PyObject* extension_field = PyDict_GetItemString(extensions_by_name,
- field_name.c_str());
+ ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(fields[i]));
if (extension_field == NULL) {
- // If we couldn't fetch extension_field, it means the module that
- // defines this extension has not been explicitly imported in Python
- // code, and the extension hasn't been registered. There's nothing much
- // we can do about this, so just skip it in the output to match the
- // behavior of the python implementation.
+ return NULL;
+ }
+ // With C++ descriptors, the field can always be retrieved, but for
+ // unknown extensions which have not been imported in Python code, there
+ // is no message class and we cannot retrieve the value.
+ // TODO(amauryfa): consider building the class on the fly!
+ if (fields[i]->message_type() != NULL &&
+ cdescriptor_pool::GetMessageClass(
+ GetDescriptorPool(), fields[i]->message_type()) == NULL) {
+ PyErr_Clear();
continue;
}
PyObject* extensions = reinterpret_cast<PyObject*>(self->extensions);
if (extensions == NULL) {
- Py_DECREF(all_fields);
return NULL;
}
// 'extension' reference later stolen by PyTuple_SET_ITEM.
PyObject* extension = PyObject_GetItem(extensions, extension_field);
if (extension == NULL) {
- Py_DECREF(all_fields);
return NULL;
}
- Py_INCREF(extension_field);
- PyTuple_SET_ITEM(t.get(), 0, extension_field);
+ PyTuple_SET_ITEM(t.get(), 0, extension_field.release());
// Steals reference to 'extension'
PyTuple_SET_ITEM(t.get(), 1, extension);
} else {
@@ -1569,35 +1614,30 @@ static PyObject* ListFields(CMessage* self) {
field_name.c_str(), field_name.length()));
if (py_field_name == NULL) {
PyErr_SetString(PyExc_ValueError, "bad string");
- Py_DECREF(all_fields);
return NULL;
}
- PyObject* field_descriptor =
- PyDict_GetItem(fields_by_name, py_field_name);
+ ScopedPyObjectPtr field_descriptor(PyFieldDescriptor_New(fields[i]));
if (field_descriptor == NULL) {
- Py_DECREF(all_fields);
return NULL;
}
PyObject* field_value = GetAttr(self, py_field_name);
if (field_value == NULL) {
PyErr_SetObject(PyExc_ValueError, py_field_name);
- Py_DECREF(all_fields);
return NULL;
}
- Py_INCREF(field_descriptor);
- PyTuple_SET_ITEM(t.get(), 0, field_descriptor);
+ PyTuple_SET_ITEM(t.get(), 0, field_descriptor.release());
PyTuple_SET_ITEM(t.get(), 1, field_value);
}
- PyList_SET_ITEM(all_fields, actual_size, t.release());
+ PyList_SET_ITEM(all_fields.get(), actual_size, t.release());
++actual_size;
}
- Py_SIZE(all_fields) = actual_size;
- return all_fields;
+ Py_SIZE(all_fields.get()) = actual_size;
+ return all_fields.release();
}
PyObject* FindInitializationErrors(CMessage* self) {
- google::protobuf::Message* message = self->message;
+ Message* message = self->message;
vector<string> errors;
message->FindInitializationErrors(&errors);
@@ -1645,9 +1685,9 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
PyObject* InternalGetScalar(
CMessage* self,
- const google::protobuf::FieldDescriptor* field_descriptor) {
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ const FieldDescriptor* field_descriptor) {
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
return NULL;
@@ -1655,50 +1695,51 @@ PyObject* InternalGetScalar(
PyObject* result = NULL;
switch (field_descriptor->cpp_type()) {
- case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+ case FieldDescriptor::CPPTYPE_INT32: {
int32 value = reflection->GetInt32(*message, field_descriptor);
result = PyInt_FromLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+ case FieldDescriptor::CPPTYPE_INT64: {
int64 value = reflection->GetInt64(*message, field_descriptor);
result = PyLong_FromLongLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+ case FieldDescriptor::CPPTYPE_UINT32: {
uint32 value = reflection->GetUInt32(*message, field_descriptor);
result = PyInt_FromSize_t(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+ case FieldDescriptor::CPPTYPE_UINT64: {
uint64 value = reflection->GetUInt64(*message, field_descriptor);
result = PyLong_FromUnsignedLongLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+ case FieldDescriptor::CPPTYPE_FLOAT: {
float value = reflection->GetFloat(*message, field_descriptor);
result = PyFloat_FromDouble(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
double value = reflection->GetDouble(*message, field_descriptor);
result = PyFloat_FromDouble(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+ case FieldDescriptor::CPPTYPE_BOOL: {
bool value = reflection->GetBool(*message, field_descriptor);
result = PyBool_FromLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+ case FieldDescriptor::CPPTYPE_STRING: {
string value = reflection->GetString(*message, field_descriptor);
result = ToStringObject(field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
- if (!message->GetReflection()->HasField(*message, field_descriptor)) {
+ case FieldDescriptor::CPPTYPE_ENUM: {
+ if (!message->GetReflection()->SupportsUnknownEnumValues() &&
+ !message->GetReflection()->HasField(*message, field_descriptor)) {
// Look for the value in the unknown fields.
- google::protobuf::UnknownFieldSet* unknown_field_set =
+ 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() ==
@@ -1710,7 +1751,7 @@ PyObject* InternalGetScalar(
}
if (result == NULL) {
- const google::protobuf::EnumValueDescriptor* enum_value =
+ const EnumValueDescriptor* enum_value =
message->GetReflection()->GetEnum(*message, field_descriptor);
result = PyInt_FromLong(enum_value->number());
}
@@ -1726,13 +1767,13 @@ PyObject* InternalGetScalar(
}
PyObject* InternalGetSubMessage(
- CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) {
- const google::protobuf::Reflection* reflection = self->message->GetReflection();
- const google::protobuf::Message& sub_message = reflection->GetMessage(
- *self->message, field_descriptor, global_message_factory);
+ CMessage* self, const FieldDescriptor* field_descriptor) {
+ const Reflection* reflection = self->message->GetReflection();
+ const Message& sub_message = reflection->GetMessage(
+ *self->message, field_descriptor, message_factory);
PyObject *message_class = cdescriptor_pool::GetMessageClass(
- descriptor_pool, field_descriptor->message_type());
+ GetDescriptorPool(), field_descriptor->message_type());
if (message_class == NULL) {
return NULL;
}
@@ -1747,17 +1788,17 @@ PyObject* InternalGetSubMessage(
cmsg->parent = self;
cmsg->parent_field_descriptor = field_descriptor;
cmsg->read_only = !reflection->HasField(*self->message, field_descriptor);
- cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
+ cmsg->message = const_cast<Message*>(&sub_message);
return reinterpret_cast<PyObject*>(cmsg);
}
int InternalSetScalar(
CMessage* self,
- const google::protobuf::FieldDescriptor* field_descriptor,
+ const FieldDescriptor* field_descriptor,
PyObject* arg) {
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
if (!CheckFieldBelongsToMessage(field_descriptor, message)) {
return -1;
@@ -1768,59 +1809,62 @@ int InternalSetScalar(
}
switch (field_descriptor->cpp_type()) {
- case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+ case FieldDescriptor::CPPTYPE_INT32: {
GOOGLE_CHECK_GET_INT32(arg, value, -1);
reflection->SetInt32(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+ case FieldDescriptor::CPPTYPE_INT64: {
GOOGLE_CHECK_GET_INT64(arg, value, -1);
reflection->SetInt64(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+ case FieldDescriptor::CPPTYPE_UINT32: {
GOOGLE_CHECK_GET_UINT32(arg, value, -1);
reflection->SetUInt32(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+ case FieldDescriptor::CPPTYPE_UINT64: {
GOOGLE_CHECK_GET_UINT64(arg, value, -1);
reflection->SetUInt64(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+ case FieldDescriptor::CPPTYPE_FLOAT: {
GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
reflection->SetFloat(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
reflection->SetDouble(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+ case FieldDescriptor::CPPTYPE_BOOL: {
GOOGLE_CHECK_GET_BOOL(arg, value, -1);
reflection->SetBool(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+ case FieldDescriptor::CPPTYPE_STRING: {
if (!CheckAndSetString(
arg, message, field_descriptor, reflection, false, -1)) {
return -1;
}
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+ case FieldDescriptor::CPPTYPE_ENUM: {
GOOGLE_CHECK_GET_INT32(arg, value, -1);
- const google::protobuf::EnumDescriptor* enum_descriptor =
- field_descriptor->enum_type();
- const google::protobuf::EnumValueDescriptor* enum_value =
- enum_descriptor->FindValueByNumber(value);
- if (enum_value != NULL) {
- reflection->SetEnum(message, field_descriptor, enum_value);
+ if (reflection->SupportsUnknownEnumValues()) {
+ reflection->SetEnumValue(message, field_descriptor, value);
} else {
- PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value);
- return -1;
+ const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+ const EnumValueDescriptor* enum_value =
+ enum_descriptor->FindValueByNumber(value);
+ if (enum_value != NULL) {
+ reflection->SetEnum(message, field_descriptor, enum_value);
+ } else {
+ PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value);
+ return -1;
+ }
}
break;
}
@@ -1851,14 +1895,35 @@ PyObject* FromString(PyTypeObject* cls, PyObject* serialized) {
return py_cmsg;
}
+// Add the number of a field descriptor to the containing message class.
+// Equivalent to:
+// _cls.<field>_FIELD_NUMBER = <number>
+static bool AddFieldNumberToClass(
+ PyObject* cls, const FieldDescriptor* field_descriptor) {
+ string constant_name = field_descriptor->name() + "_FIELD_NUMBER";
+ UpperString(&constant_name);
+ ScopedPyObjectPtr attr_name(PyString_FromStringAndSize(
+ constant_name.c_str(), constant_name.size()));
+ if (attr_name == NULL) {
+ return false;
+ }
+ ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number()));
+ if (number == NULL) {
+ return false;
+ }
+ if (PyObject_SetAttr(cls, attr_name, number) == -1) {
+ return false;
+ }
+ return true;
+}
+
// Finalize the creation of the Message class.
// Called from its metaclass: GeneratedProtocolMessageType.__init__().
-static PyObject* AddDescriptors(PyTypeObject* cls,
- PyObject* descriptor) {
- const google::protobuf::Descriptor* message_descriptor =
+static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) {
+ const Descriptor* message_descriptor =
cdescriptor_pool::RegisterMessageClass(
- descriptor_pool, reinterpret_cast<PyObject*>(cls), descriptor);
+ GetDescriptorPool(), cls, descriptor);
if (message_descriptor == NULL) {
return NULL;
}
@@ -1867,169 +1932,80 @@ static PyObject* AddDescriptors(PyTypeObject* cls,
// classes will register themselves in this class.
if (message_descriptor->extension_range_count() > 0) {
ScopedPyObjectPtr by_name(PyDict_New());
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- k_extensions_by_name, by_name) < 0) {
+ if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
return NULL;
}
ScopedPyObjectPtr by_number(PyDict_New());
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- k_extensions_by_number, by_number) < 0) {
+ if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
return NULL;
}
}
- ScopedPyObjectPtr fields(PyObject_GetAttrString(descriptor, "fields"));
- if (fields == NULL) {
- return NULL;
- }
-
- ScopedPyObjectPtr _NUMBER_string(PyString_FromString("_FIELD_NUMBER"));
- if (_NUMBER_string == NULL) {
- return NULL;
- }
-
- const Py_ssize_t fields_size = PyList_GET_SIZE(fields.get());
- for (int i = 0; i < fields_size; ++i) {
- PyObject* field = PyList_GET_ITEM(fields.get(), i);
- ScopedPyObjectPtr field_name(PyObject_GetAttr(field, kname));
- ScopedPyObjectPtr full_field_name(PyObject_GetAttr(field, kfull_name));
- if (field_name == NULL || full_field_name == NULL) {
- PyErr_SetString(PyExc_TypeError, "Name is null");
- return NULL;
- }
-
- ScopedPyObjectPtr field_descriptor(
- cdescriptor_pool::FindFieldByName(descriptor_pool, full_field_name));
- if (field_descriptor == NULL) {
- PyErr_SetString(PyExc_TypeError, "Couldn't find field");
- return NULL;
- }
- CFieldDescriptor* cfield_descriptor = reinterpret_cast<CFieldDescriptor*>(
- field_descriptor.get());
-
- // The FieldDescriptor's name field might either be of type bytes or
- // of type unicode, depending on whether the FieldDescriptor was
- // parsed from a serialized message or read from the
- // <message>_pb2.py module.
- ScopedPyObjectPtr field_name_upcased(
- PyObject_CallMethod(field_name, "upper", NULL));
- if (field_name_upcased == NULL) {
- return NULL;
- }
-
- ScopedPyObjectPtr field_number_name(PyObject_CallMethod(
- field_name_upcased, "__add__", "(O)", _NUMBER_string.get()));
- if (field_number_name == NULL) {
- return NULL;
- }
-
- ScopedPyObjectPtr number(PyInt_FromLong(
- cfield_descriptor->descriptor->number()));
- if (number == NULL) {
- return NULL;
- }
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- field_number_name, number) == -1) {
+ // For each field set: cls.<field>_FIELD_NUMBER = <number>
+ for (int i = 0; i < message_descriptor->field_count(); ++i) {
+ if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) {
return NULL;
}
}
- // Enum Values
- ScopedPyObjectPtr enum_types(PyObject_GetAttrString(descriptor,
- "enum_types"));
- if (enum_types == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr type_iter(PyObject_GetIter(enum_types));
- if (type_iter == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr enum_type;
- while ((enum_type.reset(PyIter_Next(type_iter))) != NULL) {
+ // For each enum set cls.<enum name> = EnumTypeWrapper(<enum descriptor>).
+ //
+ // The enum descriptor we get from
+ // <messagedescriptor>.enum_types_by_name[name]
+ // 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));
+ if (enum_type == NULL) {
+ return NULL;
+ }
+ // Add wrapped enum type to message class.
ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
EnumTypeWrapper_class, enum_type.get(), NULL));
if (wrapped == NULL) {
return NULL;
}
- ScopedPyObjectPtr enum_name(PyObject_GetAttr(enum_type, kname));
- if (enum_name == NULL) {
- return NULL;
- }
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- enum_name, wrapped) == -1) {
+ if (PyObject_SetAttrString(
+ cls, enum_descriptor->name().c_str(), wrapped) == -1) {
return NULL;
}
- ScopedPyObjectPtr enum_values(PyObject_GetAttrString(enum_type, "values"));
- if (enum_values == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr values_iter(PyObject_GetIter(enum_values));
- if (values_iter == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr enum_value;
- while ((enum_value.reset(PyIter_Next(values_iter))) != NULL) {
- ScopedPyObjectPtr value_name(PyObject_GetAttr(enum_value, kname));
- if (value_name == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr value_number(PyObject_GetAttrString(enum_value,
- "number"));
+ // For each enum value add cls.<name> = <number>
+ for (int j = 0; j < enum_descriptor->value_count(); ++j) {
+ const EnumValueDescriptor* enum_value_descriptor =
+ enum_descriptor->value(j);
+ ScopedPyObjectPtr value_number(PyInt_FromLong(
+ enum_value_descriptor->number()));
if (value_number == NULL) {
return NULL;
}
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- value_name, value_number) == -1) {
+ if (PyObject_SetAttrString(
+ cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
return NULL;
}
}
- if (PyErr_Occurred()) { // If PyIter_Next failed
- return NULL;
- }
- }
- if (PyErr_Occurred()) { // If PyIter_Next failed
- return NULL;
}
- ScopedPyObjectPtr extension_dict(
- PyObject_GetAttr(descriptor, kextensions_by_name));
- if (extension_dict == NULL || !PyDict_Check(extension_dict)) {
- PyErr_SetString(PyExc_TypeError, "extensions_by_name not a dict");
- return NULL;
- }
- Py_ssize_t pos = 0;
- PyObject* extension_name;
- PyObject* extension_field;
-
- while (PyDict_Next(extension_dict, &pos, &extension_name, &extension_field)) {
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- extension_name, extension_field) == -1) {
- return NULL;
- }
- const google::protobuf::FieldDescriptor* field_descriptor =
- GetExtensionDescriptor(extension_field);
- if (field_descriptor == NULL) {
+ // For each extension set cls.<extension name> = <extension descriptor>.
+ //
+ // Extension descriptors come from
+ // <message descriptor>.extensions_by_name[name]
+ // 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));
+ if (extension_field == NULL) {
return NULL;
}
- ScopedPyObjectPtr field_name_upcased(
- PyObject_CallMethod(extension_name, "upper", NULL));
- if (field_name_upcased == NULL) {
+ // Add the extension field to the message class.
+ if (PyObject_SetAttrString(
+ cls, field->name().c_str(), extension_field) == -1) {
return NULL;
}
- ScopedPyObjectPtr field_number_name(PyObject_CallMethod(
- field_name_upcased, "__add__", "(O)", _NUMBER_string.get()));
- if (field_number_name == NULL) {
- return NULL;
- }
- ScopedPyObjectPtr number(PyInt_FromLong(
- field_descriptor->number()));
- if (number == NULL) {
- return NULL;
- }
- if (PyObject_SetAttr(reinterpret_cast<PyObject*>(cls),
- field_number_name, number) == -1) {
+
+ // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
+ if (!AddFieldNumberToClass(cls, field)) {
return NULL;
}
}
@@ -2121,12 +2097,35 @@ 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(descriptor_pool, arg);
+ return cdescriptor_pool::FindFieldByName(GetDescriptorPool(), arg);
}
PyObject* _GetExtensionDescriptor(PyObject* unused, PyObject* arg) {
- return cdescriptor_pool::FindExtensionByName(descriptor_pool, 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)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Descriptors should not be created directly, "
+ "but only retrieved from their parent.");
+ return NULL;
+ }
+ Py_RETURN_NONE;
}
static PyMemberDef Members[] = {
@@ -2191,91 +2190,102 @@ static PyMethodDef Methods[] = {
// 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."},
{ NULL, NULL}
};
+static bool SetCompositeField(
+ CMessage* self, PyObject* name, PyObject* value) {
+ if (self->composite_fields == NULL) {
+ self->composite_fields = PyDict_New();
+ if (self->composite_fields == NULL) {
+ return false;
+ }
+ }
+ return PyDict_SetItem(self->composite_fields, name, value) == 0;
+}
+
PyObject* GetAttr(CMessage* self, PyObject* name) {
- PyObject* value = PyDict_GetItem(self->composite_fields, name);
+ PyObject* value = self->composite_fields ?
+ PyDict_GetItem(self->composite_fields, name) : NULL;
if (value != NULL) {
Py_INCREF(value);
return value;
}
- const google::protobuf::FieldDescriptor* field_descriptor = GetFieldDescriptor(
- self, name);
- if (field_descriptor != NULL) {
- if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
- if (field_descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
- PyObject *message_class = cdescriptor_pool::GetMessageClass(
- descriptor_pool, field_descriptor->message_type());
- if (message_class == NULL) {
- return NULL;
- }
- PyObject* py_container = repeated_composite_container::NewContainer(
- self, field_descriptor, message_class);
- if (py_container == NULL) {
- return NULL;
- }
- if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) {
- Py_DECREF(py_container);
- return NULL;
- }
- return py_container;
- } else {
- PyObject* py_container = repeated_scalar_container::NewContainer(
- self, field_descriptor);
- if (py_container == NULL) {
- return NULL;
- }
- if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) {
- Py_DECREF(py_container);
- return NULL;
- }
- return py_container;
+ const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name);
+ if (field_descriptor == NULL) {
+ return CMessage_Type.tp_base->tp_getattro(
+ reinterpret_cast<PyObject*>(self), name);
+ }
+
+ if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
+ PyObject* py_container = NULL;
+ if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ PyObject *message_class = cdescriptor_pool::GetMessageClass(
+ GetDescriptorPool(), field_descriptor->message_type());
+ if (message_class == NULL) {
+ return NULL;
}
+ py_container = repeated_composite_container::NewContainer(
+ self, field_descriptor, message_class);
} else {
- if (field_descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
- PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
- if (PyDict_SetItem(self->composite_fields, name, sub_message) < 0) {
- Py_DECREF(sub_message);
- return NULL;
- }
- return sub_message;
- } else {
- return InternalGetScalar(self, field_descriptor);
- }
+ py_container = repeated_scalar_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;
}
- return CMessage_Type.tp_base->tp_getattro(reinterpret_cast<PyObject*>(self),
- name);
+ if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
+ if (!SetCompositeField(self, name, sub_message)) {
+ Py_DECREF(sub_message);
+ return NULL;
+ }
+ return sub_message;
+ }
+
+ return InternalGetScalar(self, field_descriptor);
}
int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
- if (PyDict_Contains(self->composite_fields, name)) {
+ if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) {
PyErr_SetString(PyExc_TypeError, "Can't set composite field");
return -1;
}
- const google::protobuf::FieldDescriptor* field_descriptor =
- GetFieldDescriptor(self, name);
+ const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name);
if (field_descriptor != NULL) {
AssureWritable(self);
- if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) {
+ if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) {
PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated "
"field \"%s\" in protocol message object.",
field_descriptor->name().c_str());
return -1;
} else {
- if (field_descriptor->cpp_type() ==
- google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyErr_Format(PyExc_AttributeError, "Assignment not allowed to "
"field \"%s\" in protocol message object.",
field_descriptor->name().c_str());
@@ -2294,8 +2304,9 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
PyTypeObject CMessage_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "google.protobuf.internal."
- "cpp._message.CMessage", // tp_name
+ // Keep the fully qualified _message symbol in a line for opensource.
+ "google.protobuf.pyext._message."
+ "CMessage", // tp_name
sizeof(CMessage), // tp_basicsize
0, // tp_itemsize
(destructor)cmessage::Dealloc, // tp_dealloc
@@ -2339,7 +2350,7 @@ PyTypeObject CMessage_Type = {
const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg);
Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg);
-static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg) {
+static const Message* GetCProtoInsidePyProtoImpl(PyObject* msg) {
if (!PyObject_TypeCheck(msg, &CMessage_Type)) {
return NULL;
}
@@ -2347,12 +2358,12 @@ static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg
return cmsg->message;
}
-static google::protobuf::Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
+static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) {
if (!PyObject_TypeCheck(msg, &CMessage_Type)) {
return NULL;
}
CMessage* cmsg = reinterpret_cast<CMessage*>(msg);
- if (PyDict_Size(cmsg->composite_fields) != 0 ||
+ if ((cmsg->composite_fields && PyDict_Size(cmsg->composite_fields) != 0) ||
(cmsg->extensions != NULL &&
PyDict_Size(cmsg->extensions->values) != 0)) {
// There is currently no way of accurately syncing arbitrary changes to
@@ -2387,29 +2398,35 @@ void InitGlobals() {
kDESCRIPTOR = PyString_FromString("DESCRIPTOR");
k_cdescriptor = PyString_FromString("_cdescriptor");
kfull_name = PyString_FromString("full_name");
- kextensions_by_name = PyString_FromString("extensions_by_name");
k_extensions_by_name = PyString_FromString("_extensions_by_name");
k_extensions_by_number = PyString_FromString("_extensions_by_number");
- kname = PyString_FromString("name");
- kfields_by_name = PyString_FromString("fields_by_name");
- descriptor_pool = cdescriptor_pool::NewDescriptorPool();
-
- global_message_factory = new DynamicMessageFactory(descriptor_pool->pool);
- global_message_factory->SetDelegateToGeneratedFactory(true);
+ message_factory = new DynamicMessageFactory(GetDescriptorPool()->pool);
+ message_factory->SetDelegateToGeneratedFactory(true);
}
bool InitProto2MessageModule(PyObject *m) {
+ // Initialize types and globals in descriptor.cc
+ if (!InitDescriptor()) {
+ return false;
+ }
+
+ // Initialize types and globals in descriptor_pool.cc
+ if (!InitDescriptorPool()) {
+ return false;
+ }
+
+ // Initialize constants defined in this file.
InitGlobals();
- google::protobuf::python::CMessage_Type.tp_hash = PyObject_HashNotImplemented;
- if (PyType_Ready(&google::protobuf::python::CMessage_Type) < 0) {
+ CMessage_Type.tp_hash = PyObject_HashNotImplemented;
+ if (PyType_Ready(&CMessage_Type) < 0) {
return false;
}
// DESCRIPTOR is set on each protocol buffer message class elsewhere, but set
// it here as well to document that subclasses need to set it.
- PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, kDESCRIPTOR, Py_None);
+ PyDict_SetItem(CMessage_Type.tp_dict, kDESCRIPTOR, Py_None);
// Subclasses with message extensions will override _extensions_by_name and
// _extensions_by_number with fresh mutable dictionaries in AddDescriptors.
// All other classes can share this same immutable mapping.
@@ -2421,58 +2438,69 @@ bool InitProto2MessageModule(PyObject *m) {
if (immutable_dict == NULL) {
return false;
}
- if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
+ if (PyDict_SetItem(CMessage_Type.tp_dict,
k_extensions_by_name, immutable_dict) < 0) {
return false;
}
- if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict,
+ if (PyDict_SetItem(CMessage_Type.tp_dict,
k_extensions_by_number, immutable_dict) < 0) {
return false;
}
- PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(
- &google::protobuf::python::CMessage_Type));
+ PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type));
- google::protobuf::python::RepeatedScalarContainer_Type.tp_hash =
+ RepeatedScalarContainer_Type.tp_hash =
PyObject_HashNotImplemented;
- if (PyType_Ready(&google::protobuf::python::RepeatedScalarContainer_Type) < 0) {
+ if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
return false;
}
PyModule_AddObject(m, "RepeatedScalarContainer",
reinterpret_cast<PyObject*>(
- &google::protobuf::python::RepeatedScalarContainer_Type));
+ &RepeatedScalarContainer_Type));
- google::protobuf::python::RepeatedCompositeContainer_Type.tp_hash =
- PyObject_HashNotImplemented;
- if (PyType_Ready(&google::protobuf::python::RepeatedCompositeContainer_Type) < 0) {
+ RepeatedCompositeContainer_Type.tp_hash = PyObject_HashNotImplemented;
+ if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
return false;
}
PyModule_AddObject(
m, "RepeatedCompositeContainer",
reinterpret_cast<PyObject*>(
- &google::protobuf::python::RepeatedCompositeContainer_Type));
+ &RepeatedCompositeContainer_Type));
- google::protobuf::python::ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
- if (PyType_Ready(&google::protobuf::python::ExtensionDict_Type) < 0) {
+ ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
+ if (PyType_Ready(&ExtensionDict_Type) < 0) {
return false;
}
PyModule_AddObject(
m, "ExtensionDict",
- reinterpret_cast<PyObject*>(&google::protobuf::python::ExtensionDict_Type));
-
- if (!google::protobuf::python::InitDescriptor()) {
- return false;
- }
+ reinterpret_cast<PyObject*>(&ExtensionDict_Type));
+
+ // 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);
+
+ PyModule_AddObject(m, "Descriptor", reinterpret_cast<PyObject*>(
+ &PyMessageDescriptor_Type));
+ PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast<PyObject*>(
+ &PyFieldDescriptor_Type));
+ PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast<PyObject*>(
+ &PyEnumDescriptor_Type));
+ PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast<PyObject*>(
+ &PyEnumValueDescriptor_Type));
+ PyModule_AddObject(m, "FileDescriptor", reinterpret_cast<PyObject*>(
+ &PyFileDescriptor_Type));
+ PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast<PyObject*>(
+ &PyOneofDescriptor_Type));
PyObject* enum_type_wrapper = PyImport_ImportModule(
"google.protobuf.internal.enum_type_wrapper");
if (enum_type_wrapper == NULL) {
return false;
}
- google::protobuf::python::EnumTypeWrapper_class =
+ EnumTypeWrapper_class =
PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper");
Py_DECREF(enum_type_wrapper);
@@ -2481,25 +2509,20 @@ bool InitProto2MessageModule(PyObject *m) {
if (message_module == NULL) {
return false;
}
- google::protobuf::python::EncodeError_class = PyObject_GetAttrString(message_module,
- "EncodeError");
- google::protobuf::python::DecodeError_class = PyObject_GetAttrString(message_module,
- "DecodeError");
+ EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError");
+ DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError");
Py_DECREF(message_module);
PyObject* pickle_module = PyImport_ImportModule("pickle");
if (pickle_module == NULL) {
return false;
}
- google::protobuf::python::PickleError_class = PyObject_GetAttrString(pickle_module,
- "PickleError");
+ PickleError_class = PyObject_GetAttrString(pickle_module, "PickleError");
Py_DECREF(pickle_module);
// Override {Get,Mutable}CProtoInsidePyProto.
- google::protobuf::python::GetCProtoInsidePyProtoPtr =
- google::protobuf::python::GetCProtoInsidePyProtoImpl;
- google::protobuf::python::MutableCProtoInsidePyProtoPtr =
- google::protobuf::python::MutableCProtoInsidePyProtoImpl;
+ GetCProtoInsidePyProtoPtr = GetCProtoInsidePyProtoImpl;
+ MutableCProtoInsidePyProtoPtr = MutableCProtoInsidePyProtoImpl;
return true;
}
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 0fef92a0..2f2da795 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -42,7 +42,6 @@
#endif
#include <string>
-
namespace google {
namespace protobuf {
@@ -50,12 +49,12 @@ class Message;
class Reflection;
class FieldDescriptor;
class Descriptor;
+class DynamicMessageFactory;
using internal::shared_ptr;
namespace python {
-struct PyDescriptorPool;
struct ExtensionDict;
typedef struct CMessage {
@@ -84,7 +83,7 @@ typedef struct CMessage {
// Used together with the parent's message when making a default message
// instance mutable.
// The pointer is owned by the global DescriptorPool.
- const google::protobuf::FieldDescriptor* parent_field_descriptor;
+ const FieldDescriptor* parent_field_descriptor;
// Pointer to the C++ Message object for this CMessage. The
// CMessage does not own this pointer.
@@ -115,27 +114,26 @@ namespace cmessage {
// Internal function to create a new empty Message Python object, but with empty
// pointers to the C++ objects.
// The caller must fill self->message, self->owner and eventually self->parent.
-CMessage* NewEmptyMessage(PyObject* type,
- const google::protobuf::Descriptor* descriptor);
+CMessage* NewEmptyMessage(PyObject* type, const Descriptor* descriptor);
// Release a submessage from its proto tree, making it a new top-level messgae.
// A new message will be created if this is a read-only default instance.
//
// Corresponds to reflection api method ReleaseMessage.
-int ReleaseSubMessage(google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* field_descriptor,
+int ReleaseSubMessage(Message* message,
+ const FieldDescriptor* field_descriptor,
CMessage* child_cmessage);
// Retrieves the C++ descriptor of a Python Extension descriptor.
// On error, return NULL with an exception set.
-const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension);
+const FieldDescriptor* GetExtensionDescriptor(PyObject* extension);
// Initializes a new CMessage instance for a submessage. Only called once per
// submessage as the result is cached in composite_fields.
//
// Corresponds to reflection api method GetMessage.
PyObject* InternalGetSubMessage(
- CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor);
+ CMessage* self, const FieldDescriptor* field_descriptor);
// Deletes a range of C++ submessages in a repeated field (following a
// removal in a RepeatedCompositeContainer).
@@ -146,20 +144,20 @@ PyObject* InternalGetSubMessage(
// by slice will be removed from cmessage_list by this function.
//
// Corresponds to reflection api method RemoveLast.
-int InternalDeleteRepeatedField(google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* field_descriptor,
+int InternalDeleteRepeatedField(Message* message,
+ const FieldDescriptor* field_descriptor,
PyObject* slice, PyObject* cmessage_list);
// Sets the specified scalar value to the message.
int InternalSetScalar(CMessage* self,
- const google::protobuf::FieldDescriptor* field_descriptor,
+ const FieldDescriptor* field_descriptor,
PyObject* value);
// Retrieves the specified scalar value from the message.
//
// Returns a new python reference.
PyObject* InternalGetScalar(CMessage* self,
- const google::protobuf::FieldDescriptor* field_descriptor);
+ const FieldDescriptor* field_descriptor);
// Clears the message, removing all contained data. Extension dictionary and
// submessages are released first if there are remaining external references.
@@ -175,8 +173,7 @@ PyObject* Clear(CMessage* self);
//
// Corresponds to reflection api method ClearField.
PyObject* ClearFieldByDescriptor(
- CMessage* self,
- const google::protobuf::FieldDescriptor* descriptor);
+ CMessage* self, const FieldDescriptor* descriptor);
// Clears the data for the given field name. The message is released if there
// are any external references.
@@ -189,7 +186,7 @@ PyObject* ClearField(CMessage* self, PyObject* arg);
//
// Corresponds to reflection api method HasField
PyObject* HasFieldByDescriptor(
- CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor);
+ CMessage* self, const FieldDescriptor* field_descriptor);
// Checks if the message has the named field.
//
@@ -220,18 +217,16 @@ int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner);
int AssureWritable(CMessage* self);
-} // namespace cmessage
-
+DynamicMessageFactory* GetMessageFactory();
-// Retrieve the global descriptor pool owned by the _message module.
-PyDescriptorPool* GetDescriptorPool();
+} // namespace cmessage
/* Is 64bit */
#define IS_64BIT (SIZEOF_LONG == 8)
#define FIELD_IS_REPEATED(field_descriptor) \
- ((field_descriptor)->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED)
+ ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
#define GOOGLE_CHECK_GET_INT32(arg, value, err) \
int32 value; \
@@ -294,18 +289,17 @@ bool CheckAndGetDouble(PyObject* arg, double* value);
bool CheckAndGetFloat(PyObject* arg, float* value);
bool CheckAndGetBool(PyObject* arg, bool* value);
bool CheckAndSetString(
- PyObject* arg, google::protobuf::Message* message,
- const google::protobuf::FieldDescriptor* descriptor,
- const google::protobuf::Reflection* reflection,
+ PyObject* arg, Message* message,
+ const FieldDescriptor* descriptor,
+ const Reflection* reflection,
bool append,
int index);
-PyObject* ToStringObject(
- const google::protobuf::FieldDescriptor* descriptor, string value);
+PyObject* ToStringObject(const FieldDescriptor* descriptor, string value);
// Check if the passed field descriptor belongs to the given message.
// If not, return false and set a Python exception (a KeyError)
-bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor,
- const google::protobuf::Message* message);
+bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
+ const Message* message);
extern PyObject* PickleError_class;
diff --git a/python/google/protobuf/pyext/message_factory_cpp2_test.py b/python/google/protobuf/pyext/message_factory_cpp2_test.py
deleted file mode 100644
index 32ab4f85..00000000
--- a/python/google/protobuf/pyext/message_factory_cpp2_test.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc. All rights reserved.
-# https://developers.google.com/protocol-buffers/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-"""Tests for google.protobuf.message_factory."""
-
-import os
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2'
-
-# We must set the implementation version above before the google3 imports.
-# pylint: disable=g-import-not-at-top
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-# Run all tests from the original module by putting them in our namespace.
-# pylint: disable=wildcard-import
-from google.protobuf.internal.message_factory_test import *
-
-
-class ConfirmCppApi2Test(basetest.TestCase):
-
- def testImplementationSetting(self):
- self.assertEqual('cpp', api_implementation.Type())
- self.assertEqual(2, api_implementation.Version())
-
-
-if __name__ == '__main__':
- basetest.main()
diff --git a/python/google/protobuf/pyext/reflection_cpp2_generated_test.py b/python/google/protobuf/pyext/reflection_cpp2_generated_test.py
deleted file mode 100755
index 552efd48..00000000
--- a/python/google/protobuf/pyext/reflection_cpp2_generated_test.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#! /usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# 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.
-
-"""Unittest for reflection.py, which tests the generated C++ implementation."""
-
-__author__ = 'jasonh@google.com (Jason Hsueh)'
-
-import os
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
-os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2'
-
-from google.apputils import basetest
-from google.protobuf.internal import api_implementation
-from google.protobuf.internal import more_extensions_dynamic_pb2
-from google.protobuf.internal import more_extensions_pb2
-from google.protobuf.internal.reflection_test import *
-
-
-class ReflectionCppTest(basetest.TestCase):
- def testImplementationSetting(self):
- self.assertEqual('cpp', api_implementation.Type())
- self.assertEqual(2, api_implementation.Version())
-
- def testExtensionOfGeneratedTypeInDynamicFile(self):
- """Tests that a file built dynamically can extend a generated C++ type.
-
- The C++ implementation uses a DescriptorPool that has the generated
- DescriptorPool as an underlay. Typically, a type can only find
- extensions in its own pool. With the python C-extension, the generated C++
- extendee may be available, but not the extension. This tests that the
- C-extension implements the correct special handling to make such extensions
- available.
- """
- pb1 = more_extensions_pb2.ExtendedMessage()
- # Test that basic accessors work.
- self.assertFalse(
- pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
- self.assertFalse(
- pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
- pb1.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension] = 17
- pb1.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a = 24
- self.assertTrue(
- pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
- self.assertTrue(
- pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
-
- # Now serialize the data and parse to a new message.
- pb2 = more_extensions_pb2.ExtendedMessage()
- pb2.MergeFromString(pb1.SerializeToString())
-
- self.assertTrue(
- pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension))
- self.assertTrue(
- pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension))
- self.assertEqual(
- 17, pb2.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension])
- self.assertEqual(
- 24,
- pb2.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a)
-
-
-
-if __name__ == '__main__':
- basetest.main()
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 36fe86ae..0fe98e73 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -56,8 +56,6 @@ namespace google {
namespace protobuf {
namespace python {
-extern google::protobuf::DynamicMessageFactory* global_message_factory;
-
namespace repeated_composite_container {
// TODO(tibell): We might also want to check:
@@ -120,9 +118,9 @@ static int InternalQuickSort(RepeatedCompositeContainer* self,
GOOGLE_CHECK_ATTACHED(self);
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
- const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor;
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+ const FieldDescriptor* descriptor = self->parent_field_descriptor;
Py_ssize_t left;
Py_ssize_t right;
@@ -199,7 +197,7 @@ static int InternalQuickSort(RepeatedCompositeContainer* self,
// len()
static Py_ssize_t Length(RepeatedCompositeContainer* self) {
- google::protobuf::Message* message = self->message;
+ Message* message = self->message;
if (message != NULL) {
return message->GetReflection()->FieldSize(*message,
self->parent_field_descriptor);
@@ -221,8 +219,8 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) {
// be removed in such a way so there's no need to worry about that.
Py_ssize_t message_length = Length(self);
Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages);
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
for (Py_ssize_t i = child_length; i < message_length; ++i) {
const Message& sub_message = reflection->GetRepeatedMessage(
*(self->message), self->parent_field_descriptor, i);
@@ -233,7 +231,7 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) {
return -1;
}
cmsg->owner = self->owner;
- cmsg->message = const_cast<google::protobuf::Message*>(&sub_message);
+ cmsg->message = const_cast<Message*>(&sub_message);
cmsg->parent = self->parent;
if (PyList_Append(self->child_messages, py_cmsg) < 0) {
return -1;
@@ -255,8 +253,8 @@ static PyObject* AddToAttached(RepeatedCompositeContainer* self,
}
if (cmessage::AssureWritable(self->parent) == -1)
return NULL;
- google::protobuf::Message* message = self->message;
- google::protobuf::Message* sub_message =
+ Message* message = self->message;
+ Message* sub_message =
message->GetReflection()->AddMessage(message,
self->parent_field_descriptor);
CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init,
@@ -482,9 +480,9 @@ static PyObject* SortAttached(RepeatedCompositeContainer* self,
// Finally reverse the result if requested.
if (reverse) {
- google::protobuf::Message* message = self->message;
- const google::protobuf::Reflection* reflection = message->GetReflection();
- const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor;
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+ const FieldDescriptor* descriptor = self->parent_field_descriptor;
// Reverse the Message array.
for (int i = 0; i < length / 2; ++i)
@@ -554,6 +552,26 @@ static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) {
return item;
}
+static PyObject* Pop(RepeatedCompositeContainer* self,
+ PyObject* args) {
+ Py_ssize_t index = -1;
+ if (!PyArg_ParseTuple(args, "|n", &index)) {
+ return NULL;
+ }
+ PyObject* item = Item(self, index);
+ if (item == NULL) {
+ PyErr_Format(PyExc_IndexError,
+ "list index (%zd) out of range",
+ index);
+ return NULL;
+ }
+ ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index));
+ if (AssignSubscript(self, py_index, NULL) < 0) {
+ return NULL;
+ }
+ return item;
+}
+
// The caller takes ownership of the returned Message.
Message* ReleaseLast(const FieldDescriptor* field,
const Descriptor* type,
@@ -571,7 +589,8 @@ Message* ReleaseLast(const FieldDescriptor* field,
// the latter points to the default instance via a const_cast<>, so we
// have to reset it to a new mutable object since we are taking ownership.
if (released_message == NULL) {
- const Message* prototype = global_message_factory->GetPrototype(type);
+ const Message* prototype =
+ cmessage::GetMessageFactory()->GetPrototype(type);
GOOGLE_CHECK_NOTNULL(prototype);
return prototype->New();
} else {
@@ -646,7 +665,7 @@ int SetOwner(RepeatedCompositeContainer* self,
// The private constructor of RepeatedCompositeContainer objects.
PyObject *NewContainer(
CMessage* parent,
- const google::protobuf::FieldDescriptor* parent_field_descriptor,
+ const FieldDescriptor* parent_field_descriptor,
PyObject *concrete_class) {
if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
return NULL;
@@ -698,6 +717,8 @@ static PyMethodDef Methods[] = {
"Adds an object to the repeated container." },
{ "extend", (PyCFunction) Extend, METH_O,
"Adds objects to the repeated container." },
+ { "pop", (PyCFunction)Pop, METH_VARARGS,
+ "Removes an object from the repeated container and returns it." },
{ "remove", (PyCFunction) Remove, METH_O,
"Removes an object from the repeated container." },
{ "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS,
@@ -711,9 +732,10 @@ static PyMethodDef Methods[] = {
PyTypeObject RepeatedCompositeContainer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "google.protobuf.internal."
- "cpp._message.RepeatedCompositeContainer", // tp_name
- sizeof(RepeatedCompositeContainer), // tp_basicsize
+ // Keep the fully qualified _message symbol in a line for opensource.
+ "google.protobuf.pyext._message."
+ "RepeatedCompositeContainer", // tp_name
+ sizeof(RepeatedCompositeContainer), // tp_basicsize
0, // tp_itemsize
(destructor)repeated_composite_container::Dealloc, // tp_dealloc
0, // tp_print
diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h
index 0969af08..ce7cee0f 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.h
+++ b/python/google/protobuf/pyext/repeated_composite_container.h
@@ -43,7 +43,6 @@
#include <string>
#include <vector>
-
namespace google {
namespace protobuf {
@@ -82,7 +81,7 @@ typedef struct RepeatedCompositeContainer {
// A descriptor used to modify the underlying 'message'.
// The pointer is owned by the global DescriptorPool.
- const google::protobuf::FieldDescriptor* parent_field_descriptor;
+ const FieldDescriptor* parent_field_descriptor;
// Pointer to the C++ Message that contains this container. The
// RepeatedCompositeContainer does not own this pointer.
@@ -106,7 +105,7 @@ namespace repeated_composite_container {
// field descriptor.
PyObject *NewContainer(
CMessage* parent,
- const google::protobuf::FieldDescriptor* parent_field_descriptor,
+ const FieldDescriptor* parent_field_descriptor,
PyObject *concrete_class);
// Returns the number of items in this repeated composite container.
@@ -150,8 +149,7 @@ int AssignSubscript(RepeatedCompositeContainer* self,
// Releases the messages in the container to the given message.
//
// Returns 0 on success, -1 on failure.
-int ReleaseToMessage(RepeatedCompositeContainer* self,
- google::protobuf::Message* new_message);
+int ReleaseToMessage(RepeatedCompositeContainer* self, Message* new_message);
// Releases the messages in the container to a new message.
//
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 49d23fd6..110a4c85 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -60,8 +60,6 @@ namespace google {
namespace protobuf {
namespace python {
-extern google::protobuf::DynamicMessageFactory* global_message_factory;
-
namespace repeated_scalar_container {
static int InternalAssignRepeatedField(
@@ -78,7 +76,7 @@ static int InternalAssignRepeatedField(
}
static Py_ssize_t Len(RepeatedScalarContainer* self) {
- google::protobuf::Message* message = self->message;
+ Message* message = self->message;
return message->GetReflection()->FieldSize(*message,
self->parent_field_descriptor);
}
@@ -87,11 +85,10 @@ static int AssignItem(RepeatedScalarContainer* self,
Py_ssize_t index,
PyObject* arg) {
cmessage::AssureWritable(self->parent);
- google::protobuf::Message* message = self->message;
- const google::protobuf::FieldDescriptor* field_descriptor =
- self->parent_field_descriptor;
+ Message* message = self->message;
+ const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ const Reflection* reflection = message->GetReflection();
int field_size = reflection->FieldSize(*message, field_descriptor);
if (index < 0) {
index = field_size + index;
@@ -115,64 +112,68 @@ static int AssignItem(RepeatedScalarContainer* self,
}
switch (field_descriptor->cpp_type()) {
- case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+ case FieldDescriptor::CPPTYPE_INT32: {
GOOGLE_CHECK_GET_INT32(arg, value, -1);
reflection->SetRepeatedInt32(message, field_descriptor, index, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+ case FieldDescriptor::CPPTYPE_INT64: {
GOOGLE_CHECK_GET_INT64(arg, value, -1);
reflection->SetRepeatedInt64(message, field_descriptor, index, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+ case FieldDescriptor::CPPTYPE_UINT32: {
GOOGLE_CHECK_GET_UINT32(arg, value, -1);
reflection->SetRepeatedUInt32(message, field_descriptor, index, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+ case FieldDescriptor::CPPTYPE_UINT64: {
GOOGLE_CHECK_GET_UINT64(arg, value, -1);
reflection->SetRepeatedUInt64(message, field_descriptor, index, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+ case FieldDescriptor::CPPTYPE_FLOAT: {
GOOGLE_CHECK_GET_FLOAT(arg, value, -1);
reflection->SetRepeatedFloat(message, field_descriptor, index, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
GOOGLE_CHECK_GET_DOUBLE(arg, value, -1);
reflection->SetRepeatedDouble(message, field_descriptor, index, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+ case FieldDescriptor::CPPTYPE_BOOL: {
GOOGLE_CHECK_GET_BOOL(arg, value, -1);
reflection->SetRepeatedBool(message, field_descriptor, index, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+ case FieldDescriptor::CPPTYPE_STRING: {
if (!CheckAndSetString(
arg, message, field_descriptor, reflection, false, index)) {
return -1;
}
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+ case FieldDescriptor::CPPTYPE_ENUM: {
GOOGLE_CHECK_GET_INT32(arg, value, -1);
- const google::protobuf::EnumDescriptor* enum_descriptor =
- field_descriptor->enum_type();
- const google::protobuf::EnumValueDescriptor* enum_value =
- enum_descriptor->FindValueByNumber(value);
- if (enum_value != NULL) {
- reflection->SetRepeatedEnum(message, field_descriptor, index,
- enum_value);
+ if (reflection->SupportsUnknownEnumValues()) {
+ reflection->SetRepeatedEnumValue(message, field_descriptor, index,
+ value);
} else {
- ScopedPyObjectPtr s(PyObject_Str(arg));
- if (s != NULL) {
- PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
- PyString_AsString(s));
+ const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+ const EnumValueDescriptor* enum_value =
+ enum_descriptor->FindValueByNumber(value);
+ if (enum_value != NULL) {
+ reflection->SetRepeatedEnum(message, field_descriptor, index,
+ enum_value);
+ } else {
+ ScopedPyObjectPtr s(PyObject_Str(arg));
+ if (s != NULL) {
+ PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
+ PyString_AsString(s));
+ }
+ return -1;
}
- return -1;
}
break;
}
@@ -186,10 +187,9 @@ static int AssignItem(RepeatedScalarContainer* self,
}
static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
- google::protobuf::Message* message = self->message;
- const google::protobuf::FieldDescriptor* field_descriptor =
- self->parent_field_descriptor;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ Message* message = self->message;
+ const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
+ const Reflection* reflection = message->GetReflection();
int field_size = reflection->FieldSize(*message, field_descriptor);
if (index < 0) {
@@ -197,80 +197,80 @@ static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) {
}
if (index < 0 || index >= field_size) {
PyErr_Format(PyExc_IndexError,
- "list assignment index (%d) out of range",
- static_cast<int>(index));
+ "list index (%zd) out of range",
+ index);
return NULL;
}
PyObject* result = NULL;
switch (field_descriptor->cpp_type()) {
- case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+ case FieldDescriptor::CPPTYPE_INT32: {
int32 value = reflection->GetRepeatedInt32(
*message, field_descriptor, index);
result = PyInt_FromLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+ case FieldDescriptor::CPPTYPE_INT64: {
int64 value = reflection->GetRepeatedInt64(
*message, field_descriptor, index);
result = PyLong_FromLongLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+ case FieldDescriptor::CPPTYPE_UINT32: {
uint32 value = reflection->GetRepeatedUInt32(
*message, field_descriptor, index);
result = PyLong_FromLongLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+ case FieldDescriptor::CPPTYPE_UINT64: {
uint64 value = reflection->GetRepeatedUInt64(
*message, field_descriptor, index);
result = PyLong_FromUnsignedLongLong(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+ case FieldDescriptor::CPPTYPE_FLOAT: {
float value = reflection->GetRepeatedFloat(
*message, field_descriptor, index);
result = PyFloat_FromDouble(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
double value = reflection->GetRepeatedDouble(
*message, field_descriptor, index);
result = PyFloat_FromDouble(value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+ case FieldDescriptor::CPPTYPE_BOOL: {
bool value = reflection->GetRepeatedBool(
*message, field_descriptor, index);
result = PyBool_FromLong(value ? 1 : 0);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
- const google::protobuf::EnumValueDescriptor* enum_value =
+ case FieldDescriptor::CPPTYPE_ENUM: {
+ const EnumValueDescriptor* enum_value =
message->GetReflection()->GetRepeatedEnum(
*message, field_descriptor, index);
result = PyInt_FromLong(enum_value->number());
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+ case FieldDescriptor::CPPTYPE_STRING: {
string value = reflection->GetRepeatedString(
*message, field_descriptor, index);
result = ToStringObject(field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ case FieldDescriptor::CPPTYPE_MESSAGE: {
PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast<PyObject*>(
&CMessage_Type), NULL);
if (py_cmsg == NULL) {
return NULL;
}
CMessage* cmsg = reinterpret_cast<CMessage*>(py_cmsg);
- const google::protobuf::Message& msg = reflection->GetRepeatedMessage(
+ const Message& msg = reflection->GetRepeatedMessage(
*message, field_descriptor, index);
cmsg->owner = self->owner;
cmsg->parent = self->parent;
- cmsg->message = const_cast<google::protobuf::Message*>(&msg);
+ cmsg->message = const_cast<Message*>(&msg);
cmsg->read_only = false;
result = reinterpret_cast<PyObject*>(py_cmsg);
break;
@@ -351,69 +351,71 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) {
PyObject* Append(RepeatedScalarContainer* self, PyObject* item) {
cmessage::AssureWritable(self->parent);
- google::protobuf::Message* message = self->message;
- const google::protobuf::FieldDescriptor* field_descriptor =
- self->parent_field_descriptor;
+ Message* message = self->message;
+ const FieldDescriptor* field_descriptor = self->parent_field_descriptor;
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ const Reflection* reflection = message->GetReflection();
switch (field_descriptor->cpp_type()) {
- case google::protobuf::FieldDescriptor::CPPTYPE_INT32: {
+ case FieldDescriptor::CPPTYPE_INT32: {
GOOGLE_CHECK_GET_INT32(item, value, NULL);
reflection->AddInt32(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_INT64: {
+ case FieldDescriptor::CPPTYPE_INT64: {
GOOGLE_CHECK_GET_INT64(item, value, NULL);
reflection->AddInt64(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: {
+ case FieldDescriptor::CPPTYPE_UINT32: {
GOOGLE_CHECK_GET_UINT32(item, value, NULL);
reflection->AddUInt32(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: {
+ case FieldDescriptor::CPPTYPE_UINT64: {
GOOGLE_CHECK_GET_UINT64(item, value, NULL);
reflection->AddUInt64(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: {
+ case FieldDescriptor::CPPTYPE_FLOAT: {
GOOGLE_CHECK_GET_FLOAT(item, value, NULL);
reflection->AddFloat(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: {
+ case FieldDescriptor::CPPTYPE_DOUBLE: {
GOOGLE_CHECK_GET_DOUBLE(item, value, NULL);
reflection->AddDouble(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: {
+ case FieldDescriptor::CPPTYPE_BOOL: {
GOOGLE_CHECK_GET_BOOL(item, value, NULL);
reflection->AddBool(message, field_descriptor, value);
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_STRING: {
+ case FieldDescriptor::CPPTYPE_STRING: {
if (!CheckAndSetString(
item, message, field_descriptor, reflection, true, -1)) {
return NULL;
}
break;
}
- case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: {
+ case FieldDescriptor::CPPTYPE_ENUM: {
GOOGLE_CHECK_GET_INT32(item, value, NULL);
- const google::protobuf::EnumDescriptor* enum_descriptor =
- field_descriptor->enum_type();
- const google::protobuf::EnumValueDescriptor* enum_value =
- enum_descriptor->FindValueByNumber(value);
- if (enum_value != NULL) {
- reflection->AddEnum(message, field_descriptor, enum_value);
+ if (reflection->SupportsUnknownEnumValues()) {
+ reflection->AddEnumValue(message, field_descriptor, value);
} else {
- ScopedPyObjectPtr s(PyObject_Str(item));
- if (s != NULL) {
- PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
- PyString_AsString(s));
+ const EnumDescriptor* enum_descriptor = field_descriptor->enum_type();
+ const EnumValueDescriptor* enum_value =
+ enum_descriptor->FindValueByNumber(value);
+ if (enum_value != NULL) {
+ reflection->AddEnum(message, field_descriptor, enum_value);
+ } else {
+ ScopedPyObjectPtr s(PyObject_Str(item));
+ if (s != NULL) {
+ PyErr_Format(PyExc_ValueError, "Unknown enum value: %s",
+ PyString_AsString(s));
+ }
+ return NULL;
}
- return NULL;
}
break;
}
@@ -438,8 +440,8 @@ static int AssSubscript(RepeatedScalarContainer* self,
bool create_list = false;
cmessage::AssureWritable(self->parent);
- google::protobuf::Message* message = self->message;
- const google::protobuf::FieldDescriptor* field_descriptor =
+ Message* message = self->message;
+ const FieldDescriptor* field_descriptor =
self->parent_field_descriptor;
#if PY_MAJOR_VERSION < 3
@@ -450,7 +452,7 @@ static int AssSubscript(RepeatedScalarContainer* self,
if (PyLong_Check(slice)) {
from = to = PyLong_AsLong(slice);
} else if (PySlice_Check(slice)) {
- const google::protobuf::Reflection* reflection = message->GetReflection();
+ const Reflection* reflection = message->GetReflection();
length = reflection->FieldSize(*message, field_descriptor);
#if PY_MAJOR_VERSION >= 3
if (PySlice_GetIndicesEx(slice,
@@ -492,9 +494,15 @@ static int AssSubscript(RepeatedScalarContainer* self,
PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
cmessage::AssureWritable(self->parent);
- if (PyObject_Not(value)) {
+
+ // TODO(ptucker): Deprecate this behavior. b/18413862
+ if (value == Py_None) {
+ Py_RETURN_NONE;
+ }
+ if ((Py_TYPE(value)->tp_as_sequence == NULL) && PyObject_Not(value)) {
Py_RETURN_NONE;
}
+
ScopedPyObjectPtr iter(PyObject_GetIter(value));
if (iter == NULL) {
PyErr_SetString(PyExc_TypeError, "Value must be iterable");
@@ -627,9 +635,28 @@ static PyObject* Sort(RepeatedScalarContainer* self,
Py_RETURN_NONE;
}
+static PyObject* Pop(RepeatedScalarContainer* self,
+ PyObject* args) {
+ Py_ssize_t index = -1;
+ if (!PyArg_ParseTuple(args, "|n", &index)) {
+ return NULL;
+ }
+ PyObject* item = Item(self, index);
+ if (item == NULL) {
+ PyErr_Format(PyExc_IndexError,
+ "list index (%zd) out of range",
+ index);
+ return NULL;
+ }
+ if (AssignItem(self, index, NULL) < 0) {
+ return NULL;
+ }
+ return item;
+}
+
// The private constructor of RepeatedScalarContainer objects.
PyObject *NewContainer(
- CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) {
+ CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) {
return NULL;
}
@@ -663,7 +690,7 @@ static int InitializeAndCopyToParentContainer(
if (values == NULL) {
return -1;
}
- google::protobuf::Message* new_message = global_message_factory->GetPrototype(
+ Message* new_message = cmessage::GetMessageFactory()->GetPrototype(
from->message->GetDescriptor())->New();
to->parent = NULL;
to->parent_field_descriptor = from->parent_field_descriptor;
@@ -729,6 +756,8 @@ static PyMethodDef Methods[] = {
"Appends objects to the repeated container." },
{ "insert", (PyCFunction)Insert, METH_VARARGS,
"Appends objects to the repeated container." },
+ { "pop", (PyCFunction)Pop, METH_VARARGS,
+ "Removes an object from the repeated container and returns it." },
{ "remove", (PyCFunction)Remove, METH_O,
"Removes an object from the repeated container." },
{ "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS,
@@ -740,8 +769,9 @@ static PyMethodDef Methods[] = {
PyTypeObject RepeatedScalarContainer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "google.protobuf.internal."
- "cpp._message.RepeatedScalarContainer", // tp_name
+ // Keep the fully qualified _message symbol in a line for opensource.
+ "google.protobuf.pyext._message."
+ "RepeatedScalarContainer", // tp_name
sizeof(RepeatedScalarContainer), // tp_basicsize
0, // tp_itemsize
(destructor)repeated_scalar_container::Dealloc, // tp_dealloc
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h
index 513bfe48..5dfa21e0 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.h
+++ b/python/google/protobuf/pyext/repeated_scalar_container.h
@@ -77,7 +77,7 @@ typedef struct RepeatedScalarContainer {
// field. Used together with the parent's message when making a
// default message instance mutable.
// The pointer is owned by the global DescriptorPool.
- const google::protobuf::FieldDescriptor* parent_field_descriptor;
+ const FieldDescriptor* parent_field_descriptor;
} RepeatedScalarContainer;
extern PyTypeObject RepeatedScalarContainer_Type;
@@ -87,7 +87,7 @@ namespace repeated_scalar_container {
// Builds a RepeatedScalarContainer object, from a parent message and a
// field descriptor.
extern PyObject *NewContainer(
- CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor);
+ CMessage* parent, const FieldDescriptor* parent_field_descriptor);
// Appends the scalar 'item' to the end of the container 'self'.
//
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 1fc704a2..55e653a0 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -56,18 +56,12 @@ _FieldDescriptor = descriptor_mod.FieldDescriptor
if api_implementation.Type() == 'cpp':
- if api_implementation.Version() == 2:
- from google.protobuf.pyext import cpp_message
- _NewMessage = cpp_message.NewMessage
- _InitMessage = cpp_message.InitMessage
- else:
- from google.protobuf.internal import cpp_message
- _NewMessage = cpp_message.NewMessage
- _InitMessage = cpp_message.InitMessage
+ from google.protobuf.pyext import cpp_message as message_impl
else:
- from google.protobuf.internal import python_message
- _NewMessage = python_message.NewMessage
- _InitMessage = python_message.InitMessage
+ from google.protobuf.internal import python_message as message_impl
+
+_NewMessage = message_impl.NewMessage
+_InitMessage = message_impl.InitMessage
class GeneratedProtocolMessageType(type):
@@ -127,7 +121,6 @@ class GeneratedProtocolMessageType(type):
superclass = super(GeneratedProtocolMessageType, cls)
new_class = superclass.__new__(cls, name, bases, dictionary)
- setattr(descriptor, '_concrete_class', new_class)
return new_class
def __init__(cls, name, bases, dictionary):
@@ -151,6 +144,7 @@ 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 fb54c50c..a47ce3e3 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -319,6 +319,11 @@ def _MergeField(tokenizer, message, allow_multiple_scalars):
ParseError: In case of ASCII parsing problems.
"""
message_descriptor = message.DESCRIPTOR
+ if (hasattr(message_descriptor, 'syntax') and
+ message_descriptor.syntax == 'proto3'):
+ # Proto3 doesn't represent presence so we can't test if multiple
+ # scalars have occurred. We have to allow them.
+ allow_multiple_scalars = True
if tokenizer.TryConsume('['):
name = [tokenizer.ConsumeIdentifier()]
while tokenizer.TryConsume('.'):
diff --git a/python/setup.py b/python/setup.py
index cfe25cc0..c18818e2 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -44,6 +44,18 @@ elif os.path.exists("../vsprojects/Release/protoc.exe"):
else:
protoc = find_executable("protoc")
+def GetVersion():
+ """Gets the version from google/protobuf/__init__.py
+
+ Do not import google.protobuf.__init__ directly, because an installed protobuf
+ library may be loaded instead.
+
+ """
+ with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file:
+ exec(version_file.read())
+ return __version__
+
+
def generate_proto(source):
"""Invokes the Protocol Compiler to generate a _pb2.py from the given
.proto file. Does nothing if the output already exists and is newer than
@@ -77,6 +89,7 @@ def GenerateUnittestProtos():
generate_proto("../src/google/protobuf/unittest_import_public.proto")
generate_proto("../src/google/protobuf/unittest_mset.proto")
generate_proto("../src/google/protobuf/unittest_no_generic_services.proto")
+ generate_proto("../src/google/protobuf/unittest_proto3_arena.proto")
generate_proto("google/protobuf/internal/descriptor_pool_test1.proto")
generate_proto("google/protobuf/internal/descriptor_pool_test2.proto")
generate_proto("google/protobuf/internal/test_bad_identifiers.proto")
@@ -90,23 +103,6 @@ def GenerateUnittestProtos():
generate_proto("google/protobuf/internal/import_test_package/outer.proto")
generate_proto("google/protobuf/pyext/python.proto")
-def MakeTestSuite():
- # Test C++ implementation
- import unittest
- import google.protobuf.pyext.descriptor_cpp2_test as descriptor_cpp2_test
- import google.protobuf.pyext.message_factory_cpp2_test \
- as message_factory_cpp2_test
- import google.protobuf.pyext.reflection_cpp2_generated_test \
- as reflection_cpp2_generated_test
-
- loader = unittest.defaultTestLoader
- suite = unittest.TestSuite()
- for test in [ descriptor_cpp2_test,
- message_factory_cpp2_test,
- reflection_cpp2_generated_test]:
- suite.addTest(loader.loadTestsFromModule(test))
- return suite
-
class clean(_clean):
def run(self):
# Delete generated files in the code tree.
@@ -152,6 +148,8 @@ if __name__ == '__main__':
ext_module_list.append(Extension(
"google.protobuf.pyext._message",
[ "google/protobuf/pyext/descriptor.cc",
+ "google/protobuf/pyext/descriptor_containers.cc",
+ "google/protobuf/pyext/descriptor_pool.cc",
"google/protobuf/pyext/message.cc",
"google/protobuf/pyext/extension_dict.cc",
"google/protobuf/pyext/repeated_scalar_container.cc",
@@ -161,12 +159,12 @@ if __name__ == '__main__':
libraries = [ "protobuf" ],
library_dirs = [ '../src/.libs' ],
))
+ os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
setup(name = 'protobuf',
- version = '3.0.0-pre',
+ version = GetVersion(),
packages = [ 'google' ],
namespace_packages = [ 'google' ],
- test_suite = 'setup.MakeTestSuite',
google_test_dir = "google/protobuf/internal",
# Must list modules explicitly so that we don't install tests.
py_modules = [
diff --git a/ruby/.gitignore b/ruby/.gitignore
new file mode 100644
index 00000000..80c978f2
--- /dev/null
+++ b/ruby/.gitignore
@@ -0,0 +1,6 @@
+*.bundle
+tags
+.idea/
+lib/google/protobuf_java.jar
+protobuf-jruby.iml
+target/
diff --git a/ruby/Gemfile b/ruby/Gemfile
new file mode 100644
index 00000000..fa75df15
--- /dev/null
+++ b/ruby/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+
+gemspec
diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock
new file mode 100644
index 00000000..89deb47d
--- /dev/null
+++ b/ruby/Gemfile.lock
@@ -0,0 +1,25 @@
+PATH
+ remote: .
+ specs:
+ google-protobuf (3.0.0.alpha.2)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ power_assert (0.2.2)
+ rake (10.4.2)
+ rake-compiler (0.9.5)
+ rake
+ rubygems-tasks (0.2.4)
+ test-unit (3.0.9)
+ power_assert
+
+PLATFORMS
+ java
+ ruby
+
+DEPENDENCIES
+ google-protobuf!
+ rake-compiler
+ rubygems-tasks
+ test-unit
diff --git a/ruby/README.md b/ruby/README.md
index 88e9c0e1..d2fa76ab 100644
--- a/ruby/README.md
+++ b/ruby/README.md
@@ -7,8 +7,51 @@ we recommend using protoc's Ruby generation support with .proto files. The
build process in this directory only installs the extension; you need to
install protoc as well to have Ruby code generation functionality.
-Installation
-------------
+Installation from Gem
+---------------------
+
+When we release a version of Protocol Buffers, we will upload a Gem to
+[RubyGems](https://www.rubygems.org/). To use this pre-packaged gem, simply
+install it as you would any other gem:
+
+ $ gem install [--prerelease] google-protobuf
+
+The `--pre` flag is necessary if we have not yet made a non-alpha/beta release
+of the Ruby extension; it allows `gem` to consider these "pre-release"
+alpha/beta versions.
+
+Once the gem is installed, you may or may not need `protoc`. If you write your
+message type descriptions directly in the Ruby DSL, you do not need it.
+However, if you wish to generate the Ruby DSL from a `.proto` file, you will
+also want to install Protocol Buffers itself, as described in this repository's
+main `README` file. The version of `protoc` included in the latest release
+supports the `--ruby_out` option to generate Ruby code.
+
+A simple example of using the Ruby extension follows. More extensive
+documentation may be found in the RubyDoc comments (`call-seq` tags) in the
+source, and we plan to release separate, more detailed, documentation at a
+later date.
+
+ require 'google/protobuf'
+
+ # generated from my_proto_types.proto with protoc:
+ # $ protoc --ruby_out=. my_proto_types.proto
+ require 'my_proto_types'
+
+ mymessage = MyTestMessage.new(:field1 => 42, :field2 => ["a", "b", "c"])
+ mymessage.field1 = 43
+ mymessage.field2.push("d")
+ mymessage.field3 = SubMessage.new(:foo => 100)
+
+ encoded_data = MyTestMessage.encode(mymessage)
+ decoded = MyTestMessage.decode(encoded_data)
+ assert decoded == mymessage
+
+ puts "JSON:"
+ puts MyTestMessage.encode_json(mymessage)
+
+Installation from Source (Building Gem)
+---------------------------------------
To build this Ruby extension, you will need:
@@ -16,17 +59,53 @@ To build this Ruby extension, you will need:
* Bundler
* Ruby development headers
* a C compiler
-* the upb submodule
-First, install the required Ruby gems:
+To Build the JRuby extension, you will need:
+
+* Maven
+* The latest version of the protobuf java library
+* Install JRuby via rbenv or RVM
+
+First switch to the desired platform with rbenv or RVM.
- $ sudo gem install bundler rake rake-compiler rspec rubygems-tasks
+Then install the required Ruby gems:
+
+ $ gem install bundler
+ $ bundle
Then build the Gem:
$ rake gem
$ gem install pkg/protobuf-$VERSION.gem
+To run the specs:
+
+ $ rake test
+
This gem includes the upb parsing and serialization library as a single-file
amalgamation. It is up-to-date with upb git commit
`535bc2fe2f2b467f59347ffc9449e11e47791257`.
+
+Version Number Scheme
+---------------------
+
+We are using a version number scheme that is a hybrid of Protocol Buffers'
+overall version number and some Ruby-specific rules. Gem does not allow
+re-uploads of a gem with the same version number, so we add a sequence number
+("upload version") to the version. We also format alphabetical tags (alpha,
+pre, ...) slightly differently, and we avoid hyphens. In more detail:
+
+* First, we determine the prefix: a Protocol Buffers version "3.0.0-alpha-2"
+ becomes "3.0.0.alpha.2". When we release 3.0.0, this prefix will be simply
+ "3.0.0".
+* We then append the upload version: "3.0.0.alpha.2.0" or "3.0.0.0". If we need
+ to upload a new version of the gem to fix an issue, the version becomes
+ "3.0.0.alpha.2.1" or "3.0.0.1".
+* If we are working on a prerelease version, we append a prerelease tag:
+ "3.0.0.alpha.3.0.pre". The prerelease tag comes at the end so that when
+ version numbers are sorted, any prerelease builds are ordered between the
+ prior version and current version.
+
+These rules are designed to work with the sorting rules for
+[Gem::Version](http://ruby-doc.org/stdlib-2.0/libdoc/rubygems/rdoc/Gem/Version.html):
+release numbers should sort in actual release order.
diff --git a/ruby/Rakefile b/ruby/Rakefile
index ae7d8059..7c1d8495 100644
--- a/ruby/Rakefile
+++ b/ruby/Rakefile
@@ -1,20 +1,32 @@
-require "rake/extensiontask"
+require "rubygems"
+require "rubygems/package_task"
+require "rake/extensiontask" unless RUBY_PLATFORM == "java"
require "rake/testtask"
spec = Gem::Specification.load("google-protobuf.gemspec")
-Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
- ext.ext_dir = "ext/google/protobuf_c"
- ext.lib_dir = "lib/google"
-end
+if RUBY_PLATFORM == "java"
+ task :clean do
+ system("mvn clean")
+ end
-Rake::TestTask.new(:test => :build) do |t|
- t.test_files = FileList["tests/*.rb"]
+ task :compile do
+ system("mvn package")
+ end
+else
+ Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
+ ext.ext_dir = "ext/google/protobuf_c"
+ ext.lib_dir = "lib/google"
+ end
end
Gem::PackageTask.new(spec) do |pkg|
end
+Rake::TestTask.new(:test => :build) do |t|
+ t.test_files = FileList["tests/*.rb"]
+end
+
task :build => [:clean, :compile]
task :default => [:build]
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
index 0630f567..5730504d 100644
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ b/ruby/ext/google/protobuf_c/encode_decode.c
@@ -208,7 +208,11 @@ typedef struct {
size_t ofs;
upb_fieldtype_t key_field_type;
upb_fieldtype_t value_field_type;
- VALUE value_field_typeclass;
+
+ // We know that we can hold this reference because the handlerdata has the
+ // same lifetime as the upb_handlers struct, and the upb_handlers struct holds
+ // a reference to the upb_msgdef, which in turn has references to its subdefs.
+ const upb_def* value_field_subdef;
} map_handlerdata_t;
// Temporary frame for map parsing: at the beginning of a map entry message, a
@@ -248,8 +252,15 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) {
VALUE key = native_slot_get(
mapdata->key_field_type, Qnil,
&frame->key_storage);
+
+ VALUE value_field_typeclass = Qnil;
+ if (mapdata->value_field_type == UPB_TYPE_MESSAGE ||
+ mapdata->value_field_type == UPB_TYPE_ENUM) {
+ value_field_typeclass = get_def_obj(mapdata->value_field_subdef);
+ }
+
VALUE value = native_slot_get(
- mapdata->value_field_type, mapdata->value_field_typeclass,
+ mapdata->value_field_type, value_field_typeclass,
&frame->value_storage);
Map_index_set(frame->map, key, value);
@@ -280,17 +291,7 @@ static map_handlerdata_t* new_map_handlerdata(
MAP_VALUE_FIELD);
assert(value_field != NULL);
hd->value_field_type = upb_fielddef_type(value_field);
- hd->value_field_typeclass = field_type_class(value_field);
-
- // Ensure that value_field_typeclass is properly GC-rooted. We must do this
- // because we hold a reference to the Ruby class in the handlerdata, which is
- // owned by the handlers. The handlers are owned by *this* message's Ruby
- // object, but each Ruby object is rooted independently at the def -> Ruby
- // object map. So we have to ensure that the Ruby objects we depend on will
- // stick around as long as we're around.
- if (hd->value_field_typeclass != Qnil) {
- rb_ary_push(desc->typeclass_references, hd->value_field_typeclass);
- }
+ hd->value_field_subdef = upb_fielddef_subdef(value_field);
return hd;
}
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 4ee71d18..12e7a9d9 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -683,7 +683,7 @@ VALUE Map_inspect(VALUE _self) {
first = false;
}
str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
- str = rb_str_cat2(str, " => ");
+ str = rb_str_cat2(str, "=>");
str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
}
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index 7bfa533c..4c9449d2 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -1,24 +1,23 @@
-class << Gem::Specification
- def find_c_source(dir)
- `cd #{dir}; git ls-files "*.c" "*.h" extconf.rb Makefile`.split
- .map{|f| "#{dir}/#{f}"}
- end
-end
-
Gem::Specification.new do |s|
s.name = "google-protobuf"
- s.version = "3.0.0.alpha.2"
+ s.version = "3.0.0.alpha.3.0.pre"
s.licenses = ["BSD"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
s.authors = ["Protobuf Authors"]
s.email = "protobuf@googlegroups.com"
s.require_paths = ["lib"]
- s.extensions = ["ext/google/protobuf_c/extconf.rb"]
- s.files = ["lib/google/protobuf.rb"] +
- # extension C source
- find_c_source("ext/google/protobuf_c")
- s.test_files = ["tests/basic.rb",
- "tests/stress.rb",
- "tests/generated_code_test.rb"]
+ s.files = ["lib/google/protobuf.rb"]
+ unless RUBY_PLATFORM == "java"
+ s.files += `git ls-files "*.c" "*.h" extconf.rb Makefile`.split
+ s.extensions= ["ext/google/protobuf_c/extconf.rb"]
+ else
+ s.files += ["lib/google/protobuf_java.jar"]
+ end
+ s.test_files = ["tests/basic.rb",
+ "tests/stress.rb",
+ "tests/generated_code_test.rb"]
+ s.add_development_dependency "rake-compiler"
+ s.add_development_dependency "test-unit"
+ s.add_development_dependency "rubygems-tasks"
end
diff --git a/ruby/lib/google/protobuf.rb b/ruby/lib/google/protobuf.rb
index 74053332..75869dd8 100644
--- a/ruby/lib/google/protobuf.rb
+++ b/ruby/lib/google/protobuf.rb
@@ -28,4 +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.
-require 'google/protobuf_c'
+if RUBY_PLATFORM == "java"
+ require 'json'
+ require 'google/protobuf_java'
+else
+ require 'google/protobuf_c'
+end
diff --git a/ruby/pom.xml b/ruby/pom.xml
new file mode 100644
index 00000000..1630fe84
--- /dev/null
+++ b/ruby/pom.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google</groupId>
+ <artifactId>google</artifactId>
+ <version>1</version>
+ </parent>
+
+ <groupId>com.google.protobuf.jruby</groupId>
+ <artifactId>protobuf-jruby</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Protocol Buffer JRuby native extension</name>
+ <description>
+ Protocol Buffers are a way of encoding structured data in an efficient yet
+ extensible format.
+ </description>
+ <inceptionYear>2014</inceptionYear>
+ <url>https://developers.google.com/protocol-buffers/</url>
+ <licenses>
+ <license>
+ <name>New BSD license</name>
+ <url>http://www.opensource.org/licenses/bsd-license.php</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <url>https://github.com/google/protobuf</url>
+ <connection>
+ scm:git:https://github.com/google/protobuf.git
+ </connection>
+ </scm>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <ruby.sources>lib/google</ruby.sources>
+ <jar.finalName>protobuf_java</jar.finalName>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>${jar.finalName}</finalName>
+ <outputDirectory>${ruby.sources}</outputDirectory>
+ <appendAssemblyId>false</appendAssemblyId>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.4.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jruby</groupId>
+ <artifactId>jruby-complete</artifactId>
+ <version>1.7.13</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>3.0.0-pre</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java
new file mode 100644
index 00000000..5addae58
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyBuilder.java
@@ -0,0 +1,167 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.*;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "Builder")
+public class RubyBuilder extends RubyObject {
+ public static void createRubyBuilder(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cBuilder = protobuf.defineClassUnder("Builder", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyBuilder(runtime, klazz);
+ }
+ });
+ cBuilder.defineAnnotatedMethods(RubyBuilder.class);
+ }
+
+ public RubyBuilder(Ruby runtime, RubyClass metaClass) {
+ super(runtime, metaClass);
+ this.cDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Descriptor");
+ this.cEnumDescriptor = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumDescriptor");
+ this.cMessageBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::MessageBuilderContext");
+ this.cEnumBuilderContext = (RubyClass) runtime.getClassFromPath("Google::Protobuf::EnumBuilderContext");
+ }
+
+ /*
+ * call-seq:
+ * Builder.new => builder
+ *
+ * Creates a new Builder. A Builder can accumulate a set of new message and enum
+ * descriptors and atomically register them into a pool in a way that allows for
+ * (co)recursive type references.
+ */
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context) {
+ Ruby runtime = context.runtime;
+ this.pendingList = runtime.newArray();
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * Builder.add_message(name, &block)
+ *
+ * Creates a new, empty descriptor with the given name, and invokes the block in
+ * the context of a MessageBuilderContext on that descriptor. The block can then
+ * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
+ * methods to define the message fields.
+ *
+ * This is the recommended, idiomatic way to build message definitions.
+ */
+ @JRubyMethod(name = "add_message")
+ public IRubyObject addMessage(ThreadContext context, IRubyObject name, Block block) {
+ RubyDescriptor msgdef = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
+ IRubyObject ctx = cMessageBuilderContext.newInstance(context, msgdef, this, Block.NULL_BLOCK);
+ msgdef.setName(context, name);
+ if (block.isGiven()) {
+ if (block.arity() == Arity.ONE_ARGUMENT) {
+ block.yield(context, ctx);
+ } else {
+ Binding binding = block.getBinding();
+ binding.setSelf(ctx);
+ block.yieldSpecific(context);
+ }
+ }
+ this.pendingList.add(msgdef);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Builder.add_enum(name, &block)
+ *
+ * Creates a new, empty enum descriptor with the given name, and invokes the block in
+ * the context of an EnumBuilderContext on that descriptor. The block can then
+ * call EnumBuilderContext#add_value to define the enum values.
+ *
+ * This is the recommended, idiomatic way to build enum definitions.
+ */
+ @JRubyMethod(name = "add_enum")
+ public IRubyObject addEnum(ThreadContext context, IRubyObject name, Block block) {
+ RubyEnumDescriptor enumDef = (RubyEnumDescriptor) cEnumDescriptor.newInstance(context, Block.NULL_BLOCK);
+ IRubyObject ctx = cEnumBuilderContext.newInstance(context, enumDef, Block.NULL_BLOCK);
+ enumDef.setName(context, name);
+
+ if (block.isGiven()) {
+ if (block.arity() == Arity.ONE_ARGUMENT) {
+ block.yield(context, ctx);
+ } else {
+ Binding binding = block.getBinding();
+ binding.setSelf(ctx);
+ block.yieldSpecific(context);
+ }
+ }
+
+ this.pendingList.add(enumDef);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Builder.finalize_to_pool(pool)
+ *
+ * Adds all accumulated message and enum descriptors created in this builder
+ * context to the given pool. The operation occurs atomically, and all
+ * descriptors can refer to each other (including in cycles). This is the only
+ * way to build (co)recursive message definitions.
+ *
+ * This method is usually called automatically by DescriptorPool#build after it
+ * invokes the given user block in the context of the builder. The user should
+ * not normally need to call this manually because a Builder is not normally
+ * created manually.
+ */
+ @JRubyMethod(name = "finalize_to_pool")
+ public IRubyObject finalizeToPool(ThreadContext context, IRubyObject rbPool) {
+ RubyDescriptorPool pool = (RubyDescriptorPool) rbPool;
+ for (int i = 0; i < this.pendingList.size(); i++) {
+ IRubyObject defRb = this.pendingList.entry(i);
+ if (defRb instanceof RubyDescriptor) {
+ pool.addToSymtab(context, (RubyDescriptor) defRb);
+ } else {
+ pool.addToSymtab(context, (RubyEnumDescriptor) defRb);
+ }
+ }
+ this.pendingList = context.runtime.newArray();
+ return context.runtime.getNil();
+ }
+
+ protected RubyArray pendingList;
+ private RubyClass cDescriptor, cEnumDescriptor, cMessageBuilderContext, cEnumBuilderContext;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
new file mode 100644
index 00000000..51c50be8
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptor.java
@@ -0,0 +1,267 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+@JRubyClass(name = "Descriptor", include = "Enumerable")
+public class RubyDescriptor extends RubyObject {
+ public static void createRubyDescriptor(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cDescriptor = protobuf.defineClassUnder("Descriptor", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyDescriptor(runtime, klazz);
+ }
+ });
+ cDescriptor.includeModule(runtime.getEnumerable());
+ cDescriptor.defineAnnotatedMethods(RubyDescriptor.class);
+ }
+
+ public RubyDescriptor(Ruby runtime, RubyClass klazz) {
+ super(runtime, klazz);
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.new => descriptor
+ *
+ * Creates a new, empty, message type descriptor. At a minimum, its name must be
+ * set before it is added to a pool. It cannot be used to create messages until
+ * it is added to a pool, after which it becomes immutable (as part of a
+ * finalization process).
+ */
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context) {
+ this.builder = DescriptorProtos.DescriptorProto.newBuilder();
+ this.fieldDefMap = new HashMap<String, RubyFieldDescriptor>();
+ this.oneofDefs = new HashMap<IRubyObject, RubyOneofDescriptor>();
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.name => name
+ *
+ * Returns the name of this message type as a fully-qualfied string (e.g.,
+ * My.Package.MessageType).
+ */
+ @JRubyMethod(name = "name")
+ public IRubyObject getName(ThreadContext context) {
+ return this.name;
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.name = name
+ *
+ * Assigns a name to this message type. The descriptor must not have been added
+ * to a pool yet.
+ */
+ @JRubyMethod(name = "name=")
+ public IRubyObject setName(ThreadContext context, IRubyObject name) {
+ this.name = name;
+ this.builder.setName(Utils.escapeIdentifier(this.name.asJavaString()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.add_field(field) => nil
+ *
+ * Adds the given FieldDescriptor to this message type. The descriptor must not
+ * have been added to a pool yet. Raises an exception if a field with the same
+ * name or number already exists. Sub-type references (e.g. for fields of type
+ * message) are not resolved at this point.
+ */
+ @JRubyMethod(name = "add_field")
+ public IRubyObject addField(ThreadContext context, IRubyObject obj) {
+ RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) obj;
+ this.fieldDefMap.put(fieldDef.getName(context).asJavaString(), fieldDef);
+ this.builder.addField(fieldDef.build());
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.lookup(name) => FieldDescriptor
+ *
+ * Returns the field descriptor for the field with the given name, if present,
+ * or nil if none.
+ */
+ @JRubyMethod
+ public IRubyObject lookup(ThreadContext context, IRubyObject fieldName) {
+ return this.fieldDefMap.get(fieldName.asJavaString());
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.msgclass => message_klass
+ *
+ * Returns the Ruby class created for this message type. Valid only once the
+ * message type has been added to a pool.
+ */
+ @JRubyMethod
+ public IRubyObject msgclass(ThreadContext context) {
+ if (this.klazz == null) {
+ this.klazz = buildClassFromDescriptor(context);
+ }
+ return this.klazz;
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.each(&block)
+ *
+ * Iterates over fields in this message type, yielding to the block on each one.
+ */
+ @JRubyMethod
+ public IRubyObject each(ThreadContext context, Block block) {
+ for (Map.Entry<String, RubyFieldDescriptor> entry : fieldDefMap.entrySet()) {
+ block.yield(context, entry.getValue());
+ }
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.add_oneof(oneof) => nil
+ *
+ * Adds the given OneofDescriptor to this message type. This descriptor must not
+ * have been added to a pool yet. Raises an exception if a oneof with the same
+ * name already exists, or if any of the oneof's fields' names or numbers
+ * conflict with an existing field in this message type. All fields in the oneof
+ * are added to the message descriptor. Sub-type references (e.g. for fields of
+ * type message) are not resolved at this point.
+ */
+ @JRubyMethod(name = "add_oneof")
+ public IRubyObject addOneof(ThreadContext context, IRubyObject obj) {
+ RubyOneofDescriptor def = (RubyOneofDescriptor) obj;
+ builder.addOneofDecl(def.build(builder.getOneofDeclCount()));
+ for (RubyFieldDescriptor fieldDescriptor : def.getFields()) {
+ addField(context, fieldDescriptor);
+ }
+ oneofDefs.put(def.getName(context), def);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.each_oneof(&block) => nil
+ *
+ * Invokes the given block for each oneof in this message type, passing the
+ * corresponding OneofDescriptor.
+ */
+ @JRubyMethod(name = "each_oneof")
+ public IRubyObject eachOneof(ThreadContext context, Block block) {
+ for (RubyOneofDescriptor oneofDescriptor : oneofDefs.values()) {
+ block.yieldSpecific(context, oneofDescriptor);
+ }
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Descriptor.lookup_oneof(name) => OneofDescriptor
+ *
+ * Returns the oneof descriptor for the oneof with the given name, if present,
+ * or nil if none.
+ */
+ @JRubyMethod(name = "lookup_oneof")
+ public IRubyObject lookupOneof(ThreadContext context, IRubyObject name) {
+ if (name instanceof RubySymbol) {
+ name = ((RubySymbol) name).id2name();
+ }
+ return oneofDefs.containsKey(name) ? oneofDefs.get(name) : context.runtime.getNil();
+ }
+
+ public void setDescriptor(Descriptors.Descriptor descriptor) {
+ this.descriptor = descriptor;
+ }
+
+ public Descriptors.Descriptor getDescriptor() {
+ return this.descriptor;
+ }
+
+ public DescriptorProtos.DescriptorProto.Builder getBuilder() {
+ return builder;
+ }
+
+ public void setMapEntry(boolean isMapEntry) {
+ this.builder.setOptions(DescriptorProtos.MessageOptions.newBuilder().setMapEntry(isMapEntry));
+ }
+
+ private RubyModule buildClassFromDescriptor(ThreadContext context) {
+ Ruby runtime = context.runtime;
+
+ ObjectAllocator allocator = new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyMessage(runtime, klazz, descriptor);
+ }
+ };
+
+ // rb_define_class_id
+ RubyClass klass = RubyClass.newClass(runtime, runtime.getObject());
+ klass.setAllocator(allocator);
+ klass.makeMetaClass(runtime.getObject().getMetaClass());
+ klass.inherit(runtime.getObject());
+ klass.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
+ klass.defineAnnotatedMethods(RubyMessage.class);
+ return klass;
+ }
+
+ protected RubyFieldDescriptor lookup(String fieldName) {
+ return fieldDefMap.get(Utils.unescapeIdentifier(fieldName));
+ }
+
+ private IRubyObject name;
+ private RubyModule klazz;
+
+ private DescriptorProtos.DescriptorProto.Builder builder;
+ private Descriptors.Descriptor descriptor;
+ private Map<String, RubyFieldDescriptor> fieldDefMap;
+ private Map<IRubyObject, RubyOneofDescriptor> oneofDefs;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
new file mode 100644
index 00000000..0345cb99
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyDescriptorPool.java
@@ -0,0 +1,169 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.*;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JRubyClass(name = "DescriptorPool")
+public class RubyDescriptorPool extends RubyObject {
+ public static void createRubyDescriptorPool(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cDescriptorPool = protobuf.defineClassUnder("DescriptorPool", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyDescriptorPool(runtime, klazz);
+ }
+ });
+
+ cDescriptorPool.defineAnnotatedMethods(RubyDescriptorPool.class);
+ descriptorPool = (RubyDescriptorPool) cDescriptorPool.newInstance(runtime.getCurrentContext(), Block.NULL_BLOCK);
+ }
+
+ public RubyDescriptorPool(Ruby ruby, RubyClass klazz) {
+ super(ruby, klazz);
+ }
+
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context) {
+ this.symtab = new HashMap<IRubyObject, IRubyObject>();
+ this.cBuilder = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Builder");
+ this.builder = DescriptorProtos.FileDescriptorProto.newBuilder();
+ return this;
+ }
+
+ @JRubyMethod
+ public IRubyObject build(ThreadContext context, Block block) {
+ RubyBuilder ctx = (RubyBuilder) cBuilder.newInstance(context, Block.NULL_BLOCK);
+ if (block.arity() == Arity.ONE_ARGUMENT) {
+ block.yield(context, ctx);
+ } else {
+ Binding binding = block.getBinding();
+ binding.setSelf(ctx);
+ block.yieldSpecific(context);
+ }
+ ctx.finalizeToPool(context, this);
+ buildFileDescriptor(context);
+ return context.runtime.getNil();
+ }
+
+ @JRubyMethod
+ public IRubyObject lookup(ThreadContext context, IRubyObject name) {
+ IRubyObject descriptor = this.symtab.get(name);
+ if (descriptor == null) {
+ return context.runtime.getNil();
+ }
+ return descriptor;
+ }
+
+ /*
+ * call-seq:
+ * DescriptorPool.generated_pool => descriptor_pool
+ *
+ * Class method that returns the global DescriptorPool. This is a singleton into
+ * which generated-code message and enum types are registered. The user may also
+ * register types in this pool for convenience so that they do not have to hold
+ * a reference to a private pool instance.
+ */
+ @JRubyMethod(meta = true, name = "generated_pool")
+ public static IRubyObject generatedPool(ThreadContext context, IRubyObject recv) {
+ return descriptorPool;
+ }
+
+ protected void addToSymtab(ThreadContext context, RubyDescriptor def) {
+ symtab.put(def.getName(context), def);
+ this.builder.addMessageType(def.getBuilder());
+ }
+
+ protected void addToSymtab(ThreadContext context, RubyEnumDescriptor def) {
+ symtab.put(def.getName(context), def);
+ this.builder.addEnumType(def.getBuilder());
+ }
+
+ private void buildFileDescriptor(ThreadContext context) {
+ Ruby runtime = context.runtime;
+ try {
+ this.builder.setSyntax("proto3");
+ final Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(
+ this.builder.build(), new Descriptors.FileDescriptor[]{});
+
+ for (Descriptors.EnumDescriptor enumDescriptor : fileDescriptor.getEnumTypes()) {
+ String enumName = Utils.unescapeIdentifier(enumDescriptor.getName());
+ if (enumDescriptor.findValueByNumber(0) == null) {
+ throw runtime.newTypeError("Enum definition " + enumName
+ + " does not contain a value for '0'");
+ }
+ ((RubyEnumDescriptor) symtab.get(runtime.newString(enumName)))
+ .setDescriptor(enumDescriptor);
+ }
+ for (Descriptors.Descriptor descriptor : fileDescriptor.getMessageTypes()) {
+ RubyDescriptor rubyDescriptor = ((RubyDescriptor)
+ symtab.get(runtime.newString(Utils.unescapeIdentifier(descriptor.getName()))));
+ for (Descriptors.FieldDescriptor fieldDescriptor : descriptor.getFields()) {
+ if (fieldDescriptor.isRequired()) {
+ throw runtime.newTypeError("Required fields are unsupported in proto3");
+ }
+ RubyFieldDescriptor rubyFieldDescriptor = rubyDescriptor.lookup(fieldDescriptor.getName());
+ rubyFieldDescriptor.setFieldDef(fieldDescriptor);
+ if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
+ RubyDescriptor subType = (RubyDescriptor) lookup(context,
+ runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getMessageType().getName())));
+ rubyFieldDescriptor.setSubType(subType);
+ }
+ if (fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.ENUM) {
+ RubyEnumDescriptor subType = (RubyEnumDescriptor) lookup(context,
+ runtime.newString(Utils.unescapeIdentifier(fieldDescriptor.getEnumType().getName())));
+ rubyFieldDescriptor.setSubType(subType);
+ }
+ }
+ rubyDescriptor.setDescriptor(descriptor);
+ }
+ } catch (Descriptors.DescriptorValidationException e) {
+ throw runtime.newRuntimeError(e.getMessage());
+ }
+ }
+
+ private static RubyDescriptorPool descriptorPool;
+
+ private RubyClass cBuilder;
+ private Map<IRubyObject, IRubyObject> symtab;
+ private DescriptorProtos.FileDescriptorProto.Builder builder;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
new file mode 100644
index 00000000..929d8699
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnum.java
@@ -0,0 +1,86 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import org.jruby.RubyModule;
+import org.jruby.RubyNumeric;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+public class RubyEnum {
+ /*
+ * call-seq:
+ * Enum.lookup(number) => name
+ *
+ * This module method, provided on each generated enum module, looks up an enum
+ * value by number and returns its name as a Ruby symbol, or nil if not found.
+ */
+ @JRubyMethod(meta = true)
+ public static IRubyObject lookup(ThreadContext context, IRubyObject recv, IRubyObject number) {
+ RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
+ Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor();
+ Descriptors.EnumValueDescriptor value = descriptor.findValueByNumber(RubyNumeric.num2int(number));
+ if (value == null) return context.runtime.getNil();
+ return context.runtime.newSymbol(value.getName());
+ }
+
+ /*
+ * call-seq:
+ * Enum.resolve(name) => number
+ *
+ * This module method, provided on each generated enum module, looks up an enum
+ * value by name (as a Ruby symbol) and returns its name, or nil if not found.
+ */
+ @JRubyMethod(meta = true)
+ public static IRubyObject resolve(ThreadContext context, IRubyObject recv, IRubyObject name) {
+ RubyEnumDescriptor rubyEnumDescriptorescriptor = (RubyEnumDescriptor) getDescriptor(context, recv);
+ Descriptors.EnumDescriptor descriptor = rubyEnumDescriptorescriptor.getDescriptor();
+ Descriptors.EnumValueDescriptor value = descriptor.findValueByName(name.asJavaString());
+ if (value == null) return context.runtime.getNil();
+ return context.runtime.newFixnum(value.getNumber());
+ }
+
+ /*
+ * call-seq:
+ * Enum.descriptor
+ *
+ * This module method, provided on each generated enum module, returns the
+ * EnumDescriptor corresponding to this enum type.
+ */
+ @JRubyMethod(meta = true, name = "descriptor")
+ public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) {
+ return ((RubyModule) recv).getInstanceVariable(Utils.DESCRIPTOR_INSTANCE_VAR);
+ }
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java
new file mode 100644
index 00000000..e4cac345
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumBuilderContext.java
@@ -0,0 +1,82 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "EnumBuilderContext")
+public class RubyEnumBuilderContext extends RubyObject {
+ public static void createRubyEnumBuilderContext(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cMessageBuilderContext = protobuf.defineClassUnder("EnumBuilderContext", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyEnumBuilderContext(runtime, klazz);
+ }
+ });
+ cMessageBuilderContext.defineAnnotatedMethods(RubyEnumBuilderContext.class);
+ }
+
+ public RubyEnumBuilderContext(Ruby ruby, RubyClass klazz) {
+ super(ruby, klazz);
+ }
+
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context, IRubyObject enumDescriptor) {
+ this.enumDescriptor = (RubyEnumDescriptor) enumDescriptor;
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * EnumBuilder.add_value(name, number)
+ *
+ * Adds the given name => number mapping to the enum type. Name must be a Ruby
+ * symbol.
+ */
+ @JRubyMethod
+ public IRubyObject value(ThreadContext context, IRubyObject name, IRubyObject number) {
+ this.enumDescriptor.addValue(context, name, number);
+ return context.runtime.getNil();
+ }
+
+ private RubyEnumDescriptor enumDescriptor;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
new file mode 100644
index 00000000..4df832d0
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyEnumDescriptor.java
@@ -0,0 +1,185 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.RubyNumeric;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "EnumDescriptor", include = "Enumerable")
+public class RubyEnumDescriptor extends RubyObject {
+ public static void createRubyEnumDescriptor(Ruby runtime) {
+ RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cEnumDescriptor = mProtobuf.defineClassUnder("EnumDescriptor", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyEnumDescriptor(runtime, klazz);
+ }
+ });
+ cEnumDescriptor.includeModule(runtime.getEnumerable());
+ cEnumDescriptor.defineAnnotatedMethods(RubyEnumDescriptor.class);
+ }
+
+ public RubyEnumDescriptor(Ruby runtime, RubyClass klazz) {
+ super(runtime, klazz);
+ }
+
+ /*
+ * call-seq:
+ * EnumDescriptor.new => enum_descriptor
+ *
+ * Creates a new, empty, enum descriptor. Must be added to a pool before the
+ * enum type can be used. The enum type may only be modified prior to adding to
+ * a pool.
+ */
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context) {
+ this.builder = DescriptorProtos.EnumDescriptorProto.newBuilder();
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * EnumDescriptor.name => name
+ *
+ * Returns the name of this enum type.
+ */
+ @JRubyMethod(name = "name")
+ public IRubyObject getName(ThreadContext context) {
+ return this.name;
+ }
+
+ /*
+ * call-seq:
+ * EnumDescriptor.name = name
+ *
+ * Sets the name of this enum type. Cannot be called if the enum type has
+ * already been added to a pool.
+ */
+ @JRubyMethod(name = "name=")
+ public IRubyObject setName(ThreadContext context, IRubyObject name) {
+ this.name = name;
+ this.builder.setName(Utils.escapeIdentifier(name.asJavaString()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * EnumDescriptor.add_value(key, value)
+ *
+ * Adds a new key => value mapping to this enum type. Key must be given as a
+ * Ruby symbol. Cannot be called if the enum type has already been added to a
+ * pool. Will raise an exception if the key or value is already in use.
+ */
+ @JRubyMethod(name = "add_value")
+ public IRubyObject addValue(ThreadContext context, IRubyObject name, IRubyObject number) {
+ DescriptorProtos.EnumValueDescriptorProto.Builder valueBuilder = DescriptorProtos.EnumValueDescriptorProto.newBuilder();
+ valueBuilder.setName(name.asJavaString());
+ valueBuilder.setNumber(RubyNumeric.num2int(number));
+ this.builder.addValue(valueBuilder);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * EnumDescriptor.each(&block)
+ *
+ * Iterates over key => value mappings in this enum's definition, yielding to
+ * the block with (key, value) arguments for each one.
+ */
+ @JRubyMethod
+ public IRubyObject each(ThreadContext context, Block block) {
+ Ruby runtime = context.runtime;
+ for (Descriptors.EnumValueDescriptor enumValueDescriptor : descriptor.getValues()) {
+ block.yield(context, runtime.newArray(runtime.newSymbol(enumValueDescriptor.getName()),
+ runtime.newFixnum(enumValueDescriptor.getNumber())));
+ }
+ return runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * EnumDescriptor.enummodule => module
+ *
+ * Returns the Ruby module corresponding to this enum type. Cannot be called
+ * until the enum descriptor has been added to a pool.
+ */
+ @JRubyMethod
+ public IRubyObject enummodule(ThreadContext context) {
+ if (this.klazz == null) {
+ this.klazz = buildModuleFromDescriptor(context);
+ }
+ return this.klazz;
+ }
+
+ public void setDescriptor(Descriptors.EnumDescriptor descriptor) {
+ this.descriptor = descriptor;
+ }
+
+ public Descriptors.EnumDescriptor getDescriptor() {
+ return this.descriptor;
+ }
+
+ public DescriptorProtos.EnumDescriptorProto.Builder getBuilder() {
+ return this.builder;
+ }
+
+ private RubyModule buildModuleFromDescriptor(ThreadContext context) {
+ Ruby runtime = context.runtime;
+ Utils.checkNameAvailability(context, name.asJavaString());
+
+ RubyModule enumModule = RubyModule.newModule(runtime);
+ for (Descriptors.EnumValueDescriptor value : descriptor.getValues()) {
+ enumModule.defineConstant(value.getName(), runtime.newFixnum(value.getNumber()));
+ }
+
+ enumModule.instance_variable_set(runtime.newString(Utils.DESCRIPTOR_INSTANCE_VAR), this);
+ enumModule.defineAnnotatedMethods(RubyEnum.class);
+ return enumModule;
+ }
+
+ private IRubyObject name;
+ private RubyModule klazz;
+ private Descriptors.EnumDescriptor descriptor;
+ private DescriptorProtos.EnumDescriptorProto.Builder builder;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
new file mode 100644
index 00000000..38226c4e
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.java
@@ -0,0 +1,248 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "FieldDescriptor")
+public class RubyFieldDescriptor extends RubyObject {
+ public static void createRubyFileDescriptor(Ruby runtime) {
+ RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cFieldDescriptor = mProtobuf.defineClassUnder("FieldDescriptor", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyFieldDescriptor(runtime, klazz);
+ }
+ });
+ cFieldDescriptor.defineAnnotatedMethods(RubyFieldDescriptor.class);
+ }
+
+ public RubyFieldDescriptor(Ruby runtime, RubyClass klazz) {
+ super(runtime, klazz);
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.new => field
+ *
+ * Returns a new field descriptor. Its name, type, etc. must be set before it is
+ * added to a message type.
+ */
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context) {
+ builder = DescriptorProtos.FieldDescriptorProto.newBuilder();
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.label = label
+ *
+ * Sets the label on this field. Cannot be called if field is part of a message
+ * type already in a pool.
+ */
+ @JRubyMethod(name = "label=")
+ public IRubyObject setLabel(ThreadContext context, IRubyObject value) {
+ this.builder.setLabel(
+ DescriptorProtos.FieldDescriptorProto.Label.valueOf("LABEL_" + value.asJavaString().toUpperCase()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.name => name
+ *
+ * Returns the name of this field.
+ */
+ @JRubyMethod(name = "name")
+ public IRubyObject getName(ThreadContext context) {
+ return this.name;
+ }
+
+ @JRubyMethod(name = "subtype")
+ public IRubyObject getSubType(ThreadContext context) {
+ return subType;
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.name = name
+ *
+ * Sets the name of this field. Cannot be called once the containing message
+ * type, if any, is added to a pool.
+ */
+ @JRubyMethod(name = "name=")
+ public IRubyObject setName(ThreadContext context, IRubyObject value) {
+ String nameStr = value.asJavaString();
+ this.name = context.runtime.newString(nameStr);
+ this.builder.setName(Utils.escapeIdentifier(nameStr));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.type => type
+ *
+ * Returns this field's type, as a Ruby symbol, or nil if not yet set.
+ *
+ * Valid field types are:
+ * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
+ * :bytes, :message.
+ */
+ @JRubyMethod(name = "type")
+ public IRubyObject getType(ThreadContext context) {
+ return Utils.fieldTypeToRuby(context, this.builder.getType());
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.type = type
+ *
+ * Sets this field's type. Cannot be called if field is part of a message type
+ * already in a pool.
+ */
+ @JRubyMethod(name = "type=")
+ public IRubyObject setType(ThreadContext context, IRubyObject value) {
+ this.builder.setType(DescriptorProtos.FieldDescriptorProto.Type.valueOf("TYPE_" + value.asJavaString().toUpperCase()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.number = number
+ *
+ * Sets the tag number for this field. Cannot be called if field is part of a
+ * message type already in a pool.
+ */
+ @JRubyMethod(name = "number=")
+ public IRubyObject setNumber(ThreadContext context, IRubyObject value) {
+ this.builder.setNumber(RubyNumeric.num2int(value));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.submsg_name = submsg_name
+ *
+ * Sets the name of the message or enum type corresponding to this field, if it
+ * is a message or enum field (respectively). This type name will be resolved
+ * within the context of the pool to which the containing message type is added.
+ * Cannot be called on field that are not of message or enum type, or on fields
+ * that are part of a message type already added to a pool.
+ */
+ @JRubyMethod(name = "submsg_name=")
+ public IRubyObject setSubmsgName(ThreadContext context, IRubyObject name) {
+ this.builder.setTypeName("." + Utils.escapeIdentifier(name.asJavaString()));
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.get(message) => value
+ *
+ * Returns the value set for this field on the given message. Raises an
+ * exception if message is of the wrong type.
+ */
+ @JRubyMethod(name = "get")
+ public IRubyObject getValue(ThreadContext context, IRubyObject msgRb) {
+ RubyMessage message = (RubyMessage) msgRb;
+ if (message.getDescriptor() != fieldDef.getContainingType()) {
+ throw context.runtime.newTypeError("set method called on wrong message type");
+ }
+ return message.getField(context, fieldDef);
+ }
+
+ /*
+ * call-seq:
+ * FieldDescriptor.set(message, value)
+ *
+ * Sets the value corresponding to this field to the given value on the given
+ * message. Raises an exception if message is of the wrong type. Performs the
+ * ordinary type-checks for field setting.
+ */
+ @JRubyMethod(name = "set")
+ public IRubyObject setValue(ThreadContext context, IRubyObject msgRb, IRubyObject value) {
+ RubyMessage message = (RubyMessage) msgRb;
+ if (message.getDescriptor() != fieldDef.getContainingType()) {
+ throw context.runtime.newTypeError("set method called on wrong message type");
+ }
+ message.setField(context, fieldDef, value);
+ return context.runtime.getNil();
+ }
+
+ protected void setSubType(IRubyObject rubyDescriptor) {
+ this.subType = rubyDescriptor;
+ }
+
+ protected void setFieldDef(Descriptors.FieldDescriptor fieldDescriptor) {
+ this.fieldDef = fieldDescriptor;
+ }
+
+ protected void setOneofName(IRubyObject name) {
+ oneofName = name;
+ }
+
+ protected void setOneofIndex(int index) {
+ hasOneofIndex = true;
+ oneofIndex = index;
+ }
+
+ protected IRubyObject getOneofName() {
+ return oneofName;
+ }
+
+ protected Descriptors.FieldDescriptor getFieldDef() {
+ return fieldDef;
+ }
+
+ protected DescriptorProtos.FieldDescriptorProto build() {
+ if (hasOneofIndex)
+ builder.setOneofIndex(oneofIndex);
+ return this.builder.build();
+ }
+
+ private DescriptorProtos.FieldDescriptorProto.Builder builder;
+ private IRubyObject name;
+ private IRubyObject subType;
+ private IRubyObject oneofName;
+ private Descriptors.FieldDescriptor fieldDef;
+ private int oneofIndex;
+ private boolean hasOneofIndex = false;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
new file mode 100644
index 00000000..b25dc6e1
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMap.java
@@ -0,0 +1,434 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.MapEntry;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.internal.runtime.methods.DynamicMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.util.ByteList;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@JRubyClass(name = "Map", include = "Enumerable")
+public class RubyMap extends RubyObject {
+ public static void createRubyMap(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cMap = protobuf.defineClassUnder("Map", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
+ return new RubyMap(ruby, rubyClass);
+ }
+ });
+ cMap.includeModule(runtime.getEnumerable());
+ cMap.defineAnnotatedMethods(RubyMap.class);
+ }
+
+ public RubyMap(Ruby ruby, RubyClass rubyClass) {
+ super(ruby, rubyClass);
+ }
+
+ /*
+ * call-seq:
+ * Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
+ * => new map
+ *
+ * Allocates a new Map container. This constructor may be called with 2, 3, or 4
+ * arguments. The first two arguments are always present and are symbols (taking
+ * on the same values as field-type symbols in message descriptors) that
+ * indicate the type of the map key and value fields.
+ *
+ * The supported key types are: :int32, :int64, :uint32, :uint64, :bool,
+ * :string, :bytes.
+ *
+ * The supported value types are: :int32, :int64, :uint32, :uint64, :bool,
+ * :string, :bytes, :enum, :message.
+ *
+ * The third argument, value_typeclass, must be present if value_type is :enum
+ * or :message. As in RepeatedField#new, this argument must be a message class
+ * (for :message) or enum module (for :enum).
+ *
+ * The last argument, if present, provides initial content for map. Note that
+ * this may be an ordinary Ruby hashmap or another Map instance with identical
+ * key and value types. Also note that this argument may be present whether or
+ * not value_typeclass is present (and it is unambiguously separate from
+ * value_typeclass because value_typeclass's presence is strictly determined by
+ * value_type). The contents of this initial hashmap or Map instance are
+ * shallow-copied into the new Map: the original map is unmodified, but
+ * references to underlying objects will be shared if the value type is a
+ * message type.
+ */
+
+ @JRubyMethod(required = 2, optional = 2)
+ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
+ this.table = new HashMap<IRubyObject, IRubyObject>();
+ this.keyType = Utils.rubyToFieldType(args[0]);
+ this.valueType = Utils.rubyToFieldType(args[1]);
+
+ switch(keyType) {
+ case INT32:
+ case INT64:
+ case UINT32:
+ case UINT64:
+ case BOOL:
+ case STRING:
+ case BYTES:
+ // These are OK.
+ break;
+ default:
+ throw context.runtime.newArgumentError("Invalid key type for map.");
+ }
+
+ int initValueArg = 2;
+ if (needTypeclass(this.valueType) && args.length > 2) {
+ this.valueTypeClass = args[2];
+ Utils.validateTypeClass(context, this.valueType, this.valueTypeClass);
+ initValueArg = 3;
+ } else {
+ this.valueTypeClass = context.runtime.getNilClass();
+ }
+
+ // Table value type is always UINT64: this ensures enough space to store the
+ // native_slot value.
+ if (args.length > initValueArg) {
+ mergeIntoSelf(context, args[initValueArg]);
+ }
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * Map.[]=(key, value) => value
+ *
+ * Inserts or overwrites the value at the given key with the given new value.
+ * Throws an exception if the key type is incorrect. Returns the new value that
+ * was just inserted.
+ */
+ @JRubyMethod(name = "[]=")
+ public IRubyObject indexSet(ThreadContext context, IRubyObject key, IRubyObject value) {
+ Utils.checkType(context, keyType, key, (RubyModule) valueTypeClass);
+ Utils.checkType(context, valueType, value, (RubyModule) valueTypeClass);
+ IRubyObject symbol;
+ if (valueType == Descriptors.FieldDescriptor.Type.ENUM &&
+ Utils.isRubyNum(value) &&
+ ! (symbol = RubyEnum.lookup(context, valueTypeClass, value)).isNil()) {
+ value = symbol;
+ }
+ this.table.put(key, value);
+ return value;
+ }
+
+ /*
+ * call-seq:
+ * Map.[](key) => value
+ *
+ * Accesses the element at the given key. Throws an exception if the key type is
+ * incorrect. Returns nil when the key is not present in the map.
+ */
+ @JRubyMethod(name = "[]")
+ public IRubyObject index(ThreadContext context, IRubyObject key) {
+ if (table.containsKey(key))
+ return this.table.get(key);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Map.==(other) => boolean
+ *
+ * Compares this map to another. Maps are equal if they have identical key sets,
+ * and for each key, the values in both maps compare equal. Elements are
+ * compared as per normal Ruby semantics, by calling their :== methods (or
+ * performing a more efficient comparison for primitive types).
+ *
+ * Maps with dissimilar key types or value types/typeclasses are never equal,
+ * even if value comparison (for example, between integers and floats) would
+ * have otherwise indicated that every element has equal value.
+ */
+ @JRubyMethod(name = "==")
+ public IRubyObject eq(ThreadContext context, IRubyObject _other) {
+ if (_other instanceof RubyHash)
+ return toHash(context).op_equal(context, _other);
+ RubyMap other = (RubyMap) _other;
+ if (this == other) return context.runtime.getTrue();
+ if (!typeCompatible(other) || this.table.size() != other.table.size())
+ return context.runtime.getFalse();
+ for (IRubyObject key : table.keySet()) {
+ if (! other.table.containsKey(key))
+ return context.runtime.getFalse();
+ if (! other.table.get(key).equals(table.get(key)))
+ return context.runtime.getFalse();
+ }
+ return context.runtime.getTrue();
+ }
+
+ /*
+ * call-seq:
+ * Map.inspect => string
+ *
+ * Returns a string representing this map's elements. It will be formatted as
+ * "{key => value, key => value, ...}", with each key and value string
+ * representation computed by its own #inspect method.
+ */
+ @JRubyMethod
+ public IRubyObject inspect() {
+ return toHash(getRuntime().getCurrentContext()).inspect();
+ }
+
+ /*
+ * call-seq:
+ * Map.hash => hash_value
+ *
+ * Returns a hash value based on this map's contents.
+ */
+ @JRubyMethod
+ public IRubyObject hash(ThreadContext context) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ for (IRubyObject key : table.keySet()) {
+ digest.update((byte) key.hashCode());
+ digest.update((byte) table.get(key).hashCode());
+ }
+ return context.runtime.newString(new ByteList(digest.digest()));
+ } catch (NoSuchAlgorithmException ignore) {
+ return context.runtime.newFixnum(System.identityHashCode(table));
+ }
+ }
+
+ /*
+ * call-seq:
+ * Map.keys => [list_of_keys]
+ *
+ * Returns the list of keys contained in the map, in unspecified order.
+ */
+ @JRubyMethod
+ public IRubyObject keys(ThreadContext context) {
+ return RubyArray.newArray(context.runtime, table.keySet());
+ }
+
+ /*
+ * call-seq:
+ * Map.values => [list_of_values]
+ *
+ * Returns the list of values contained in the map, in unspecified order.
+ */
+ @JRubyMethod
+ public IRubyObject values(ThreadContext context) {
+ return RubyArray.newArray(context.runtime, table.values());
+ }
+
+ /*
+ * call-seq:
+ * Map.clear
+ *
+ * Removes all entries from the map.
+ */
+ @JRubyMethod
+ public IRubyObject clear(ThreadContext context) {
+ table.clear();
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Map.each(&block)
+ *
+ * Invokes &block on each |key, value| pair in the map, in unspecified order.
+ * Note that Map also includes Enumerable; map thus acts like a normal Ruby
+ * sequence.
+ */
+ @JRubyMethod
+ public IRubyObject each(ThreadContext context, Block block) {
+ for (IRubyObject key : table.keySet()) {
+ block.yieldSpecific(context, key, table.get(key));
+ }
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * Map.delete(key) => old_value
+ *
+ * Deletes the value at the given key, if any, returning either the old value or
+ * nil if none was present. Throws an exception if the key is of the wrong type.
+ */
+ @JRubyMethod
+ public IRubyObject delete(ThreadContext context, IRubyObject key) {
+ return table.remove(key);
+ }
+
+ /*
+ * call-seq:
+ * Map.has_key?(key) => bool
+ *
+ * Returns true if the given key is present in the map. Throws an exception if
+ * the key has the wrong type.
+ */
+ @JRubyMethod(name = "has_key?")
+ public IRubyObject hasKey(ThreadContext context, IRubyObject key) {
+ return this.table.containsKey(key) ? context.runtime.getTrue() : context.runtime.getFalse();
+ }
+
+ /*
+ * call-seq:
+ * Map.length
+ *
+ * Returns the number of entries (key-value pairs) in the map.
+ */
+ @JRubyMethod
+ public IRubyObject length(ThreadContext context) {
+ return context.runtime.newFixnum(this.table.size());
+ }
+
+ /*
+ * call-seq:
+ * Map.dup => new_map
+ *
+ * Duplicates this map with a shallow copy. References to all non-primitive
+ * element objects (e.g., submessages) are shared.
+ */
+ @JRubyMethod
+ public IRubyObject dup(ThreadContext context) {
+ RubyMap newMap = newThisType(context);
+ for (Map.Entry<IRubyObject, IRubyObject> entry : table.entrySet()) {
+ newMap.table.put(entry.getKey(), entry.getValue());
+ }
+ return newMap;
+ }
+
+ @JRubyMethod(name = "to_h")
+ public RubyHash toHash(ThreadContext context) {
+ return RubyHash.newHash(context.runtime, table, context.runtime.getNil());
+ }
+
+ // Used by Google::Protobuf.deep_copy but not exposed directly.
+ protected IRubyObject deepCopy(ThreadContext context) {
+ RubyMap newMap = newThisType(context);
+ switch (valueType) {
+ case MESSAGE:
+ for (IRubyObject key : table.keySet()) {
+ RubyMessage message = (RubyMessage) table.get(key);
+ newMap.table.put(key.dup(), message.deepCopy(context));
+ }
+ break;
+ default:
+ for (IRubyObject key : table.keySet()) {
+ newMap.table.put(key.dup(), table.get(key).dup());
+ }
+ }
+ return newMap;
+ }
+
+ protected List<DynamicMessage> build(ThreadContext context, RubyDescriptor descriptor) {
+ List<DynamicMessage> list = new ArrayList<DynamicMessage>();
+ RubyClass rubyClass = (RubyClass) descriptor.msgclass(context);
+ Descriptors.FieldDescriptor keyField = descriptor.lookup("key").getFieldDef();
+ Descriptors.FieldDescriptor valueField = descriptor.lookup("value").getFieldDef();
+ for (IRubyObject key : table.keySet()) {
+ RubyMessage mapMessage = (RubyMessage) rubyClass.newInstance(context, Block.NULL_BLOCK);
+ mapMessage.setField(context, keyField, key);
+ mapMessage.setField(context, valueField, table.get(key));
+ list.add(mapMessage.build(context));
+ }
+ return list;
+ }
+
+ protected RubyMap mergeIntoSelf(final ThreadContext context, IRubyObject hashmap) {
+ if (hashmap instanceof RubyHash) {
+ ((RubyHash) hashmap).visitAll(new RubyHash.Visitor() {
+ @Override
+ public void visit(IRubyObject key, IRubyObject val) {
+ indexSet(context, key, val);
+ }
+ });
+ } else if (hashmap instanceof RubyMap) {
+ RubyMap other = (RubyMap) hashmap;
+ if (!typeCompatible(other)) {
+ throw context.runtime.newTypeError("Attempt to merge Map with mismatching types");
+ }
+ } else {
+ throw context.runtime.newTypeError("Unknown type merging into Map");
+ }
+ return this;
+ }
+
+ protected boolean typeCompatible(RubyMap other) {
+ return this.keyType == other.keyType &&
+ this.valueType == other.valueType &&
+ this.valueTypeClass == other.valueTypeClass;
+ }
+
+ private RubyMap newThisType(ThreadContext context) {
+ RubyMap newMap;
+ if (needTypeclass(valueType)) {
+ newMap = (RubyMap) metaClass.newInstance(context,
+ Utils.fieldTypeToRuby(context, keyType),
+ Utils.fieldTypeToRuby(context, valueType),
+ valueTypeClass, Block.NULL_BLOCK);
+ } else {
+ newMap = (RubyMap) metaClass.newInstance(context,
+ Utils.fieldTypeToRuby(context, keyType),
+ Utils.fieldTypeToRuby(context, valueType),
+ Block.NULL_BLOCK);
+ }
+ newMap.table = new HashMap<IRubyObject, IRubyObject>();
+ return newMap;
+ }
+
+ private boolean needTypeclass(Descriptors.FieldDescriptor.Type type) {
+ switch(type) {
+ case MESSAGE:
+ case ENUM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private Descriptors.FieldDescriptor.Type keyType;
+ private Descriptors.FieldDescriptor.Type valueType;
+ private IRubyObject valueTypeClass;
+ private Map<IRubyObject, IRubyObject> table;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
new file mode 100644
index 00000000..04bc0b76
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -0,0 +1,744 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.*;
+import org.jruby.*;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.Helpers;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+import org.jruby.util.ByteList;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RubyMessage extends RubyObject {
+ public RubyMessage(Ruby ruby, RubyClass klazz, Descriptors.Descriptor descriptor) {
+ super(ruby, klazz);
+ this.descriptor = descriptor;
+ }
+
+ /*
+ * call-seq:
+ * Message.new(kwargs) => new_message
+ *
+ * Creates a new instance of the given message class. Keyword arguments may be
+ * provided with keywords corresponding to field names.
+ *
+ * Note that no literal Message class exists. Only concrete classes per message
+ * type exist, as provided by the #msgclass method on Descriptors after they
+ * have been added to a pool. The method definitions described here on the
+ * Message class are provided on each concrete message class.
+ */
+ @JRubyMethod(optional = 1)
+ public IRubyObject initialize(final ThreadContext context, IRubyObject[] args) {
+ final Ruby runtime = context.runtime;
+ this.cRepeatedField = (RubyClass) runtime.getClassFromPath("Google::Protobuf::RepeatedField");
+ this.cMap = (RubyClass) runtime.getClassFromPath("Google::Protobuf::Map");
+ this.builder = DynamicMessage.newBuilder(this.descriptor);
+ this.repeatedFields = new HashMap<Descriptors.FieldDescriptor, RubyRepeatedField>();
+ this.maps = new HashMap<Descriptors.FieldDescriptor, RubyMap>();
+ this.fields = new HashMap<Descriptors.FieldDescriptor, IRubyObject>();
+ this.oneofCases = new HashMap<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor>();
+ if (args.length == 1) {
+ if (!(args[0] instanceof RubyHash)) {
+ throw runtime.newArgumentError("expected Hash arguments.");
+ }
+ RubyHash hash = args[0].convertToHash();
+ hash.visitAll(new RubyHash.Visitor() {
+ @Override
+ public void visit(IRubyObject key, IRubyObject value) {
+ if (!(key instanceof RubySymbol))
+ throw runtime.newTypeError("Expected symbols as hash keys in initialization map.");
+ final Descriptors.FieldDescriptor fieldDescriptor = findField(context, key);
+
+ if (Utils.isMapEntry(fieldDescriptor)) {
+ if (!(value instanceof RubyHash))
+ throw runtime.newArgumentError("Expected Hash object as initializer value for map field.");
+
+ final RubyMap map = newMapForField(context, fieldDescriptor);
+ map.mergeIntoSelf(context, value);
+ maps.put(fieldDescriptor, map);
+ } else if (fieldDescriptor.isRepeated()) {
+ if (!(value instanceof RubyArray))
+ throw runtime.newTypeError("Expected array as initializer var for repeated field.");
+ RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, value);
+ addRepeatedField(fieldDescriptor, repeatedField);
+ } else {
+ Descriptors.OneofDescriptor oneof = fieldDescriptor.getContainingOneof();
+ if (oneof != null) {
+ oneofCases.put(oneof, fieldDescriptor);
+ }
+ fields.put(fieldDescriptor, value);
+ }
+
+ }
+ });
+ }
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * Message.[]=(index, value)
+ *
+ * Sets a field's value by field name. The provided field name should be a
+ * string.
+ */
+ @JRubyMethod(name = "[]=")
+ public IRubyObject indexSet(ThreadContext context, IRubyObject fieldName, IRubyObject value) {
+ Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName);
+ return setField(context, fieldDescriptor, value);
+ }
+
+ /*
+ * call-seq:
+ * Message.[](index) => value
+ *
+ * Accesses a field's value by field name. The provided field name should be a
+ * string.
+ */
+ @JRubyMethod(name = "[]")
+ public IRubyObject index(ThreadContext context, IRubyObject fieldName) {
+ Descriptors.FieldDescriptor fieldDescriptor = findField(context, fieldName);
+ return getField(context, fieldDescriptor);
+ }
+
+ /*
+ * call-seq:
+ * Message.inspect => string
+ *
+ * Returns a human-readable string representing this message. It will be
+ * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
+ * field's value is represented according to its own #inspect method.
+ */
+ @JRubyMethod
+ public IRubyObject inspect() {
+ String cname = metaClass.getName();
+ StringBuilder sb = new StringBuilder("<");
+ sb.append(cname);
+ sb.append(": ");
+ sb.append(this.layoutInspect());
+ sb.append(">");
+
+ return getRuntime().newString(sb.toString());
+ }
+
+ /*
+ * call-seq:
+ * Message.hash => hash_value
+ *
+ * Returns a hash value that represents this message's field values.
+ */
+ @JRubyMethod
+ public IRubyObject hash(ThreadContext context) {
+ int hashCode = System.identityHashCode(this);
+ return context.runtime.newFixnum(hashCode);
+ }
+
+ /*
+ * call-seq:
+ * Message.==(other) => boolean
+ *
+ * Performs a deep comparison of this message with another. Messages are equal
+ * if they have the same type and if each field is equal according to the :==
+ * method's semantics (a more efficient comparison may actually be done if the
+ * field is of a primitive type).
+ */
+ @JRubyMethod(name = "==")
+ public IRubyObject eq(ThreadContext context, IRubyObject other) {
+ Ruby runtime = context.runtime;
+ if (!(other instanceof RubyMessage))
+ return runtime.getFalse();
+ RubyMessage message = (RubyMessage) other;
+ if (descriptor != message.descriptor) {
+ return runtime.getFalse();
+ }
+
+ for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) {
+ IRubyObject thisVal = getField(context, fdef);
+ IRubyObject thatVal = message.getField(context, fdef);
+ IRubyObject ret = thisVal.callMethod(context, "==", thatVal);
+ if (!ret.isTrue()) {
+ return runtime.getFalse();
+ }
+ }
+ return runtime.getTrue();
+ }
+
+ /*
+ * call-seq:
+ * Message.method_missing(*args)
+ *
+ * Provides accessors and setters for message fields according to their field
+ * names. For any field whose name does not conflict with a built-in method, an
+ * accessor is provided with the same name as the field, and a setter is
+ * provided with the name of the field plus the '=' suffix. Thus, given a
+ * message instance 'msg' with field 'foo', the following code is valid:
+ *
+ * msg.foo = 42
+ * puts msg.foo
+ */
+ @JRubyMethod(name = "method_missing", rest = true)
+ public IRubyObject methodMissing(ThreadContext context, IRubyObject[] args) {
+ if (args.length == 1) {
+ RubyDescriptor rubyDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
+ IRubyObject oneofDescriptor = rubyDescriptor.lookupOneof(context, args[0]);
+ if (oneofDescriptor.isNil()) {
+ return index(context, args[0]);
+ }
+ RubyOneofDescriptor rubyOneofDescriptor = (RubyOneofDescriptor) oneofDescriptor;
+ Descriptors.FieldDescriptor fieldDescriptor =
+ oneofCases.get(rubyOneofDescriptor.getOneofDescriptor());
+ if (fieldDescriptor == null)
+ return context.runtime.getNil();
+
+ return context.runtime.newSymbol(fieldDescriptor.getName());
+ } else {
+ // fieldName is RubySymbol
+ RubyString field = args[0].asString();
+ RubyString equalSign = context.runtime.newString(Utils.EQUAL_SIGN);
+ if (field.end_with_p(context, equalSign).isTrue()) {
+ field.chomp_bang(context, equalSign);
+ }
+ return indexSet(context, field, args[1]);
+ }
+ }
+
+ /**
+ * call-seq:
+ * Message.dup => new_message
+ * Performs a shallow copy of this message and returns the new copy.
+ */
+ @JRubyMethod
+ public IRubyObject dup(ThreadContext context) {
+ RubyMessage dup = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK);
+ IRubyObject value;
+ for (Descriptors.FieldDescriptor fieldDescriptor : builder.getAllFields().keySet()) {
+ if (fieldDescriptor.isRepeated()) {
+ dup.repeatedFields.put(fieldDescriptor, getRepeatedField(context, fieldDescriptor));
+ } else if (builder.hasField(fieldDescriptor)) {
+ dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, builder.getField(fieldDescriptor)));
+ }
+ }
+ for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) {
+ dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor));
+ }
+ for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) {
+ dup.maps.put(fieldDescriptor, maps.get(fieldDescriptor));
+ }
+ return dup;
+ }
+
+ /*
+ * call-seq:
+ * Message.descriptor => descriptor
+ *
+ * Class method that returns the Descriptor instance corresponding to this
+ * message class's type.
+ */
+ @JRubyMethod(name = "descriptor", meta = true)
+ public static IRubyObject getDescriptor(ThreadContext context, IRubyObject recv) {
+ return ((RubyClass) recv).getInstanceVariable(Utils.DESCRIPTOR_INSTANCE_VAR);
+ }
+
+ /*
+ * call-seq:
+ * MessageClass.encode(msg) => bytes
+ *
+ * Encodes the given message object to its serialized form in protocol buffers
+ * wire format.
+ */
+ @JRubyMethod(meta = true)
+ public static IRubyObject encode(ThreadContext context, IRubyObject recv, IRubyObject value) {
+ RubyMessage message = (RubyMessage) value;
+ return context.runtime.newString(new ByteList(message.build(context).toByteArray()));
+ }
+
+ /*
+ * call-seq:
+ * MessageClass.decode(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+ @JRubyMethod(meta = true)
+ public static IRubyObject decode(ThreadContext context, IRubyObject recv, IRubyObject data) {
+ byte[] bin = data.convertToString().getBytes();
+ RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK);
+ try {
+ ret.builder.mergeFrom(bin);
+ } catch (InvalidProtocolBufferException e) {
+ throw context.runtime.newRuntimeError(e.getMessage());
+ }
+ return ret;
+ }
+
+ /*
+ * call-seq:
+ * MessageClass.encode_json(msg) => json_string
+ *
+ * Encodes the given message object into its serialized JSON representation.
+ */
+ @JRubyMethod(name = "encode_json", meta = true)
+ public static IRubyObject encodeJson(ThreadContext context, IRubyObject recv, IRubyObject msgRb) {
+ RubyMessage message = (RubyMessage) msgRb;
+ return Helpers.invoke(context, message.toHash(context), "to_json");
+ }
+
+ /*
+ * call-seq:
+ * MessageClass.decode_json(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+ @JRubyMethod(name = "decode_json", meta = true)
+ public static IRubyObject decodeJson(ThreadContext context, IRubyObject recv, IRubyObject json) {
+ Ruby runtime = context.runtime;
+ RubyMessage ret = (RubyMessage) ((RubyClass) recv).newInstance(context, Block.NULL_BLOCK);
+ RubyModule jsonModule = runtime.getClassFromPath("JSON");
+ RubyHash opts = RubyHash.newHash(runtime);
+ opts.fastASet(runtime.newSymbol("symbolize_names"), runtime.getTrue());
+ IRubyObject[] args = new IRubyObject[] { Helpers.invoke(context, jsonModule, "parse", json, opts) };
+ ret.initialize(context, args);
+ return ret;
+ }
+
+ @JRubyMethod(name = "to_h")
+ public IRubyObject toHash(ThreadContext context) {
+ Ruby runtime = context.runtime;
+ RubyHash ret = RubyHash.newHash(runtime);
+ for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
+ IRubyObject value = getField(context, fdef);
+ if (value.respondsTo("to_h")) {
+ value = Helpers.invoke(context, value, "to_h");
+ }
+ ret.fastASet(runtime.newString(fdef.getName()), value);
+ }
+ return ret;
+ }
+
+ protected DynamicMessage build(ThreadContext context) {
+ return build(context, 0);
+ }
+
+ protected DynamicMessage build(ThreadContext context, int depth) {
+ if (depth > SINK_MAXIMUM_NESTING) {
+ throw context.runtime.newRuntimeError("Maximum recursion depth exceeded during encoding.");
+ }
+ for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) {
+ this.builder.clearField(fieldDescriptor);
+ RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
+ for (DynamicMessage kv : maps.get(fieldDescriptor).build(context, mapDescriptor)) {
+ this.builder.addRepeatedField(fieldDescriptor, kv);
+ }
+ }
+ for (Descriptors.FieldDescriptor fieldDescriptor : repeatedFields.keySet()) {
+ RubyRepeatedField repeatedField = repeatedFields.get(fieldDescriptor);
+ this.builder.clearField(fieldDescriptor);
+ for (int i = 0; i < repeatedField.size(); i++) {
+ Object item = convert(context, fieldDescriptor, repeatedField.get(i), depth);
+ this.builder.addRepeatedField(fieldDescriptor, item);
+ }
+ }
+ for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) {
+ IRubyObject value = fields.get(fieldDescriptor);
+ this.builder.setField(fieldDescriptor, convert(context, fieldDescriptor, value, depth));
+ }
+ return this.builder.build();
+ }
+
+ protected Descriptors.Descriptor getDescriptor() {
+ return this.descriptor;
+ }
+
+ // Internal use only, called by Google::Protobuf.deep_copy
+ protected IRubyObject deepCopy(ThreadContext context) {
+ RubyMessage copy = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK);
+ for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
+ if (fdef.isRepeated()) {
+ copy.addRepeatedField(fdef, this.getRepeatedField(context, fdef).deepCopy(context));
+ } else if (fields.containsKey(fdef)) {
+ copy.fields.put(fdef, fields.get(fdef));
+ } else if (this.builder.hasField(fdef)) {
+ copy.fields.put(fdef, wrapField(context, fdef, this.builder.getField(fdef)));
+ }
+ }
+ return copy;
+ }
+
+ private RubyRepeatedField getRepeatedField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+ if (this.repeatedFields.containsKey(fieldDescriptor)) {
+ return this.repeatedFields.get(fieldDescriptor);
+ }
+ int count = this.builder.getRepeatedFieldCount(fieldDescriptor);
+ RubyRepeatedField ret = repeatedFieldForFieldDescriptor(context, fieldDescriptor);
+ for (int i = 0; i < count; i++) {
+ ret.push(context, wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i)));
+ }
+ return ret;
+ }
+
+ private void addRepeatedField(Descriptors.FieldDescriptor fieldDescriptor, RubyRepeatedField repeatedField) {
+ this.repeatedFields.put(fieldDescriptor, repeatedField);
+ }
+
+ private IRubyObject buildFrom(ThreadContext context, DynamicMessage dynamicMessage) {
+ this.builder.mergeFrom(dynamicMessage);
+ return this;
+ }
+
+ private Descriptors.FieldDescriptor findField(ThreadContext context, IRubyObject fieldName) {
+ String nameStr = fieldName.asJavaString();
+ Descriptors.FieldDescriptor ret = this.descriptor.findFieldByName(Utils.escapeIdentifier(nameStr));
+ if (ret == null)
+ throw context.runtime.newArgumentError("field " + fieldName.asJavaString() + " is not found");
+ return ret;
+ }
+
+ private void checkRepeatedFieldType(ThreadContext context, IRubyObject value,
+ Descriptors.FieldDescriptor fieldDescriptor) {
+ Ruby runtime = context.runtime;
+ if (!(value instanceof RubyRepeatedField)) {
+ throw runtime.newTypeError("Expected repeated field array");
+ }
+ }
+
+ // convert a ruby object to protobuf type, with type check
+ private Object convert(ThreadContext context,
+ Descriptors.FieldDescriptor fieldDescriptor,
+ IRubyObject value, int depth) {
+ Ruby runtime = context.runtime;
+ Object val = null;
+ switch (fieldDescriptor.getType()) {
+ case INT32:
+ case INT64:
+ case UINT32:
+ case UINT64:
+ if (!Utils.isRubyNum(value)) {
+ throw runtime.newTypeError("Expected number type for integral field.");
+ }
+ Utils.checkIntTypePrecision(context, fieldDescriptor.getType(), value);
+ switch (fieldDescriptor.getType()) {
+ case INT32:
+ val = RubyNumeric.num2int(value);
+ break;
+ case INT64:
+ val = RubyNumeric.num2long(value);
+ break;
+ case UINT32:
+ val = Utils.num2uint(value);
+ break;
+ case UINT64:
+ val = Utils.num2ulong(context.runtime, value);
+ break;
+ default:
+ break;
+ }
+ break;
+ case FLOAT:
+ if (!Utils.isRubyNum(value))
+ throw runtime.newTypeError("Expected number type for float field.");
+ val = (float) RubyNumeric.num2dbl(value);
+ break;
+ case DOUBLE:
+ if (!Utils.isRubyNum(value))
+ throw runtime.newTypeError("Expected number type for double field.");
+ val = RubyNumeric.num2dbl(value);
+ break;
+ case BOOL:
+ if (!(value instanceof RubyBoolean))
+ throw runtime.newTypeError("Invalid argument for boolean field.");
+ val = value.isTrue();
+ break;
+ case BYTES:
+ case STRING:
+ Utils.validateStringEncoding(context.runtime, fieldDescriptor.getType(), value);
+ RubyString str = (RubyString) value;
+ switch (fieldDescriptor.getType()) {
+ case BYTES:
+ val = ByteString.copyFrom(str.getBytes());
+ break;
+ case STRING:
+ val = str.asJavaString();
+ break;
+ default:
+ break;
+ }
+ break;
+ case MESSAGE:
+ RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+ if (!value.getMetaClass().equals(typeClass))
+ throw runtime.newTypeError(value, "Invalid type to assign to submessage field.");
+ val = ((RubyMessage) value).build(context, depth + 1);
+ break;
+ case ENUM:
+ Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
+
+ if (Utils.isRubyNum(value)) {
+ val = enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
+ } else if (value instanceof RubySymbol) {
+ val = enumDescriptor.findValueByName(value.asJavaString());
+ } else {
+ throw runtime.newTypeError("Expected number or symbol type for enum field.");
+ }
+ if (val == null) {
+ throw runtime.newRangeError("Enum value " + value + " is not found.");
+ }
+ break;
+ default:
+ break;
+ }
+ return val;
+ }
+
+ private IRubyObject wrapField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, Object value) {
+ if (value == null) {
+ return context.runtime.getNil();
+ }
+ Ruby runtime = context.runtime;
+ switch (fieldDescriptor.getType()) {
+ case INT32:
+ case INT64:
+ case UINT32:
+ case UINT64:
+ case FLOAT:
+ case DOUBLE:
+ case BOOL:
+ case BYTES:
+ case STRING:
+ return Utils.wrapPrimaryValue(context, fieldDescriptor.getType(), value);
+ case MESSAGE:
+ RubyClass typeClass = (RubyClass) ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+ RubyMessage msg = (RubyMessage) typeClass.newInstance(context, Block.NULL_BLOCK);
+ return msg.buildFrom(context, (DynamicMessage) value);
+ case ENUM:
+ Descriptors.EnumValueDescriptor enumValueDescriptor = (Descriptors.EnumValueDescriptor) value;
+ if (enumValueDescriptor.getIndex() == -1) { // UNKNOWN ENUM VALUE
+ return runtime.newFixnum(enumValueDescriptor.getNumber());
+ }
+ return runtime.newSymbol(enumValueDescriptor.getName());
+ default:
+ return runtime.newString(value.toString());
+ }
+ }
+
+ private RubyRepeatedField repeatedFieldForFieldDescriptor(ThreadContext context,
+ Descriptors.FieldDescriptor fieldDescriptor) {
+ IRubyObject typeClass = context.runtime.getNilClass();
+
+ IRubyObject descriptor = getDescriptorForField(context, fieldDescriptor);
+ Descriptors.FieldDescriptor.Type type = fieldDescriptor.getType();
+ if (type == Descriptors.FieldDescriptor.Type.MESSAGE) {
+ typeClass = ((RubyDescriptor) descriptor).msgclass(context);
+
+ } else if (type == Descriptors.FieldDescriptor.Type.ENUM) {
+ typeClass = ((RubyEnumDescriptor) descriptor).enummodule(context);
+ }
+ return new RubyRepeatedField(context.runtime, cRepeatedField, type, typeClass);
+ }
+
+ protected IRubyObject getField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+ Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+ if (oneofDescriptor != null) {
+ if (oneofCases.containsKey(oneofDescriptor)) {
+ if (oneofCases.get(oneofDescriptor) != fieldDescriptor)
+ return context.runtime.getNil();
+ return fields.get(fieldDescriptor);
+ } else {
+ Descriptors.FieldDescriptor oneofCase = builder.getOneofFieldDescriptor(oneofDescriptor);
+ if (oneofCase != fieldDescriptor) return context.runtime.getNil();
+ IRubyObject value = wrapField(context, oneofCase, builder.getField(oneofCase));
+ fields.put(fieldDescriptor, value);
+ return value;
+ }
+ }
+
+ if (Utils.isMapEntry(fieldDescriptor)) {
+ RubyMap map = maps.get(fieldDescriptor);
+ if (map == null) {
+ map = newMapForField(context, fieldDescriptor);
+ int mapSize = this.builder.getRepeatedFieldCount(fieldDescriptor);
+ Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
+ Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
+ RubyDescriptor kvDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
+ RubyClass kvClass = (RubyClass) kvDescriptor.msgclass(context);
+ for (int i = 0; i < mapSize; i++) {
+ RubyMessage kvMessage = (RubyMessage) kvClass.newInstance(context, Block.NULL_BLOCK);
+ DynamicMessage message = (DynamicMessage) this.builder.getRepeatedField(fieldDescriptor, i);
+ kvMessage.buildFrom(context, message);
+ map.indexSet(context, kvMessage.getField(context, keyField), kvMessage.getField(context, valueField));
+ }
+ maps.put(fieldDescriptor, map);
+ }
+ return map;
+ }
+ if (fieldDescriptor.isRepeated()) {
+ return getRepeatedField(context, fieldDescriptor);
+ }
+ if (fieldDescriptor.getType() != Descriptors.FieldDescriptor.Type.MESSAGE ||
+ this.builder.hasField(fieldDescriptor) || fields.containsKey(fieldDescriptor)) {
+ if (fields.containsKey(fieldDescriptor)) {
+ return fields.get(fieldDescriptor);
+ } else {
+ IRubyObject value = wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor));
+ if (this.builder.hasField(fieldDescriptor)) {
+ fields.put(fieldDescriptor, value);
+ }
+ return value;
+ }
+ }
+ return context.runtime.getNil();
+ }
+
+ protected IRubyObject setField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) {
+ if (Utils.isMapEntry(fieldDescriptor)) {
+ if (!(value instanceof RubyMap)) {
+ throw context.runtime.newTypeError("Expected Map instance");
+ }
+ RubyMap thisMap = (RubyMap) getField(context, fieldDescriptor);
+ thisMap.mergeIntoSelf(context, value);
+ } else if (fieldDescriptor.isRepeated()) {
+ checkRepeatedFieldType(context, value, fieldDescriptor);
+ if (value instanceof RubyRepeatedField) {
+ addRepeatedField(fieldDescriptor, (RubyRepeatedField) value);
+ } else {
+ RubyArray ary = value.convertToArray();
+ RubyRepeatedField repeatedField = rubyToRepeatedField(context, fieldDescriptor, ary);
+ addRepeatedField(fieldDescriptor, repeatedField);
+ }
+ } else {
+ Descriptors.OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
+ if (oneofDescriptor != null) {
+ Descriptors.FieldDescriptor oneofCase = oneofCases.get(oneofDescriptor);
+ if (oneofCase != null && oneofCase != fieldDescriptor) {
+ fields.remove(oneofCase);
+ }
+ if (value.isNil()) {
+ oneofCases.remove(oneofDescriptor);
+ fields.remove(fieldDescriptor);
+ } else {
+ oneofCases.put(oneofDescriptor, fieldDescriptor);
+ fields.put(fieldDescriptor, value);
+ }
+ } else {
+ Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
+ IRubyObject typeClass = context.runtime.getObject();
+ if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
+ typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+ } else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
+ typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context);
+ }
+ Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ // Convert integer enum to symbol
+ if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
+ Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
+ if (Utils.isRubyNum(value)) {
+ Descriptors.EnumValueDescriptor val =
+ enumDescriptor.findValueByNumberCreatingIfUnknown(RubyNumeric.num2int(value));
+ if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName());
+ }
+ }
+ this.fields.put(fieldDescriptor, value);
+ }
+ }
+ return context.runtime.getNil();
+ }
+
+ private String layoutInspect() {
+ ThreadContext context = getRuntime().getCurrentContext();
+ StringBuilder sb = new StringBuilder();
+ for (Descriptors.FieldDescriptor fdef : descriptor.getFields()) {
+ sb.append(Utils.unescapeIdentifier(fdef.getName()));
+ sb.append(": ");
+ sb.append(getField(context, fdef).inspect());
+ sb.append(", ");
+ }
+ return sb.substring(0, sb.length() - 2);
+ }
+
+ private IRubyObject getDescriptorForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+ RubyDescriptor thisRbDescriptor = (RubyDescriptor) getDescriptor(context, metaClass);
+ return thisRbDescriptor.lookup(fieldDescriptor.getName()).getSubType(context);
+ }
+
+ private RubyRepeatedField rubyToRepeatedField(ThreadContext context,
+ Descriptors.FieldDescriptor fieldDescriptor, IRubyObject value) {
+ RubyArray arr = value.convertToArray();
+ RubyRepeatedField repeatedField = repeatedFieldForFieldDescriptor(context, fieldDescriptor);
+ for (int i = 0; i < arr.size(); i++) {
+ repeatedField.push(context, arr.eltInternal(i));
+ }
+ return repeatedField;
+ }
+
+ private RubyMap newMapForField(ThreadContext context, Descriptors.FieldDescriptor fieldDescriptor) {
+ RubyDescriptor mapDescriptor = (RubyDescriptor) getDescriptorForField(context, fieldDescriptor);
+ Descriptors.FieldDescriptor keyField = fieldDescriptor.getMessageType().findFieldByNumber(1);
+ Descriptors.FieldDescriptor valueField = fieldDescriptor.getMessageType().findFieldByNumber(2);
+ IRubyObject keyType = RubySymbol.newSymbol(context.runtime, keyField.getType().name());
+ IRubyObject valueType = RubySymbol.newSymbol(context.runtime, valueField.getType().name());
+ if (valueField.getType() == Descriptors.FieldDescriptor.Type.MESSAGE) {
+ RubyFieldDescriptor rubyFieldDescriptor = (RubyFieldDescriptor) mapDescriptor.lookup(context,
+ context.runtime.newString("value"));
+ RubyDescriptor rubyDescriptor = (RubyDescriptor) rubyFieldDescriptor.getSubType(context);
+ return (RubyMap) cMap.newInstance(context, keyType, valueType,
+ rubyDescriptor.msgclass(context), Block.NULL_BLOCK);
+ } else {
+ return (RubyMap) cMap.newInstance(context, keyType, valueType, Block.NULL_BLOCK);
+ }
+ }
+
+ private Descriptors.FieldDescriptor getOneofCase(Descriptors.OneofDescriptor oneof) {
+ if (oneofCases.containsKey(oneof)) {
+ return oneofCases.get(oneof);
+ }
+ return builder.getOneofFieldDescriptor(oneof);
+ }
+
+ private Descriptors.Descriptor descriptor;
+ private DynamicMessage.Builder builder;
+ private RubyClass cRepeatedField;
+ private RubyClass cMap;
+ private Map<Descriptors.FieldDescriptor, RubyRepeatedField> repeatedFields;
+ private Map<Descriptors.FieldDescriptor, RubyMap> maps;
+ private Map<Descriptors.FieldDescriptor, IRubyObject> fields;
+ private Map<Descriptors.OneofDescriptor, Descriptors.FieldDescriptor> oneofCases;
+
+ private static final int SINK_MAXIMUM_NESTING = 64;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java
new file mode 100644
index 00000000..a619b803
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessageBuilderContext.java
@@ -0,0 +1,217 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Binding;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "MessageBuilderContext")
+public class RubyMessageBuilderContext extends RubyObject {
+ public static void createRubyMessageBuilderContext(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cMessageBuilderContext = protobuf.defineClassUnder("MessageBuilderContext", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyMessageBuilderContext(runtime, klazz);
+ }
+ });
+ cMessageBuilderContext.defineAnnotatedMethods(RubyMessageBuilderContext.class);
+ }
+
+ public RubyMessageBuilderContext(Ruby ruby, RubyClass klazz) {
+ super(ruby, klazz);
+ }
+
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context, IRubyObject descriptor, IRubyObject rubyBuilder) {
+ this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
+ this.cDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Descriptor");
+ this.cOneofDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::OneofDescriptor");
+ this.cOneofBuilderContext = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::Internal::OneofBuilderContext");
+ this.descriptor = (RubyDescriptor) descriptor;
+ this.builder = (RubyBuilder) rubyBuilder;
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * MessageBuilderContext.optional(name, type, number, type_class = nil)
+ *
+ * Defines a new optional field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+ @JRubyMethod(required = 3, optional = 1)
+ public IRubyObject optional(ThreadContext context, IRubyObject[] args) {
+ Ruby runtime = context.runtime;
+ IRubyObject typeClass = runtime.getNil();
+ if (args.length > 3) typeClass = args[3];
+ msgdefAddField(context, "optional", args[0], args[1], args[2], typeClass);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * MessageBuilderContext.required(name, type, number, type_class = nil)
+ *
+ * Defines a new required field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ *
+ * Proto3 does not have required fields, but this method exists for
+ * completeness. Any attempt to add a message type with required fields to a
+ * pool will currently result in an error.
+ */
+ @JRubyMethod(required = 3, optional = 1)
+ public IRubyObject required(ThreadContext context, IRubyObject[] args) {
+ IRubyObject typeClass = context.runtime.getNil();
+ if (args.length > 3) typeClass = args[3];
+ msgdefAddField(context, "required", args[0], args[1], args[2], typeClass);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * MessageBuilderContext.repeated(name, type, number, type_class = nil)
+ *
+ * Defines a new repeated field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+ @JRubyMethod(required = 3, optional = 1)
+ public IRubyObject repeated(ThreadContext context, IRubyObject[] args) {
+ IRubyObject typeClass = context.runtime.getNil();
+ if (args.length > 3) typeClass = args[3];
+ msgdefAddField(context, "repeated", args[0], args[1], args[2], typeClass);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * MessageBuilderContext.map(name, key_type, value_type, number,
+ * value_type_class = nil)
+ *
+ * Defines a new map field on this message type with the given key and value
+ * types, tag number, and type class (for message and enum value types). The key
+ * type must be :int32/:uint32/:int64/:uint64, :bool, or :string. The value type
+ * type must be a Ruby symbol (as accepted by FieldDescriptor#type=) and the
+ * type_class must be a string, if present (as accepted by
+ * FieldDescriptor#submsg_name=).
+ */
+ @JRubyMethod(required = 4, optional = 1)
+ public IRubyObject map(ThreadContext context, IRubyObject[] args) {
+ Ruby runtime = context.runtime;
+ IRubyObject name = args[0];
+ IRubyObject keyType = args[1];
+ IRubyObject valueType = args[2];
+ IRubyObject number = args[3];
+ IRubyObject typeClass = args.length > 4 ? args[4] : context.runtime.getNil();
+
+ // Validate the key type. We can't accept enums, messages, or floats/doubles
+ // as map keys. (We exclude these explicitly, and the field-descriptor setter
+ // below then ensures that the type is one of the remaining valid options.)
+ if (keyType.equals(RubySymbol.newSymbol(runtime, "float")) ||
+ keyType.equals(RubySymbol.newSymbol(runtime, "double")) ||
+ keyType.equals(RubySymbol.newSymbol(runtime, "enum")) ||
+ keyType.equals(RubySymbol.newSymbol(runtime, "message")))
+ throw runtime.newArgumentError("Cannot add a map field with a float, double, enum, or message type.");
+
+ // Create a new message descriptor for the map entry message, and create a
+ // repeated submessage field here with that type.
+ RubyDescriptor mapentryDesc = (RubyDescriptor) cDescriptor.newInstance(context, Block.NULL_BLOCK);
+ IRubyObject mapentryDescName = RubySymbol.newSymbol(runtime, name).id2name(context);
+ mapentryDesc.setName(context, mapentryDescName);
+ mapentryDesc.setMapEntry(true);
+
+ //optional <type> key = 1;
+ RubyFieldDescriptor keyField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
+ keyField.setName(context, runtime.newString("key"));
+ keyField.setLabel(context, RubySymbol.newSymbol(runtime, "optional"));
+ keyField.setNumber(context, runtime.newFixnum(1));
+ keyField.setType(context, keyType);
+ mapentryDesc.addField(context, keyField);
+
+ //optional <type> value = 2;
+ RubyFieldDescriptor valueField = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
+ valueField.setName(context, runtime.newString("value"));
+ valueField.setLabel(context, RubySymbol.newSymbol(runtime, "optional"));
+ valueField.setNumber(context, runtime.newFixnum(2));
+ valueField.setType(context, valueType);
+ if (! typeClass.isNil()) valueField.setSubmsgName(context, typeClass);
+ mapentryDesc.addField(context, valueField);
+
+ // Add the map-entry message type to the current builder, and use the type to
+ // create the map field itself.
+ this.builder.pendingList.add(mapentryDesc);
+
+ msgdefAddField(context, "repeated", name, runtime.newSymbol("message"), number, mapentryDescName);
+ return runtime.getNil();
+ }
+
+ @JRubyMethod
+ public IRubyObject oneof(ThreadContext context, IRubyObject name, Block block) {
+ RubyOneofDescriptor oneofdef = (RubyOneofDescriptor)
+ cOneofDescriptor.newInstance(context, Block.NULL_BLOCK);
+ RubyOneofBuilderContext ctx = (RubyOneofBuilderContext)
+ cOneofBuilderContext.newInstance(context, oneofdef, Block.NULL_BLOCK);
+ oneofdef.setName(context, name);
+ Binding binding = block.getBinding();
+ binding.setSelf(ctx);
+ block.yieldSpecific(context);
+ descriptor.addOneof(context, oneofdef);
+ return context.runtime.getNil();
+ }
+
+ private void msgdefAddField(ThreadContext context, String label, IRubyObject name,
+ IRubyObject type, IRubyObject number, IRubyObject typeClass) {
+ descriptor.addField(context,
+ Utils.msgdefCreateField(context, label, name, type, number, typeClass, cFieldDescriptor));
+ }
+
+ private RubyDescriptor descriptor;
+ private RubyBuilder builder;
+ private RubyClass cFieldDescriptor;
+ private RubyClass cOneofDescriptor;
+ private RubyClass cOneofBuilderContext;
+ private RubyClass cDescriptor;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java
new file mode 100644
index 00000000..c9b99e04
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofBuilderContext.java
@@ -0,0 +1,84 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "OneofBuilderContext")
+public class RubyOneofBuilderContext extends RubyObject {
+ public static void createRubyOneofBuilderContext(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyModule internal = protobuf.defineModuleUnder("Internal");
+ RubyClass cRubyOneofBuidlerContext = internal.defineClassUnder("OneofBuilderContext", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
+ return new RubyOneofBuilderContext(ruby, rubyClass);
+ }
+ });
+ cRubyOneofBuidlerContext.defineAnnotatedMethods(RubyOneofBuilderContext.class);
+ }
+
+ public RubyOneofBuilderContext(Ruby ruby, RubyClass rubyClass) {
+ super(ruby, rubyClass);
+ }
+
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context, IRubyObject oneofdef) {
+ this.descriptor = (RubyOneofDescriptor) oneofdef;
+ this.cFieldDescriptor = (RubyClass) context.runtime.getClassFromPath("Google::Protobuf::FieldDescriptor");
+ return this;
+ }
+
+ @JRubyMethod(required = 3, optional = 1)
+ public IRubyObject optional(ThreadContext context, IRubyObject[] args) {
+ IRubyObject name = args[0];
+ IRubyObject type = args[1];
+ IRubyObject number = args[2];
+ IRubyObject typeClass = args.length > 3 ? args[3] : context.runtime.getNil();
+ RubyFieldDescriptor fieldDescriptor = Utils.msgdefCreateField(context, "optional",
+ name, type, number, typeClass, cFieldDescriptor);
+ descriptor.addField(context, fieldDescriptor);
+ return this;
+ }
+
+ private RubyOneofDescriptor descriptor;
+ private RubyClass cFieldDescriptor;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
new file mode 100644
index 00000000..cc4ab662
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java
@@ -0,0 +1,124 @@
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jruby.Ruby;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.RubyObject;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.util.*;
+
+@JRubyClass(name = "OneofDescriptor", include = "Enumerable")
+public class RubyOneofDescriptor extends RubyObject {
+
+ public static void createRubyOneofDescriptor(Ruby runtime) {
+ RubyModule protobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cRubyOneofDescriptor = protobuf.defineClassUnder("OneofDescriptor", runtime.getObject(), new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby ruby, RubyClass rubyClass) {
+ return new RubyOneofDescriptor(ruby, rubyClass);
+ }
+ });
+ cRubyOneofDescriptor.defineAnnotatedMethods(RubyOneofDescriptor.class);
+ cRubyOneofDescriptor.includeModule(runtime.getEnumerable());
+ }
+
+ public RubyOneofDescriptor(Ruby ruby, RubyClass rubyClass) {
+ super(ruby, rubyClass);
+ }
+
+ @JRubyMethod
+ public IRubyObject initialize(ThreadContext context) {
+ builder = DescriptorProtos.OneofDescriptorProto.newBuilder();
+ fields = new ArrayList<RubyFieldDescriptor>();
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * OneofDescriptor.name => name
+ *
+ * Returns the name of this oneof.
+ */
+ @JRubyMethod(name = "name")
+ public IRubyObject getName(ThreadContext context) {
+ return name;
+ }
+
+ /*
+ * call-seq:
+ * OneofDescriptor.name = name
+ *
+ * Sets a new name for this oneof. The oneof must not have been added to a
+ * message descriptor yet.
+ */
+ @JRubyMethod(name = "name=")
+ public IRubyObject setName(ThreadContext context, IRubyObject name) {
+ this.name = context.runtime.newString(name.asJavaString());
+ this.builder.setName(name.asJavaString());
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * OneofDescriptor.add_field(field) => nil
+ *
+ * Adds a field to this oneof. The field may have been added to this oneof in
+ * the past, or the message to which this oneof belongs (if any), but may not
+ * have already been added to any other oneof or message. Otherwise, an
+ * exception is raised.
+ *
+ * All fields added to the oneof via this method will be automatically added to
+ * the message to which this oneof belongs, if it belongs to one currently, or
+ * else will be added to any message to which the oneof is later added at the
+ * time that it is added.
+ */
+ @JRubyMethod(name = "add_field")
+ public IRubyObject addField(ThreadContext context, IRubyObject obj) {
+ RubyFieldDescriptor fieldDescriptor = (RubyFieldDescriptor) obj;
+ fieldDescriptor.setOneofName(this.name);
+ fields.add(fieldDescriptor);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * OneofDescriptor.each(&block) => nil
+ *
+ * Iterates through fields in this oneof, yielding to the block on each one.
+ */
+ @JRubyMethod
+ public IRubyObject each(ThreadContext context, Block block) {
+ for (RubyFieldDescriptor field : fields) {
+ block.yieldSpecific(context, field);
+ }
+ return context.runtime.getNil();
+ }
+
+ public DescriptorProtos.OneofDescriptorProto build(int index) {
+ for (RubyFieldDescriptor field: fields) {
+ field.setOneofIndex(index);
+ }
+ return this.builder.build();
+ }
+
+ protected Collection<RubyFieldDescriptor> getFields() {
+ return fields;
+ }
+
+ protected Descriptors.OneofDescriptor getOneofDescriptor() {
+ RubyFieldDescriptor fieldDescriptor = fields.get(0);
+ return fieldDescriptor.getFieldDef().getContainingOneof();
+ }
+
+ private IRubyObject name;
+ private DescriptorProtos.OneofDescriptorProto.Builder builder;
+ private List<RubyFieldDescriptor> fields;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
new file mode 100644
index 00000000..cb3fcd48
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java
@@ -0,0 +1,118 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import org.jruby.Ruby;
+import org.jruby.RubyModule;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.anno.JRubyModule;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyModule(name = "Protobuf")
+public class RubyProtobuf {
+
+ public static void createProtobuf(Ruby runtime) {
+ RubyModule mGoogle = runtime.getModule("Google");
+ RubyModule mProtobuf = mGoogle.defineModuleUnder("Protobuf");
+ mProtobuf.defineAnnotatedMethods(RubyProtobuf.class);
+ }
+
+ /*
+ * call-seq:
+ * Google::Protobuf.encode(msg) => bytes
+ *
+ * Encodes the given message object to protocol buffers wire format. This is an
+ * alternative to the #encode method on msg's class.
+ */
+ @JRubyMethod(meta = true)
+ public static IRubyObject encode(ThreadContext context, IRubyObject self, IRubyObject message) {
+ return RubyMessage.encode(context, message.getMetaClass(), message);
+ }
+
+ /*
+ * call-seq:
+ * Google::Protobuf.decode(class, bytes) => msg
+ *
+ * Decodes the given bytes as protocol buffers wire format under the
+ * interpretation given by the given class's message definition. This is an
+ * alternative to the #decode method on the given class.
+ */
+ @JRubyMethod(meta = true)
+ public static IRubyObject decode(ThreadContext context, IRubyObject self, IRubyObject klazz, IRubyObject message) {
+ return RubyMessage.decode(context, klazz, message);
+ }
+
+ /*
+ * call-seq:
+ * Google::Protobuf.encode_json(msg) => json_string
+ *
+ * Encodes the given message object to its JSON representation. This is an
+ * alternative to the #encode_json method on msg's class.
+ */
+ @JRubyMethod(name = "encode_json", meta = true)
+ public static IRubyObject encodeJson(ThreadContext context, IRubyObject self, IRubyObject message) {
+ return RubyMessage.encodeJson(context, message.getMetaClass(), message);
+ }
+
+ /*
+ * call-seq:
+ * Google::Protobuf.decode_json(class, json_string) => msg
+ *
+ * Decodes the given JSON string under the interpretation given by the given
+ * class's message definition. This is an alternative to the #decode_json method
+ * on the given class.
+ */
+ @JRubyMethod(name = "decode_json", meta = true)
+ public static IRubyObject decodeJson(ThreadContext context, IRubyObject self, IRubyObject klazz, IRubyObject message) {
+ return RubyMessage.decodeJson(context, klazz, message);
+ }
+
+ /*
+ * call-seq:
+ * Google::Protobuf.deep_copy(obj) => copy_of_obj
+ *
+ * Performs a deep copy of either a RepeatedField instance or a message object,
+ * recursively copying its members.
+ */
+ @JRubyMethod(name = "deep_copy", meta = true)
+ public static IRubyObject deepCopy(ThreadContext context, IRubyObject self, IRubyObject message) {
+ if (message instanceof RubyMessage) {
+ return ((RubyMessage) message).deepCopy(context);
+ } else if (message instanceof RubyRepeatedField) {
+ return ((RubyRepeatedField) message).deepCopy(context);
+ } else {
+ return ((RubyMap) message).deepCopy(context);
+ }
+ }
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
new file mode 100644
index 00000000..9788317a
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
@@ -0,0 +1,391 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.Descriptors;
+import org.jruby.*;
+import org.jruby.anno.JRubyClass;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ObjectAllocator;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+@JRubyClass(name = "RepeatedClass", include = "Enumerable")
+public class RubyRepeatedField extends RubyObject {
+ public static void createRubyRepeatedField(Ruby runtime) {
+ RubyModule mProtobuf = runtime.getClassFromPath("Google::Protobuf");
+ RubyClass cRepeatedField = mProtobuf.defineClassUnder("RepeatedField", runtime.getObject(),
+ new ObjectAllocator() {
+ @Override
+ public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
+ return new RubyRepeatedField(runtime, klazz);
+ }
+ });
+ cRepeatedField.defineAnnotatedMethods(RubyRepeatedField.class);
+ cRepeatedField.includeModule(runtime.getEnumerable());
+ }
+
+ public RubyRepeatedField(Ruby runtime, RubyClass klazz) {
+ super(runtime, klazz);
+ }
+
+ public RubyRepeatedField(Ruby runtime, RubyClass klazz, Descriptors.FieldDescriptor.Type fieldType, IRubyObject typeClass) {
+ this(runtime, klazz);
+ this.fieldType = fieldType;
+ this.storage = runtime.newArray();
+ this.typeClass = typeClass;
+ }
+
+ @JRubyMethod(required = 1, optional = 2)
+ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
+ Ruby runtime = context.runtime;
+ this.storage = runtime.newArray();
+ IRubyObject ary = null;
+ if (!(args[0] instanceof RubySymbol)) {
+ throw runtime.newArgumentError("Expected Symbol for type name");
+ }
+ this.fieldType = Utils.rubyToFieldType(args[0]);
+ if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE
+ || fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
+ if (args.length < 2)
+ throw runtime.newArgumentError("Expected at least 2 arguments for message/enum");
+ typeClass = args[1];
+ if (args.length > 2)
+ ary = args[2];
+ Utils.validateTypeClass(context, fieldType, typeClass);
+ } else {
+ if (args.length > 2)
+ throw runtime.newArgumentError("Too many arguments: expected 1 or 2");
+ if (args.length > 1)
+ ary = args[1];
+ }
+ if (ary != null) {
+ RubyArray arr = ary.convertToArray();
+ for (int i = 0; i < arr.size(); i++) {
+ this.storage.add(arr.eltInternal(i));
+ }
+ }
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.[]=(index, value)
+ *
+ * Sets the element at the given index. On out-of-bounds assignments, extends
+ * the array and fills the hole (if any) with default values.
+ */
+ @JRubyMethod(name = "[]=")
+ public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
+ Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ this.storage.set(RubyNumeric.num2int(index), value);
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.[](index) => value
+ *
+ * Accesses the element at the given index. Throws an exception on out-of-bounds
+ * errors.
+ */
+ @JRubyMethod(name = "[]")
+ public IRubyObject index(ThreadContext context, IRubyObject index) {
+ return this.storage.eltInternal(RubyNumeric.num2int(index));
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.insert(*args)
+ *
+ * Pushes each arg in turn onto the end of the repeated field.
+ */
+ @JRubyMethod(rest = true)
+ public IRubyObject insert(ThreadContext context, IRubyObject[] args) {
+ for (int i = 0; i < args.length; i++) {
+ Utils.checkType(context, fieldType, args[i], (RubyModule) typeClass);
+ this.storage.add(args[i]);
+ }
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.push(value)
+ *
+ * Adds a new element to the repeated field.
+ */
+ @JRubyMethod(name = {"push", "<<"})
+ public IRubyObject push(ThreadContext context, IRubyObject value) {
+ Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ this.storage.add(value);
+ return this;
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.pop => value
+ *
+ * Removes the last element and returns it. Throws an exception if the repeated
+ * field is empty.
+ */
+ @JRubyMethod
+ public IRubyObject pop(ThreadContext context) {
+ IRubyObject ret = this.storage.last();
+ this.storage.remove(ret);
+ return ret;
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.replace(list)
+ *
+ * Replaces the contents of the repeated field with the given list of elements.
+ */
+ @JRubyMethod
+ public IRubyObject replace(ThreadContext context, IRubyObject list) {
+ RubyArray arr = (RubyArray) list;
+ checkArrayElementType(context, arr);
+ this.storage = arr;
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.clear
+ *
+ * Clears (removes all elements from) this repeated field.
+ */
+ @JRubyMethod
+ public IRubyObject clear(ThreadContext context) {
+ this.storage.clear();
+ return context.runtime.getNil();
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.length
+ *
+ * Returns the length of this repeated field.
+ */
+ @JRubyMethod(name = {"count", "length"})
+ public IRubyObject length(ThreadContext context) {
+ return context.runtime.newFixnum(this.storage.size());
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.+(other) => repeated field
+ *
+ * Returns a new repeated field that contains the concatenated list of this
+ * repeated field's elements and other's elements. The other (second) list may
+ * be either another repeated field or a Ruby array.
+ */
+ @JRubyMethod(name = "+")
+ public IRubyObject plus(ThreadContext context, IRubyObject list) {
+ RubyRepeatedField dup = (RubyRepeatedField) dup(context);
+ if (list instanceof RubyArray) {
+ checkArrayElementType(context, (RubyArray) list);
+ dup.storage.addAll((RubyArray) list);
+ } else {
+ RubyRepeatedField repeatedField = (RubyRepeatedField) list;
+ if (! fieldType.equals(repeatedField.fieldType) || (typeClass != null && !
+ typeClass.equals(repeatedField.typeClass)))
+ throw context.runtime.newArgumentError("Attempt to append RepeatedField with different element type.");
+ dup.storage.addAll((RubyArray) repeatedField.toArray(context));
+ }
+ return dup;
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.hash => hash_value
+ *
+ * Returns a hash value computed from this repeated field's elements.
+ */
+ @JRubyMethod
+ public IRubyObject hash(ThreadContext context) {
+ int hashCode = System.identityHashCode(this.storage);
+ return context.runtime.newFixnum(hashCode);
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.==(other) => boolean
+ *
+ * Compares this repeated field to another. Repeated fields are equal if their
+ * element types are equal, their lengths are equal, and each element is equal.
+ * Elements are compared as per normal Ruby semantics, by calling their :==
+ * methods (or performing a more efficient comparison for primitive types).
+ */
+ @JRubyMethod(name = "==")
+ public IRubyObject eq(ThreadContext context, IRubyObject other) {
+ return this.toArray(context).op_equal(context, other);
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.each(&block)
+ *
+ * Invokes the block once for each element of the repeated field. RepeatedField
+ * also includes Enumerable; combined with this method, the repeated field thus
+ * acts like an ordinary Ruby sequence.
+ */
+ @JRubyMethod
+ public IRubyObject each(ThreadContext context, Block block) {
+ this.storage.each(context, block);
+ return context.runtime.getNil();
+ }
+
+ @JRubyMethod(name = {"to_ary", "to_a"})
+ public IRubyObject toArray(ThreadContext context) {
+ for (int i = 0; i < this.storage.size(); i++) {
+ IRubyObject defaultValue = defaultValue(context);
+ if (storage.eltInternal(i).isNil()) {
+ storage.set(i, defaultValue);
+ }
+ }
+ return this.storage;
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.dup => repeated_field
+ *
+ * Duplicates this repeated field with a shallow copy. References to all
+ * non-primitive element objects (e.g., submessages) are shared.
+ */
+ @JRubyMethod
+ public IRubyObject dup(ThreadContext context) {
+ RubyRepeatedField dup = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
+ for (int i = 0; i < this.storage.size(); i++) {
+ dup.push(context, this.storage.eltInternal(i));
+ }
+ return dup;
+ }
+
+ /*
+ * call-seq:
+ * RepeatedField.inspect => string
+ *
+ * Returns a string representing this repeated field's elements. It will be
+ * formated as "[<element>, <element>, ...]", with each element's string
+ * representation computed by its own #inspect method.
+ */
+ @JRubyMethod
+ public IRubyObject inspect() {
+ StringBuilder str = new StringBuilder("[");
+ for (int i = 0; i < this.storage.size(); i++) {
+ str.append(storage.eltInternal(i).inspect());
+ str.append(", ");
+ }
+
+ if (str.length() > 1) {
+ str.replace(str.length() - 2, str.length(), "]");
+ } else {
+ str.append("]");
+ }
+
+ return getRuntime().newString(str.toString());
+ }
+
+ // Java API
+ protected IRubyObject get(int index) {
+ return this.storage.eltInternal(index);
+ }
+
+ protected RubyRepeatedField deepCopy(ThreadContext context) {
+ RubyRepeatedField copy = new RubyRepeatedField(context.runtime, metaClass, fieldType, typeClass);
+ for (int i = 0; i < size(); i++) {
+ IRubyObject value = storage.eltInternal(i);
+ if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
+ copy.storage.add(((RubyMessage) value).deepCopy(context));
+ } else {
+ copy.storage.add(value);
+ }
+ }
+ return copy;
+ }
+
+ protected int size() {
+ return this.storage.size();
+ }
+
+ private IRubyObject defaultValue(ThreadContext context) {
+ SentinelOuterClass.Sentinel sentinel = SentinelOuterClass.Sentinel.getDefaultInstance();
+ Object value;
+ switch (fieldType) {
+ case INT32:
+ value = sentinel.getDefaultInt32();
+ break;
+ case INT64:
+ value = sentinel.getDefaultInt64();
+ break;
+ case UINT32:
+ value = sentinel.getDefaultUnit32();
+ break;
+ case UINT64:
+ value = sentinel.getDefaultUint64();
+ break;
+ case FLOAT:
+ value = sentinel.getDefaultFloat();
+ break;
+ case DOUBLE:
+ value = sentinel.getDefaultDouble();
+ break;
+ case BOOL:
+ value = sentinel.getDefaultBool();
+ break;
+ case BYTES:
+ value = sentinel.getDefaultBytes();
+ break;
+ case STRING:
+ value = sentinel.getDefaultString();
+ break;
+ default:
+ return context.runtime.getNil();
+ }
+ return Utils.wrapPrimaryValue(context, fieldType, value);
+ }
+
+ private void checkArrayElementType(ThreadContext context, RubyArray arr) {
+ for (int i = 0; i < arr.getLength(); i++) {
+ Utils.checkType(context, fieldType, arr.eltInternal(i), (RubyModule) typeClass);
+ }
+ }
+
+ private RubyArray storage;
+ private Descriptors.FieldDescriptor.Type fieldType;
+ private IRubyObject typeClass;
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java b/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java
new file mode 100644
index 00000000..54f2c729
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java
@@ -0,0 +1,776 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: sentinel.proto
+
+package com.google.protobuf.jruby;
+
+public final class SentinelOuterClass {
+ private SentinelOuterClass() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ }
+ public interface SentinelOrBuilder extends
+ // @@protoc_insertion_point(interface_extends:com.google.protobuf.jruby.Sentinel)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ * <code>optional int32 default_int32 = 1;</code>
+ */
+ int getDefaultInt32();
+
+ /**
+ * <code>optional int64 default_int64 = 2;</code>
+ */
+ long getDefaultInt64();
+
+ /**
+ * <code>optional uint32 default_unit32 = 3;</code>
+ */
+ int getDefaultUnit32();
+
+ /**
+ * <code>optional uint64 default_uint64 = 4;</code>
+ */
+ long getDefaultUint64();
+
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ java.lang.String getDefaultString();
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ com.google.protobuf.ByteString
+ getDefaultStringBytes();
+
+ /**
+ * <code>optional bool default_bool = 6;</code>
+ */
+ boolean getDefaultBool();
+
+ /**
+ * <code>optional float default_float = 7;</code>
+ */
+ float getDefaultFloat();
+
+ /**
+ * <code>optional double default_double = 8;</code>
+ */
+ double getDefaultDouble();
+
+ /**
+ * <code>optional bytes default_bytes = 9;</code>
+ */
+ com.google.protobuf.ByteString getDefaultBytes();
+ }
+ /**
+ * Protobuf type {@code com.google.protobuf.jruby.Sentinel}
+ */
+ public static final class Sentinel extends
+ com.google.protobuf.GeneratedMessage implements
+ // @@protoc_insertion_point(message_implements:com.google.protobuf.jruby.Sentinel)
+ SentinelOrBuilder {
+ // Use Sentinel.newBuilder() to construct.
+ private Sentinel(com.google.protobuf.GeneratedMessage.Builder builder) {
+ super(builder);
+ }
+ private Sentinel() {
+ defaultInt32_ = 0;
+ defaultInt64_ = 0L;
+ defaultUnit32_ = 0;
+ defaultUint64_ = 0L;
+ defaultString_ = "";
+ defaultBool_ = false;
+ defaultFloat_ = 0F;
+ defaultDouble_ = 0D;
+ defaultBytes_ = com.google.protobuf.ByteString.EMPTY;
+ }
+
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class, com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class);
+ }
+
+ public static final com.google.protobuf.Parser<Sentinel> PARSER =
+ new com.google.protobuf.AbstractParser<Sentinel>() {
+ public Sentinel parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser<Sentinel> getParserForType() {
+ return PARSER;
+ }
+
+ public static final int DEFAULT_INT32_FIELD_NUMBER = 1;
+ private int defaultInt32_;
+ /**
+ * <code>optional int32 default_int32 = 1;</code>
+ */
+ public int getDefaultInt32() {
+ return defaultInt32_;
+ }
+
+ public static final int DEFAULT_INT64_FIELD_NUMBER = 2;
+ private long defaultInt64_;
+ /**
+ * <code>optional int64 default_int64 = 2;</code>
+ */
+ public long getDefaultInt64() {
+ return defaultInt64_;
+ }
+
+ public static final int DEFAULT_UNIT32_FIELD_NUMBER = 3;
+ private int defaultUnit32_;
+ /**
+ * <code>optional uint32 default_unit32 = 3;</code>
+ */
+ public int getDefaultUnit32() {
+ return defaultUnit32_;
+ }
+
+ public static final int DEFAULT_UINT64_FIELD_NUMBER = 4;
+ private long defaultUint64_;
+ /**
+ * <code>optional uint64 default_uint64 = 4;</code>
+ */
+ public long getDefaultUint64() {
+ return defaultUint64_;
+ }
+
+ public static final int DEFAULT_STRING_FIELD_NUMBER = 5;
+ private java.lang.Object defaultString_;
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ public java.lang.String getDefaultString() {
+ java.lang.Object ref = defaultString_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ defaultString_ = s;
+ }
+ return s;
+ }
+ }
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ public com.google.protobuf.ByteString
+ getDefaultStringBytes() {
+ java.lang.Object ref = defaultString_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ defaultString_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int DEFAULT_BOOL_FIELD_NUMBER = 6;
+ private boolean defaultBool_;
+ /**
+ * <code>optional bool default_bool = 6;</code>
+ */
+ public boolean getDefaultBool() {
+ return defaultBool_;
+ }
+
+ public static final int DEFAULT_FLOAT_FIELD_NUMBER = 7;
+ private float defaultFloat_;
+ /**
+ * <code>optional float default_float = 7;</code>
+ */
+ public float getDefaultFloat() {
+ return defaultFloat_;
+ }
+
+ public static final int DEFAULT_DOUBLE_FIELD_NUMBER = 8;
+ private double defaultDouble_;
+ /**
+ * <code>optional double default_double = 8;</code>
+ */
+ public double getDefaultDouble() {
+ return defaultDouble_;
+ }
+
+ public static final int DEFAULT_BYTES_FIELD_NUMBER = 9;
+ private com.google.protobuf.ByteString defaultBytes_;
+ /**
+ * <code>optional bytes default_bytes = 9;</code>
+ */
+ public com.google.protobuf.ByteString getDefaultBytes() {
+ return defaultBytes_;
+ }
+
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return new Builder(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(com.google.protobuf.jruby.SentinelOuterClass.Sentinel prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code com.google.protobuf.jruby.Sentinel}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+ // @@protoc_insertion_point(builder_implements:com.google.protobuf.jruby.Sentinel)
+ com.google.protobuf.jruby.SentinelOuterClass.SentinelOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.protobuf.jruby.SentinelOuterClass.Sentinel.class, com.google.protobuf.jruby.SentinelOuterClass.Sentinel.Builder.class);
+ }
+
+ // Construct using com.google.protobuf.jruby.SentinelOuterClass.Sentinel.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ public Builder clear() {
+ super.clear();
+ defaultInt32_ = 0;
+
+ defaultInt64_ = 0L;
+
+ defaultUnit32_ = 0;
+
+ defaultUint64_ = 0L;
+
+ defaultString_ = "";
+
+ defaultBool_ = false;
+
+ defaultFloat_ = 0F;
+
+ defaultDouble_ = 0D;
+
+ defaultBytes_ = com.google.protobuf.ByteString.EMPTY;
+
+ return this;
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return com.google.protobuf.jruby.SentinelOuterClass.internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+ }
+
+ public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() {
+ return com.google.protobuf.jruby.SentinelOuterClass.Sentinel.getDefaultInstance();
+ }
+
+ public com.google.protobuf.jruby.SentinelOuterClass.Sentinel build() {
+ com.google.protobuf.jruby.SentinelOuterClass.Sentinel result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public com.google.protobuf.jruby.SentinelOuterClass.Sentinel buildPartial() {
+ com.google.protobuf.jruby.SentinelOuterClass.Sentinel result = new com.google.protobuf.jruby.SentinelOuterClass.Sentinel(this);
+ result.defaultInt32_ = defaultInt32_;
+ result.defaultInt64_ = defaultInt64_;
+ result.defaultUnit32_ = defaultUnit32_;
+ result.defaultUint64_ = defaultUint64_;
+ result.defaultString_ = defaultString_;
+ result.defaultBool_ = defaultBool_;
+ result.defaultFloat_ = defaultFloat_;
+ result.defaultDouble_ = defaultDouble_;
+ result.defaultBytes_ = defaultBytes_;
+ onBuilt();
+ return result;
+ }
+
+
+ private int defaultInt32_ ;
+ /**
+ * <code>optional int32 default_int32 = 1;</code>
+ */
+ public int getDefaultInt32() {
+ return defaultInt32_;
+ }
+ /**
+ * <code>optional int32 default_int32 = 1;</code>
+ */
+ public Builder setDefaultInt32(int value) {
+
+ defaultInt32_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int32 default_int32 = 1;</code>
+ */
+ public Builder clearDefaultInt32() {
+
+ defaultInt32_ = 0;
+ onChanged();
+ return this;
+ }
+
+ private long defaultInt64_ ;
+ /**
+ * <code>optional int64 default_int64 = 2;</code>
+ */
+ public long getDefaultInt64() {
+ return defaultInt64_;
+ }
+ /**
+ * <code>optional int64 default_int64 = 2;</code>
+ */
+ public Builder setDefaultInt64(long value) {
+
+ defaultInt64_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional int64 default_int64 = 2;</code>
+ */
+ public Builder clearDefaultInt64() {
+
+ defaultInt64_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ private int defaultUnit32_ ;
+ /**
+ * <code>optional uint32 default_unit32 = 3;</code>
+ */
+ public int getDefaultUnit32() {
+ return defaultUnit32_;
+ }
+ /**
+ * <code>optional uint32 default_unit32 = 3;</code>
+ */
+ public Builder setDefaultUnit32(int value) {
+
+ defaultUnit32_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint32 default_unit32 = 3;</code>
+ */
+ public Builder clearDefaultUnit32() {
+
+ defaultUnit32_ = 0;
+ onChanged();
+ return this;
+ }
+
+ private long defaultUint64_ ;
+ /**
+ * <code>optional uint64 default_uint64 = 4;</code>
+ */
+ public long getDefaultUint64() {
+ return defaultUint64_;
+ }
+ /**
+ * <code>optional uint64 default_uint64 = 4;</code>
+ */
+ public Builder setDefaultUint64(long value) {
+
+ defaultUint64_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional uint64 default_uint64 = 4;</code>
+ */
+ public Builder clearDefaultUint64() {
+
+ defaultUint64_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ private java.lang.Object defaultString_ = "";
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ public java.lang.String getDefaultString() {
+ java.lang.Object ref = defaultString_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ defaultString_ = s;
+ }
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ public com.google.protobuf.ByteString
+ getDefaultStringBytes() {
+ java.lang.Object ref = defaultString_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ defaultString_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ public Builder setDefaultString(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+
+ defaultString_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ public Builder clearDefaultString() {
+
+ defaultString_ = getDefaultInstance().getDefaultString();
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional string default_string = 5;</code>
+ */
+ public Builder setDefaultStringBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+
+ defaultString_ = value;
+ onChanged();
+ return this;
+ }
+
+ private boolean defaultBool_ ;
+ /**
+ * <code>optional bool default_bool = 6;</code>
+ */
+ public boolean getDefaultBool() {
+ return defaultBool_;
+ }
+ /**
+ * <code>optional bool default_bool = 6;</code>
+ */
+ public Builder setDefaultBool(boolean value) {
+
+ defaultBool_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bool default_bool = 6;</code>
+ */
+ public Builder clearDefaultBool() {
+
+ defaultBool_ = false;
+ onChanged();
+ return this;
+ }
+
+ private float defaultFloat_ ;
+ /**
+ * <code>optional float default_float = 7;</code>
+ */
+ public float getDefaultFloat() {
+ return defaultFloat_;
+ }
+ /**
+ * <code>optional float default_float = 7;</code>
+ */
+ public Builder setDefaultFloat(float value) {
+
+ defaultFloat_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional float default_float = 7;</code>
+ */
+ public Builder clearDefaultFloat() {
+
+ defaultFloat_ = 0F;
+ onChanged();
+ return this;
+ }
+
+ private double defaultDouble_ ;
+ /**
+ * <code>optional double default_double = 8;</code>
+ */
+ public double getDefaultDouble() {
+ return defaultDouble_;
+ }
+ /**
+ * <code>optional double default_double = 8;</code>
+ */
+ public Builder setDefaultDouble(double value) {
+
+ defaultDouble_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional double default_double = 8;</code>
+ */
+ public Builder clearDefaultDouble() {
+
+ defaultDouble_ = 0D;
+ onChanged();
+ return this;
+ }
+
+ private com.google.protobuf.ByteString defaultBytes_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * <code>optional bytes default_bytes = 9;</code>
+ */
+ public com.google.protobuf.ByteString getDefaultBytes() {
+ return defaultBytes_;
+ }
+ /**
+ * <code>optional bytes default_bytes = 9;</code>
+ */
+ public Builder setDefaultBytes(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+
+ defaultBytes_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>optional bytes default_bytes = 9;</code>
+ */
+ public Builder clearDefaultBytes() {
+
+ defaultBytes_ = getDefaultInstance().getDefaultBytes();
+ onChanged();
+ return this;
+ }
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return this;
+ }
+
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return this;
+ }
+
+
+ // @@protoc_insertion_point(builder_scope:com.google.protobuf.jruby.Sentinel)
+ }
+
+ // @@protoc_insertion_point(class_scope:com.google.protobuf.jruby.Sentinel)
+ private static final com.google.protobuf.jruby.SentinelOuterClass.Sentinel defaultInstance;static {
+ defaultInstance = new com.google.protobuf.jruby.SentinelOuterClass.Sentinel();
+ }
+
+ public static com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public com.google.protobuf.jruby.SentinelOuterClass.Sentinel getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ }
+
+ private static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_com_google_protobuf_jruby_Sentinel_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\016sentinel.proto\022\031com.google.protobuf.jr" +
+ "uby\"\334\001\n\010Sentinel\022\025\n\rdefault_int32\030\001 \001(\005\022" +
+ "\025\n\rdefault_int64\030\002 \001(\003\022\026\n\016default_unit32" +
+ "\030\003 \001(\r\022\026\n\016default_uint64\030\004 \001(\004\022\026\n\016defaul" +
+ "t_string\030\005 \001(\t\022\024\n\014default_bool\030\006 \001(\010\022\025\n\r" +
+ "default_float\030\007 \001(\002\022\026\n\016default_double\030\010 " +
+ "\001(\001\022\025\n\rdefault_bytes\030\t \001(\014B\002H\002b\006proto3"
+ };
+ com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+ new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
+ public com.google.protobuf.ExtensionRegistry assignDescriptors(
+ com.google.protobuf.Descriptors.FileDescriptor root) {
+ descriptor = root;
+ return null;
+ }
+ };
+ com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ }, assigner);
+ internal_static_com_google_protobuf_jruby_Sentinel_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_com_google_protobuf_jruby_Sentinel_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_com_google_protobuf_jruby_Sentinel_descriptor,
+ new java.lang.String[] { "DefaultInt32", "DefaultInt64", "DefaultUnit32", "DefaultUint64", "DefaultString", "DefaultBool", "DefaultFloat", "DefaultDouble", "DefaultBytes", });
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/Utils.java b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
new file mode 100644
index 00000000..596a0979
--- /dev/null
+++ b/ruby/src/main/java/com/google/protobuf/jruby/Utils.java
@@ -0,0 +1,300 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.google.protobuf.jruby;
+
+import com.google.protobuf.ByteString;
+import com.google.protobuf.DescriptorProtos;
+import com.google.protobuf.Descriptors;
+import org.jcodings.Encoding;
+import org.jcodings.specific.ASCIIEncoding;
+import org.jcodings.specific.USASCIIEncoding;
+import org.jcodings.specific.UTF8Encoding;
+import org.jruby.*;
+import org.jruby.runtime.Block;
+import org.jruby.runtime.ThreadContext;
+import org.jruby.runtime.builtin.IRubyObject;
+
+import java.math.BigInteger;
+
+public class Utils {
+ public static Descriptors.FieldDescriptor.Type rubyToFieldType(IRubyObject typeClass) {
+ return Descriptors.FieldDescriptor.Type.valueOf(typeClass.asJavaString().toUpperCase());
+ }
+
+ public static IRubyObject fieldTypeToRuby(ThreadContext context, Descriptors.FieldDescriptor.Type type) {
+ return fieldTypeToRuby(context, type.name());
+ }
+
+ public static IRubyObject fieldTypeToRuby(ThreadContext context, DescriptorProtos.FieldDescriptorProto.Type type) {
+ return fieldTypeToRuby(context, type.name());
+ }
+
+ private static IRubyObject fieldTypeToRuby(ThreadContext context, String typeName) {
+
+ return context.runtime.newSymbol(typeName.replace("TYPE_", "").toLowerCase());
+ }
+
+ public static void checkType(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType,
+ IRubyObject value, RubyModule typeClass) {
+ Ruby runtime = context.runtime;
+ Object val;
+ switch(fieldType) {
+ case INT32:
+ case INT64:
+ case UINT32:
+ case UINT64:
+ if (!isRubyNum(value)) {
+ throw runtime.newTypeError("Expected number type for integral field.");
+ }
+ switch(fieldType) {
+ case INT32:
+ RubyNumeric.num2int(value);
+ break;
+ case INT64:
+ RubyNumeric.num2long(value);
+ break;
+ case UINT32:
+ num2uint(value);
+ break;
+ default:
+ num2ulong(context.runtime, value);
+ break;
+ }
+ checkIntTypePrecision(context, fieldType, value);
+ break;
+ case FLOAT:
+ if (!isRubyNum(value))
+ throw runtime.newTypeError("Expected number type for float field.");
+ break;
+ case DOUBLE:
+ if (!isRubyNum(value))
+ throw runtime.newTypeError("Expected number type for double field.");
+ break;
+ case BOOL:
+ if (!(value instanceof RubyBoolean))
+ throw runtime.newTypeError("Invalid argument for boolean field.");
+ break;
+ case BYTES:
+ case STRING:
+ validateStringEncoding(context.runtime, fieldType, value);
+ break;
+ case MESSAGE:
+ if (value.getMetaClass() != typeClass) {
+ throw runtime.newTypeError(value, typeClass);
+ }
+ break;
+ case ENUM:
+ if (value instanceof RubySymbol) {
+ Descriptors.EnumDescriptor enumDescriptor =
+ ((RubyEnumDescriptor) typeClass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR)).getDescriptor();
+ val = enumDescriptor.findValueByName(value.asJavaString());
+ if (val == null)
+ throw runtime.newRangeError("Enum value " + value + " is not found.");
+ } else if(!isRubyNum(value)) {
+ throw runtime.newTypeError("Expected number or symbol type for enum field.");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public static IRubyObject wrapPrimaryValue(ThreadContext context, Descriptors.FieldDescriptor.Type fieldType, Object value) {
+ Ruby runtime = context.runtime;
+ switch (fieldType) {
+ case INT32:
+ return runtime.newFixnum((Integer) value);
+ case INT64:
+ return runtime.newFixnum((Long) value);
+ case UINT32:
+ return runtime.newFixnum(((Integer) value) & (-1l >>> 32));
+ case UINT64:
+ long ret = (Long) value;
+ return ret >= 0 ? runtime.newFixnum(ret) :
+ RubyBignum.newBignum(runtime, UINT64_COMPLEMENTARY.add(new BigInteger(ret + "")));
+ case FLOAT:
+ return runtime.newFloat((Float) value);
+ case DOUBLE:
+ return runtime.newFloat((Double) value);
+ case BOOL:
+ return (Boolean) value ? runtime.getTrue() : runtime.getFalse();
+ case BYTES:
+ return runtime.newString(((ByteString) value).toStringUtf8());
+ case STRING:
+ return runtime.newString(value.toString());
+ default:
+ return runtime.getNil();
+ }
+ }
+
+ public static int num2uint(IRubyObject value) {
+ long longVal = RubyNumeric.num2long(value);
+ if (longVal > UINT_MAX)
+ throw value.getRuntime().newRangeError("Integer " + longVal + " too big to convert to 'unsigned int'");
+ long num = longVal;
+ if (num > Integer.MAX_VALUE || num < Integer.MIN_VALUE)
+ // encode to UINT32
+ num = (-longVal ^ (-1l >>> 32) ) + 1;
+ RubyNumeric.checkInt(value, num);
+ return (int) num;
+ }
+
+ public static long num2ulong(Ruby runtime, IRubyObject value) {
+ if (value instanceof RubyFloat) {
+ RubyBignum bignum = RubyBignum.newBignum(runtime, ((RubyFloat) value).getDoubleValue());
+ return RubyBignum.big2ulong(bignum);
+ } else if (value instanceof RubyBignum) {
+ return RubyBignum.big2ulong((RubyBignum) value);
+ } else {
+ return RubyNumeric.num2long(value);
+ }
+ }
+
+ public static void validateStringEncoding(Ruby runtime, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+ if (!(value instanceof RubyString))
+ throw runtime.newTypeError("Invalid argument for string field.");
+ Encoding encoding = ((RubyString) value).getEncoding();
+ switch(type) {
+ case BYTES:
+ if (encoding != ASCIIEncoding.INSTANCE)
+ throw runtime.newTypeError("Encoding for bytes fields" +
+ " must be \"ASCII-8BIT\", but was " + encoding);
+ break;
+ case STRING:
+ if (encoding != UTF8Encoding.INSTANCE
+ && encoding != USASCIIEncoding.INSTANCE)
+ throw runtime.newTypeError("Encoding for string fields" +
+ " must be \"UTF-8\" or \"ASCII\", but was " + encoding);
+ break;
+ default:
+ break;
+ }
+ }
+
+ public static void checkNameAvailability(ThreadContext context, String name) {
+ if (context.runtime.getObject().getConstantAt(name) != null)
+ throw context.runtime.newNameError(name + " is already defined", name);
+ }
+
+ /**
+ * Replace invalid "." in descriptor with __DOT__
+ * @param name
+ * @return
+ */
+ public static String escapeIdentifier(String name) {
+ return name.replace(".", BADNAME_REPLACEMENT);
+ }
+
+ /**
+ * Replace __DOT__ in descriptor name with "."
+ * @param name
+ * @return
+ */
+ public static String unescapeIdentifier(String name) {
+ return name.replace(BADNAME_REPLACEMENT, ".");
+ }
+
+ public static boolean isMapEntry(Descriptors.FieldDescriptor fieldDescriptor) {
+ return fieldDescriptor.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
+ fieldDescriptor.isRepeated() &&
+ fieldDescriptor.getMessageType().getOptions().getMapEntry();
+ }
+
+ public static RubyFieldDescriptor msgdefCreateField(ThreadContext context, String label, IRubyObject name,
+ IRubyObject type, IRubyObject number, IRubyObject typeClass, RubyClass cFieldDescriptor) {
+ Ruby runtime = context.runtime;
+ RubyFieldDescriptor fieldDef = (RubyFieldDescriptor) cFieldDescriptor.newInstance(context, Block.NULL_BLOCK);
+ fieldDef.setLabel(context, runtime.newString(label));
+ fieldDef.setName(context, name);
+ fieldDef.setType(context, type);
+ fieldDef.setNumber(context, number);
+
+ if (!typeClass.isNil()) {
+ if (!(typeClass instanceof RubyString)) {
+ throw runtime.newArgumentError("expected string for type class");
+ }
+ fieldDef.setSubmsgName(context, typeClass);
+ }
+ return fieldDef;
+ }
+
+ protected static void checkIntTypePrecision(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+ if (value instanceof RubyFloat) {
+ double doubleVal = RubyNumeric.num2dbl(value);
+ if (Math.floor(doubleVal) != doubleVal) {
+ throw context.runtime.newRangeError("Non-integral floating point value assigned to integer field.");
+ }
+ }
+ if (type == Descriptors.FieldDescriptor.Type.UINT32 || type == Descriptors.FieldDescriptor.Type.UINT64) {
+ if (RubyNumeric.num2dbl(value) < 0) {
+ throw context.runtime.newRangeError("Assigning negative value to unsigned integer field.");
+ }
+ }
+ }
+
+ protected static boolean isRubyNum(Object value) {
+ return value instanceof RubyFixnum || value instanceof RubyFloat || value instanceof RubyBignum;
+ }
+
+ protected static void validateTypeClass(ThreadContext context, Descriptors.FieldDescriptor.Type type, IRubyObject value) {
+ Ruby runtime = context.runtime;
+ if (!(value instanceof RubyModule)) {
+ throw runtime.newArgumentError("TypeClass has incorrect type");
+ }
+ RubyModule klass = (RubyModule) value;
+ IRubyObject descriptor = klass.getInstanceVariable(DESCRIPTOR_INSTANCE_VAR);
+ if (descriptor.isNil()) {
+ throw runtime.newArgumentError("Type class has no descriptor. Please pass a " +
+ "class or enum as returned by the DescriptorPool.");
+ }
+ if (type == Descriptors.FieldDescriptor.Type.MESSAGE) {
+ if (! (descriptor instanceof RubyDescriptor)) {
+ throw runtime.newArgumentError("Descriptor has an incorrect type");
+ }
+ } else if (type == Descriptors.FieldDescriptor.Type.ENUM) {
+ if (! (descriptor instanceof RubyEnumDescriptor)) {
+ throw runtime.newArgumentError("Descriptor has an incorrect type");
+ }
+ }
+ }
+
+ public static String BADNAME_REPLACEMENT = "__DOT__";
+
+ public static String DESCRIPTOR_INSTANCE_VAR = "@descriptor";
+
+ public static String EQUAL_SIGN = "=";
+
+ private static BigInteger UINT64_COMPLEMENTARY = new BigInteger("18446744073709551616"); //Math.pow(2, 64)
+
+ private static long UINT_MAX = 0xffffffffl;
+}
diff --git a/ruby/src/main/java/google/ProtobufJavaService.java b/ruby/src/main/java/google/ProtobufJavaService.java
new file mode 100644
index 00000000..bffb492a
--- /dev/null
+++ b/ruby/src/main/java/google/ProtobufJavaService.java
@@ -0,0 +1,60 @@
+/*
+ * Protocol Buffers - Google's data interchange format
+ * Copyright 2014 Google Inc. All rights reserved.
+ * https://developers.google.com/protocol-buffers/
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package google;
+
+import com.google.protobuf.jruby.*;
+import org.jruby.Ruby;
+import org.jruby.runtime.load.BasicLibraryService;
+
+import java.io.IOException;
+
+public class ProtobufJavaService implements BasicLibraryService {
+ @Override
+ public boolean basicLoad(Ruby ruby) throws IOException {
+ ruby.defineModule("Google");
+ RubyProtobuf.createProtobuf(ruby);
+ RubyDescriptor.createRubyDescriptor(ruby);
+ RubyBuilder.createRubyBuilder(ruby);
+ RubyFieldDescriptor.createRubyFileDescriptor(ruby);
+ RubyMessageBuilderContext.createRubyMessageBuilderContext(ruby);
+ RubyEnumDescriptor.createRubyEnumDescriptor(ruby);
+ RubyEnumBuilderContext.createRubyEnumBuilderContext(ruby);
+ RubyDescriptorPool.createRubyDescriptorPool(ruby);
+ RubyRepeatedField.createRubyRepeatedField(ruby);
+ RubyFieldDescriptor.createRubyFileDescriptor(ruby);
+ RubyMap.createRubyMap(ruby);
+ RubyOneofDescriptor.createRubyOneofDescriptor(ruby);
+ RubyOneofBuilderContext.createRubyOneofBuilderContext(ruby);
+ return true;
+ }
+}
diff --git a/ruby/src/main/sentinel.proto b/ruby/src/main/sentinel.proto
new file mode 100644
index 00000000..89a1ae19
--- /dev/null
+++ b/ruby/src/main/sentinel.proto
@@ -0,0 +1,15 @@
+syntax = "proto3";
+package com.google.protobuf.jruby;
+option optimize_for = CODE_SIZE;
+
+message Sentinel {
+ optional int32 default_int32 = 1;
+ optional int64 default_int64 = 2;
+ optional uint32 default_unit32 = 3;
+ optional uint64 default_uint64 = 4;
+ optional string default_string = 5;
+ optional bool default_bool = 6;
+ optional float default_float = 7;
+ optional double default_double = 8;
+ optional bytes default_bytes = 9;
+}
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 97d1099e..9d0f0a98 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -391,7 +391,7 @@ module BasicTest
# We only assert on inspect value when there is one map entry because the
# order in which elements appear is unspecified (depends on the internal
# hash function). We don't want a brittle test.
- assert m.inspect == "{\"jkl;\" => 42}"
+ assert m.inspect == "{\"jkl;\"=>42}"
assert m.keys == ["jkl;"]
assert m.values == [42]
@@ -972,6 +972,7 @@ module BasicTest
end
def test_json
+ skip("Unimplemented") if RUBY_PLATFORM == "java"
m = TestMessage.new(:optional_int32 => 1234,
:optional_int64 => -0x1_0000_0000,
:optional_uint32 => 0x8000_0000,
@@ -994,6 +995,7 @@ module BasicTest
end
def test_json_maps
+ skip("Unimplemented") if RUBY_PLATFORM == "java"
m = MapMessage.new(:map_string_int32 => {"a" => 1})
expected = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
assert MapMessage.encode_json(m) == expected
diff --git a/ruby/tests/generated_code.rb b/ruby/tests/generated_code.rb
index db762ad9..5a685433 100644
--- a/ruby/tests/generated_code.rb
+++ b/ruby/tests/generated_code.rb
@@ -27,16 +27,16 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
repeated :repeated_bytes, :string, 29
repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum"
repeated :repeated_msg, :message, 31, "A.B.C.TestMessage"
- repeated :map_int32_string, :message, 61, "A.B.C.TestMessage.MapInt32StringEntry"
- repeated :map_int64_string, :message, 62, "A.B.C.TestMessage.MapInt64StringEntry"
- repeated :map_uint32_string, :message, 63, "A.B.C.TestMessage.MapUint32StringEntry"
- repeated :map_uint64_string, :message, 64, "A.B.C.TestMessage.MapUint64StringEntry"
- repeated :map_bool_string, :message, 65, "A.B.C.TestMessage.MapBoolStringEntry"
- repeated :map_string_string, :message, 66, "A.B.C.TestMessage.MapStringStringEntry"
- repeated :map_string_msg, :message, 67, "A.B.C.TestMessage.MapStringMsgEntry"
- repeated :map_string_enum, :message, 68, "A.B.C.TestMessage.MapStringEnumEntry"
- repeated :map_string_int32, :message, 69, "A.B.C.TestMessage.MapStringInt32Entry"
- repeated :map_string_bool, :message, 70, "A.B.C.TestMessage.MapStringBoolEntry"
+ map :map_int32_string, :int32, :string, 61
+ map :map_int64_string, :int64, :string, 62
+ map :map_uint32_string, :uint32, :string, 63
+ map :map_uint64_string, :uint64, :string, 64
+ map :map_bool_string, :bool, :string, 65
+ map :map_string_string, :string, :string, 66
+ map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage"
+ map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum"
+ map :map_string_int32, :string, :int32, 69
+ map :map_string_bool, :string, :bool, 70
optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage"
oneof :my_oneof do
optional :oneof_int32, :int32, 41
@@ -52,46 +52,6 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
optional :oneof_msg, :message, 51, "A.B.C.TestMessage"
end
end
- add_message "A.B.C.TestMessage.MapInt32StringEntry" do
- optional :key, :int32, 1
- optional :value, :string, 2
- end
- add_message "A.B.C.TestMessage.MapInt64StringEntry" do
- optional :key, :int64, 1
- optional :value, :string, 2
- end
- add_message "A.B.C.TestMessage.MapUint32StringEntry" do
- optional :key, :uint32, 1
- optional :value, :string, 2
- end
- add_message "A.B.C.TestMessage.MapUint64StringEntry" do
- optional :key, :uint64, 1
- optional :value, :string, 2
- end
- add_message "A.B.C.TestMessage.MapBoolStringEntry" do
- optional :key, :bool, 1
- optional :value, :string, 2
- end
- add_message "A.B.C.TestMessage.MapStringStringEntry" do
- optional :key, :string, 1
- optional :value, :string, 2
- end
- add_message "A.B.C.TestMessage.MapStringMsgEntry" do
- optional :key, :string, 1
- optional :value, :message, 2, "A.B.C.TestMessage"
- end
- add_message "A.B.C.TestMessage.MapStringEnumEntry" do
- optional :key, :string, 1
- optional :value, :enum, 2, "A.B.C.TestEnum"
- end
- add_message "A.B.C.TestMessage.MapStringInt32Entry" do
- optional :key, :string, 1
- optional :value, :int32, 2
- end
- add_message "A.B.C.TestMessage.MapStringBoolEntry" do
- optional :key, :string, 1
- optional :value, :bool, 2
- end
add_message "A.B.C.TestMessage.NestedMessage" do
optional :foo, :int32, 1
end
@@ -107,16 +67,6 @@ module A
module B
module C
TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass
- TestMessage::MapInt32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt32StringEntry").msgclass
- TestMessage::MapInt64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt64StringEntry").msgclass
- TestMessage::MapUint32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint32StringEntry").msgclass
- TestMessage::MapUint64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint64StringEntry").msgclass
- TestMessage::MapBoolStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapBoolStringEntry").msgclass
- TestMessage::MapStringStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringStringEntry").msgclass
- TestMessage::MapStringMsgEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringMsgEntry").msgclass
- TestMessage::MapStringEnumEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringEnumEntry").msgclass
- TestMessage::MapStringInt32Entry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringInt32Entry").msgclass
- TestMessage::MapStringBoolEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringBoolEntry").msgclass
TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass
TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule
end
diff --git a/ruby/tests/stress.rb b/ruby/tests/stress.rb
index 1bd768ed..082d5e22 100644
--- a/ruby/tests/stress.rb
+++ b/ruby/tests/stress.rb
@@ -30,7 +30,7 @@ module StressTest
100_000.times do
mnew = TestMessage.decode(data)
mnew = mnew.dup
- assert mnew.inspect == m.inspect
+ assert_equal mnew.inspect, m.inspect
assert TestMessage.encode(mnew) == data
end
end
diff --git a/src/Makefile.am b/src/Makefile.am
index 6fd8bd2b..7811b0ae 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,12 +31,24 @@ nobase_dist_proto_DATA = google/protobuf/descriptor.proto \
clean-local:
rm -f *.loT
-CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
+public_config = google/protobuf/stubs/pbconfig.h
+
+CLEANFILES = $(protoc_outputs) $(public_config) unittest_proto_middleman \
testzip.jar testzip.list testzip.proto testzip.zip
MAINTAINERCLEANFILES = \
Makefile.in
+# Generate and distribute a minimum config.h file to make hash_map work.
+# The autoheader config has too much info, which might conflict with other
+# macros applications might include. Thus, we create a stubs/pbconfig.h, that
+# only #defines what we really need, and prefix it with GOOGLE_PROTOBUF_ to
+# avoid conflicts.
+$(public_config): $(top_builddir)/config.h $(top_srcdir)/config.h.include
+ echo "// Note: Google Protobuf internal only. Do NOT include." > $@
+ cat $(top_builddir)/config.h | grep -f $(top_srcdir)/config.h.include | \
+ sed 's,#define , #define GOOGLE_PROTOBUF_,' >> $@
+
nobase_include_HEADERS = \
google/protobuf/stubs/atomic_sequence_num.h \
google/protobuf/stubs/atomicops.h \
@@ -54,11 +66,13 @@ nobase_include_HEADERS = \
google/protobuf/stubs/atomicops_internals_x86_gcc.h \
google/protobuf/stubs/atomicops_internals_x86_msvc.h \
google/protobuf/stubs/casts.h \
- google/protobuf/stubs/singleton.h \
google/protobuf/stubs/common.h \
google/protobuf/stubs/fastmem.h \
+ google/protobuf/stubs/hash.h \
google/protobuf/stubs/once.h \
google/protobuf/stubs/platform_macros.h \
+ google/protobuf/stubs/shared_ptr.h \
+ google/protobuf/stubs/singleton.h \
google/protobuf/stubs/stl_util.h \
google/protobuf/stubs/template_util.h \
google/protobuf/stubs/type_traits.h \
@@ -70,10 +84,13 @@ nobase_include_HEADERS = \
google/protobuf/dynamic_message.h \
google/protobuf/extension_set.h \
google/protobuf/generated_enum_reflection.h \
+ google/protobuf/generated_enum_util.h \
google/protobuf/generated_message_reflection.h \
google/protobuf/generated_message_util.h \
google/protobuf/map_entry.h \
+ google/protobuf/map_entry_lite.h \
google/protobuf/map_field.h \
+ google/protobuf/map_field_lite.h \
google/protobuf/map_field_inl.h \
google/protobuf/map.h \
google/protobuf/map_type_handler.h \
@@ -111,6 +128,9 @@ nobase_include_HEADERS = \
google/protobuf/compiler/python/python_generator.h \
google/protobuf/compiler/ruby/ruby_generator.h
+nobase_nodist_include_HEADERS = \
+ $(public_config)
+
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
@@ -136,6 +156,7 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/io/coded_stream_inl.h \
google/protobuf/io/zero_copy_stream.cc \
google/protobuf/io/zero_copy_stream_impl_lite.cc
+nodist_libprotobuf_lite_la_SOURCES = $(public_config)
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
libprotobuf_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
@@ -167,6 +188,7 @@ libprotobuf_la_SOURCES = \
google/protobuf/io/zero_copy_stream_impl.cc \
google/protobuf/compiler/importer.cc \
google/protobuf/compiler/parser.cc
+nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
libprotoc_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
@@ -243,26 +265,28 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/java/java_doc_comment.cc \
google/protobuf/compiler/java/java_doc_comment.h \
google/protobuf/compiler/javanano/javanano_enum.cc \
+ google/protobuf/compiler/javanano/javanano_enum.h \
+ google/protobuf/compiler/javanano/javanano_enum_field.cc \
google/protobuf/compiler/javanano/javanano_enum_field.h \
google/protobuf/compiler/javanano/javanano_extension.cc \
+ google/protobuf/compiler/javanano/javanano_extension.h \
google/protobuf/compiler/javanano/javanano_field.cc \
+ google/protobuf/compiler/javanano/javanano_field.h \
google/protobuf/compiler/javanano/javanano_file.cc \
+ google/protobuf/compiler/javanano/javanano_file.h \
google/protobuf/compiler/javanano/javanano_generator.cc \
+ google/protobuf/compiler/javanano/javanano_generator.h \
google/protobuf/compiler/javanano/javanano_helpers.cc \
+ google/protobuf/compiler/javanano/javanano_helpers.h \
+ google/protobuf/compiler/javanano/javanano_map_field.cc \
+ google/protobuf/compiler/javanano/javanano_map_field.h \
google/protobuf/compiler/javanano/javanano_message.cc \
+ google/protobuf/compiler/javanano/javanano_message.h \
+ google/protobuf/compiler/javanano/javanano_message_field.cc \
google/protobuf/compiler/javanano/javanano_message_field.h \
google/protobuf/compiler/javanano/javanano_params.h \
- google/protobuf/compiler/javanano/javanano_primitive_field.h \
- google/protobuf/compiler/javanano/javanano_enum_field.cc \
- google/protobuf/compiler/javanano/javanano_enum.h \
- google/protobuf/compiler/javanano/javanano_extension.h \
- google/protobuf/compiler/javanano/javanano_field.h \
- google/protobuf/compiler/javanano/javanano_file.h \
- google/protobuf/compiler/javanano/javanano_generator.h \
- google/protobuf/compiler/javanano/javanano_helpers.h \
- google/protobuf/compiler/javanano/javanano_message_field.cc \
- google/protobuf/compiler/javanano/javanano_message.h \
google/protobuf/compiler/javanano/javanano_primitive_field.cc \
+ google/protobuf/compiler/javanano/javanano_primitive_field.h \
google/protobuf/compiler/python/python_generator.cc \
google/protobuf/compiler/ruby/ruby_generator.cc
@@ -295,8 +319,10 @@ protoc_inputs = \
google/protobuf/unittest_no_generic_services.proto \
google/protobuf/unittest_optimize_for.proto \
google/protobuf/unittest_preserve_unknown_enum.proto \
+ google/protobuf/unittest_preserve_unknown_enum2.proto \
google/protobuf/unittest_proto3_arena.proto \
- google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \
+ google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
EXTRA_DIST = \
$(protoc_inputs) \
@@ -305,6 +331,7 @@ EXTRA_DIST = \
google/protobuf/io/gzip_stream_unittest.sh \
google/protobuf/testdata/golden_message \
google/protobuf/testdata/golden_message_oneof_implemented \
+ google/protobuf/testdata/golden_message_proto3 \
google/protobuf/testdata/golden_packed_fields_message \
google/protobuf/testdata/bad_utf8_string \
google/protobuf/testdata/text_format_unittest_data.txt \
@@ -320,6 +347,8 @@ EXTRA_DIST = \
google/protobuf/unittest_enormous_descriptor.proto
protoc_lite_outputs = \
+ google/protobuf/map_lite_unittest.pb.cc \
+ google/protobuf/map_lite_unittest.pb.h \
google/protobuf/unittest_lite.pb.cc \
google/protobuf/unittest_lite.pb.h \
google/protobuf/unittest_import_lite.pb.cc \
@@ -329,8 +358,6 @@ protoc_lite_outputs = \
protoc_outputs = \
$(protoc_lite_outputs) \
- google/protobuf/map_lite_unittest.pb.cc \
- google/protobuf/map_lite_unittest.pb.h \
google/protobuf/map_proto2_unittest.pb.cc \
google/protobuf/map_proto2_unittest.pb.h \
google/protobuf/map_unittest.pb.cc \
@@ -367,12 +394,16 @@ protoc_outputs = \
google/protobuf/unittest_optimize_for.pb.h \
google/protobuf/unittest_preserve_unknown_enum.pb.cc \
google/protobuf/unittest_preserve_unknown_enum.pb.h \
+ google/protobuf/unittest_preserve_unknown_enum2.pb.cc \
+ google/protobuf/unittest_preserve_unknown_enum2.pb.h \
google/protobuf/unittest_proto3_arena.pb.cc \
google/protobuf/unittest_proto3_arena.pb.h \
+ google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc \
+ google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
-BUILT_SOURCES = $(protoc_outputs)
+BUILT_SOURCES = $(public_config) $(protoc_outputs)
if USE_EXTERNAL_PROTOC
@@ -394,8 +425,11 @@ endif
$(protoc_outputs): unittest_proto_middleman
COMMON_TEST_SOURCES = \
+ google/protobuf/arena_test_util.cc \
+ google/protobuf/arena_test_util.h \
google/protobuf/map_test_util.cc \
google/protobuf/map_test_util.h \
+ google/protobuf/map_test_util_impl.h \
google/protobuf/test_util.cc \
google/protobuf/test_util.h \
google/protobuf/testing/googletest.cc \
@@ -481,8 +515,12 @@ protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la
protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
protobuf_lite_test_SOURCES = \
google/protobuf/lite_unittest.cc \
+ google/protobuf/map_lite_test_util.cc \
+ google/protobuf/map_lite_test_util.h \
google/protobuf/test_util_lite.cc \
google/protobuf/test_util_lite.h
+ # TODO(teboring) add the file back and make the test build.
+ # google/protobuf/map_lite_test.cc
nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
# Test plugin binary.
diff --git a/src/google/protobuf/SEBS b/src/google/protobuf/SEBS
deleted file mode 100644
index ba33c732..00000000
--- a/src/google/protobuf/SEBS
+++ /dev/null
@@ -1,240 +0,0 @@
-# **EXPERIMENTAL**
-#
-# See http://sebs.googlecode.com
-#
-# This is an experimental build definition file using the SEBS build system.
-# I (Kenton Varda, maintainer of Protocol Buffers) happen to be the author of
-# SEBS, though SEBS is not a Google project. I'm sticking this file in
-# protobuf's SVN because that's the easiest place for me to put it, and it
-# shouldn't harm anyone. This file is not included in the distribution.
-#
-# Currently, to use this file, you must generate config.h and put it at the
-# top level of the source tree.
-
-_cpp = sebs.import_("//sebs/cpp.sebs")
-
-# ====================================================================
-# Public targets
-
-protobuf_lite = _cpp.Library(
- name = "protobuf-lite",
- srcs = [ "stubs/common.cc",
- "stubs/once.cc",
- "stubs/hash.cc",
- "stubs/hash.h",
- "stubs/map-util.h",
- "stubs/stl_util-inl.h",
- "extension_set.cc",
- "generated_message_util.cc",
- "message_lite.cc",
- "repeated_field.cc",
- "wire_format_lite.cc",
- "io/coded_stream.cc",
- "io/zero_copy_stream.cc",
- "io/zero_copy_stream_impl_lite.cc" ],
- deps = [ _cpp.SystemLibrary(name = "pthread") ])
-
-protobuf = _cpp.Library(
- name = "protobuf",
- srcs = [ "stubs/strutil.cc",
- "stubs/strutil.h",
- "stubs/substitute.cc",
- "stubs/substitute.h",
- "stubs/structurally_valid.cc",
- "descriptor.cc",
- "descriptor.pb.cc",
- "descriptor_database.cc",
- "dynamic_message.cc",
- "extension_set_heavy.cc",
- "generated_message_reflection.cc",
- "message.cc",
- "reflection_ops.cc",
- "service.cc",
- "text_format.cc",
- "unknown_field_set.cc",
- "wire_format.cc",
- "io/gzip_stream.cc",
- "io/printer.cc",
- "io/tokenizer.cc",
- "io/zero_copy_stream_impl.cc",
- "compiler/importer.cc",
- "compiler/parser.cc" ],
- deps = [ protobuf_lite,
- _cpp.SystemLibrary(name = "z") ])
-
-libprotoc = _cpp.Library(
- name = "protoc",
- srcs = [ "compiler/code_generator.cc",
- "compiler/command_line_interface.cc",
- "compiler/cpp/cpp_enum.cc",
- "compiler/cpp/cpp_enum.h",
- "compiler/cpp/cpp_enum_field.cc",
- "compiler/cpp/cpp_enum_field.h",
- "compiler/cpp/cpp_extension.cc",
- "compiler/cpp/cpp_extension.h",
- "compiler/cpp/cpp_field.cc",
- "compiler/cpp/cpp_field.h",
- "compiler/cpp/cpp_file.cc",
- "compiler/cpp/cpp_file.h",
- "compiler/cpp/cpp_generator.cc",
- "compiler/cpp/cpp_helpers.cc",
- "compiler/cpp/cpp_helpers.h",
- "compiler/cpp/cpp_message.cc",
- "compiler/cpp/cpp_message.h",
- "compiler/cpp/cpp_message_field.cc",
- "compiler/cpp/cpp_message_field.h",
- "compiler/cpp/cpp_primitive_field.cc",
- "compiler/cpp/cpp_primitive_field.h",
- "compiler/cpp/cpp_service.cc",
- "compiler/cpp/cpp_service.h",
- "compiler/cpp/cpp_string_field.cc",
- "compiler/cpp/cpp_string_field.h",
- "compiler/java/java_enum.cc",
- "compiler/java/java_enum.h",
- "compiler/java/java_enum_field.cc",
- "compiler/java/java_enum_field.h",
- "compiler/java/java_extension.cc",
- "compiler/java/java_extension.h",
- "compiler/java/java_field.cc",
- "compiler/java/java_field.h",
- "compiler/java/java_file.cc",
- "compiler/java/java_file.h",
- "compiler/java/java_generator.cc",
- "compiler/java/java_helpers.cc",
- "compiler/java/java_helpers.h",
- "compiler/java/java_message.cc",
- "compiler/java/java_message.h",
- "compiler/java/java_message_field.cc",
- "compiler/java/java_message_field.h",
- "compiler/java/java_primitive_field.cc",
- "compiler/java/java_primitive_field.h",
- "compiler/java/java_service.cc",
- "compiler/java/java_service.h",
- "compiler/python/python_generator.cc" ],
- deps = [ protobuf ])
-
-protoc = _cpp.Binary(
- name = "protoc",
- srcs = [ "compiler/main.cc" ],
- deps = [ libprotoc ])
-
-# ====================================================================
-# ProtobufLibrary rule class
-
-class ProtobufLibrary(sebs.Rule):
- argument_spec = sebs.ArgumentSpec(srcs = [sebs.Artifact],
- deps = ([sebs.Rule], []),
- lite = (bool, False))
-
- def _expand(self, args):
- for dep in args.deps:
- if not isinstance(dep, ProtobufLibrary):
- raise sebs.DefinitionError(
- "Dependency of ProtobufLibrary is not a ProtobufLibrary: %s" % dep)
-
- protoc.expand_once()
-
- # We must build protoc for the host configuration to allow cross-compiling.
- host_protoc = self.context.configured_artifact(protoc.binary, "host")
-
- protoc_action = self.context.action(self, "protobuf")
- protoc_args = [host_protoc, "-Isrc", "-Itmp", "-Iinclude","--cpp_out=tmp"]
-
- cpp_srcs = []
- for src in args.srcs:
- protoc_args.append(src)
-
- # We cannot build .proto files from other packages because the .pb.cc
- # and .pb.h files would be written to that package, and we aren't allowed
- # to write to other packages.
- if self.context.local_filename(src) is None:
- raise sebs.DefinitionError(
- "Source file is not in this package: %s" % src)
-
- cc_artifact = self.context.derived_artifact(src, ".pb.cc", protoc_action)
- header_artifact = self.context.derived_artifact(
- src, ".pb.h", protoc_action)
-
- cpp_srcs.append(cc_artifact)
- cpp_srcs.append(header_artifact)
-
- protoc_action.set_command(
- sebs.SubprocessCommand(protoc_action, protoc_args, implicit = cpp_srcs))
-
- deps = list(args.deps)
- if args.lite:
- deps.append(protobuf_lite)
- else:
- deps.append(protobuf)
-
- self.__cpp_library = _cpp.Library(srcs = cpp_srcs, deps = deps,
- context = self.context)
- self.__cpp_library.label = self.label
- self.outputs = []
-
- def as_cpp_library(self):
- self.expand_once()
- return self.__cpp_library
-
-# ====================================================================
-# Tests
-
-_lite_test_protos = ProtobufLibrary(
- srcs = [ "unittest_lite.proto",
- "unittest_import_lite.proto" ],
- lite = True)
-_test_protos = ProtobufLibrary(
- srcs = [ "unittest.proto",
- "unittest_empty.proto",
- "unittest_import.proto",
- "unittest_mset.proto",
- "unittest_optimize_for.proto",
- "unittest_embed_optimize_for.proto",
- "unittest_custom_options.proto",
- "unittest_lite_imports_nonlite.proto",
- "compiler/cpp/cpp_test_bad_identifiers.proto" ],
- deps = [ _lite_test_protos ])
-
-_test_util = _cpp.Library(
- name = "test_util",
- srcs = [ "test_util.cc",
- "test_util.h",
- "testing/googletest.cc",
- "testing/googletest.h",
- "testing/file.cc",
- "testing/file.h" ],
- deps = [ protobuf, _test_protos, _cpp.SystemLibrary(name = "gtest")] )
-
-protobuf_lite_test = _cpp.Test(
- srcs = [ "lite_unittest.cc",
- "test_util_lite.cc",
- "test_util_lite.h" ],
- deps = [ _lite_test_protos ])
-
-protobuf_test = _cpp.Test(
- srcs = [ "stubs/common_unittest.cc",
- "stubs/once_unittest.cc",
- "stubs/strutil_unittest.cc",
- "stubs/structurally_valid_unittest.cc",
- "descriptor_database_unittest.cc",
- "descriptor_unittest.cc",
- "dynamic_message_unittest.cc",
- "extension_set_unittest.cc",
- "generated_message_reflection_unittest.cc",
- "message_unittest.cc",
- "reflection_ops_unittest.cc",
- "repeated_field_unittest.cc",
- "text_format_unittest.cc",
- "unknown_field_set_unittest.cc",
- "wire_format_unittest.cc",
- "io/coded_stream_unittest.cc",
- "io/printer_unittest.cc",
- "io/tokenizer_unittest.cc",
- "io/zero_copy_stream_unittest.cc",
- "compiler/command_line_interface_unittest.cc",
- "compiler/importer_unittest.cc",
- "compiler/parser_unittest.cc",
- "compiler/cpp/cpp_bootstrap_unittest.cc",
- "compiler/cpp/cpp_unittest.cc" ],
- deps = [ protobuf, libprotoc, _test_util,
- _cpp.SystemLibrary(name = "gtest_main") ])
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
new file mode 100644
index 00000000..bf2aa0a9
--- /dev/null
+++ b/src/google/protobuf/any.proto
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "AnyProto";
+option java_package = "com.google.protobuf";
+
+
+// `Any` contains an arbitrary serialized message along with a URL
+// that describes the type of the serialized message.
+//
+//
+//
+// # JSON
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": <string>,
+// "lastName": <string>
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the the `@type`
+// field. Example (for message [google.protobuf.Duration][google.protobuf.Duration]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+message Any {
+ // A URL/resource name whose content describes the type of the
+ // serialized message.
+ //
+ // For URLs which use the schema `http`, `https`, or no schema, the
+ // following restrictions and interpretations apply:
+ //
+ // * If no schema is provided, https is assumed.
+ // * The last segment of the URL's path must represent the fully
+ // qualified name of the type (as in `path/google.protobuf.Duration`).
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility need to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Schemas other than `http`, `https` (or the empty schema) might be
+ // used with implementation specific semantics.
+ //
+ //
+ string type_url = 1;
+
+ // Must be valid serialized data of the above specified type.
+ bytes value = 2;
+}
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 18536781..bda37413 100644..100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -47,35 +47,53 @@ Arena::ThreadCache& Arena::thread_cache() {
GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
#endif
-void Arena::Init(const ArenaOptions& options) {
+void Arena::Init() {
lifecycle_id_ = lifecycle_id_generator_.GetNext();
- start_block_size_ = options.start_block_size;
- max_block_size_ = options.max_block_size;
- block_alloc = options.block_alloc;
- block_dealloc = options.block_dealloc;
blocks_ = 0;
hint_ = 0;
owns_first_block_ = true;
cleanup_list_ = 0;
- if (options.initial_block != NULL && options.initial_block_size > 0) {
+ if (options_.initial_block != NULL && options_.initial_block_size > 0) {
// Add first unowned block to list.
- Block* first_block = reinterpret_cast<Block*>(options.initial_block);
- first_block->size = options.initial_block_size;
+ Block* first_block = reinterpret_cast<Block*>(options_.initial_block);
+ first_block->size = options_.initial_block_size;
first_block->pos = kHeaderSize;
first_block->next = NULL;
first_block->owner = &first_block->owner;
AddBlock(first_block);
owns_first_block_ = false;
}
+
+ // Call the initialization hook
+ if (options_.on_arena_init != NULL) {
+ hooks_cookie_ = options_.on_arena_init(this);
+ } else {
+ hooks_cookie_ = NULL;
+ }
+}
+
+Arena::~Arena() {
+ uint64 space_allocated = Reset();
+
+ // Call the destruction hook
+ if (options_.on_arena_destruction != NULL) {
+ options_.on_arena_destruction(this, hooks_cookie_, space_allocated);
+ }
}
uint64 Arena::Reset() {
CleanupList();
- uint64 space_used = FreeBlocks();
+ uint64 space_allocated = FreeBlocks();
// Invalidate any ThreadCaches pointing to any blocks we just destroyed.
lifecycle_id_ = lifecycle_id_generator_.GetNext();
- return space_used;
+
+ // Call the reset hook
+ if (options_.on_arena_reset != NULL) {
+ options_.on_arena_reset(this, hooks_cookie_, space_allocated);
+ }
+
+ return space_allocated;
}
Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
@@ -93,7 +111,7 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
size = kHeaderSize + n;
}
- Block* b = reinterpret_cast<Block*>(block_alloc(size));
+ Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
b->pos = kHeaderSize + n;
b->size = size;
if (b->avail() == 0) {
@@ -184,7 +202,7 @@ void* Arena::SlowAlloc(size_t n) {
google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
return AllocFromBlock(b, n);
}
- b = NewBlock(me, b, n, start_block_size_, max_block_size_);
+ b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size);
AddBlock(b);
if (b->owner == me) { // If this block can be reused (see NewBlock()).
SetThreadCacheBlock(b);
@@ -192,29 +210,38 @@ void* Arena::SlowAlloc(size_t n) {
return reinterpret_cast<char*>(b) + kHeaderSize;
}
+uint64 Arena::SpaceAllocated() const {
+ uint64 space_allocated = 0;
+ Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+ while (b != NULL) {
+ space_allocated += (b->size);
+ b = b->next;
+ }
+ return space_allocated;
+}
+
uint64 Arena::SpaceUsed() const {
uint64 space_used = 0;
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
while (b != NULL) {
- space_used += (b->size);
+ space_used += (b->pos - kHeaderSize);
b = b->next;
}
return space_used;
}
-
uint64 Arena::FreeBlocks() {
- uint64 space_used = 0;
+ uint64 space_allocated = 0;
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
Block* first_block = NULL;
while (b != NULL) {
- space_used += (b->size);
+ space_allocated += (b->size);
Block* next = b->next;
if (next != NULL) {
- block_dealloc(b, b->size);
+ options_.block_dealloc(b, b->size);
} else {
if (owns_first_block_) {
- block_dealloc(b, b->size);
+ options_.block_dealloc(b, b->size);
} else {
// User passed in the first block, skip free'ing the memory.
first_block = b;
@@ -231,7 +258,7 @@ uint64 Arena::FreeBlocks() {
first_block->owner = &first_block->owner;
AddBlock(first_block);
}
- return space_used;
+ return space_allocated;
}
void Arena::CleanupList() {
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index d0cb163c..bb15e80c 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -34,9 +34,11 @@
#ifndef GOOGLE_PROTOBUF_ARENA_H__
#define GOOGLE_PROTOBUF_ARENA_H__
-#include <google/protobuf/stubs/common.h>
+#include <typeinfo>
+
#include <google/protobuf/stubs/atomic_sequence_num.h>
#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/type_traits.h>
namespace google {
@@ -89,19 +91,44 @@ struct ArenaOptions {
// A function pointer to an alloc method that returns memory blocks of size
// requested. By default, it contains a ptr to the malloc function.
+ //
+ // NOTE: block_alloc and dealloc functions are expected to behave like
+ // malloc and free, including Asan poisoning.
void* (*block_alloc)(size_t);
// A function pointer to a dealloc method that takes ownership of the blocks
// from the arena. By default, it contains a ptr to a wrapper function that
// calls free.
void (*block_dealloc)(void*, size_t);
+ // Hooks for adding external functionality such as user-specific metrics
+ // collection, specific debugging abilities, etc.
+ // Init hook may return a pointer to a cookie to be stored in the arena.
+ // reset and destruction hooks will then be called with the same cookie
+ // pointer. This allows us to save an external object per arena instance and
+ // use it on the other hooks (Note: It is just as legal for init to return
+ // NULL and not use the cookie feature).
+ // on_arena_reset and on_arena_destruction also receive the space used in
+ // the arena just before the reset.
+ void* (*on_arena_init)(Arena* arena);
+ 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);
+
ArenaOptions()
: start_block_size(kDefaultStartBlockSize),
max_block_size(kDefaultMaxBlockSize),
initial_block(NULL),
initial_block_size(0),
block_alloc(&malloc),
- block_dealloc(&internal::arena_free) {}
+ block_dealloc(&internal::arena_free),
+ on_arena_init(NULL),
+ on_arena_reset(NULL),
+ on_arena_destruction(NULL),
+ on_arena_allocation(NULL) {}
private:
// Constants define default starting block size and max block size for
@@ -123,23 +150,21 @@ class LIBPROTOBUF_EXPORT Arena {
public:
// Arena constructor taking custom options. See ArenaOptions below for
// descriptions of the options available.
- explicit Arena(const ArenaOptions& options) {
- Init(options);
+ explicit Arena(const ArenaOptions& options) : options_(options) {
+ Init();
}
// Default constructor with sensible default options, tuned for average
// use-cases.
Arena() {
- Init(ArenaOptions());
+ Init();
}
// Destructor deletes all owned heap allocated objects, and destructs objects
// that have non-trivial destructors, except for proto2 message objects whose
// destructors can be skipped. Also, frees all blocks except the initial block
// if it was passed in.
- ~Arena() {
- Reset();
- }
+ ~Arena();
// API to create proto2 message objects on the arena. If the arena passed in
// is NULL, then a heap allocated object is returned. Type T must be a message
@@ -195,6 +220,40 @@ class LIBPROTOBUF_EXPORT Arena {
}
}
+ // Version of the above with three constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3) {
+ if (arena == NULL) {
+ return new T(arg1, arg2, arg3);
+ } else {
+ return arena->CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)),
+ arg1,
+ arg2,
+ arg3);
+ }
+ }
+
+ // Version of the above with four constructor arguments for the created
+ // object.
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena,
+ const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4) {
+ 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);
+ }
+ }
+
// Create an array of object type T on the arena. Type T must have a trivial
// constructor, as it will not be invoked when created on the arena.
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
@@ -202,8 +261,7 @@ class LIBPROTOBUF_EXPORT Arena {
if (arena == NULL) {
return new T[num_elements];
} else {
- return static_cast<T*>(
- arena->AllocateAligned(num_elements * sizeof(T)));
+ return arena->CreateInternalRawArray<T>(num_elements);
}
}
@@ -211,6 +269,8 @@ class LIBPROTOBUF_EXPORT Arena {
// of the underlying blocks. The total space used may not include the new
// blocks that are allocated by this arena from other threads concurrently
// with the call to this method.
+ uint64 SpaceAllocated() const GOOGLE_ATTRIBUTE_NOINLINE;
+ // As above, but does not include any free space in underlying blocks.
uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE;
// Frees all storage allocated by this arena after calling destructors
@@ -253,7 +313,7 @@ class LIBPROTOBUF_EXPORT Arena {
// latter is a virtual call, while this method is a templated call that
// resolves at compile-time.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArena(T* value) {
+ static inline ::google::protobuf::Arena* GetArena(const T* value) {
return GetArenaInternal(value, static_cast<T*>(0));
}
@@ -295,9 +355,6 @@ class LIBPROTOBUF_EXPORT Arena {
// data follows
};
- void* (*block_alloc)(size_t); // Allocates a free block of a particular size.
- void (*block_dealloc)(void*, size_t); // Deallocates the given block.
-
template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
friend class MockArena; // For unit-testing.
friend class internal::ArenaString; // For AllocateAligned.
@@ -313,6 +370,8 @@ class LIBPROTOBUF_EXPORT Arena {
static const size_t kHeaderSize = sizeof(Block);
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
#ifdef PROTOBUF_USE_DLLS
+ // Thread local variables cannot be exposed through DLL interface but we can
+ // wrap them in static functions.
static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
@@ -352,6 +411,13 @@ class LIBPROTOBUF_EXPORT Arena {
return Create<T>(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));
+ }
+
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
inline T* CreateInternal(
bool skip_explicit_ownership) {
@@ -382,12 +448,57 @@ class LIBPROTOBUF_EXPORT Arena {
return t;
}
+ template <typename T, typename Arg1, typename Arg2, typename Arg3>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3) {
+ T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
+ template <typename T, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4) {
+ T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3, arg4);
+ if (!skip_explicit_ownership) {
+ AddListNode(t, &internal::arena_destruct_object<T>);
+ }
+ return t;
+ }
+
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
this);
}
+ // 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.
+ template <typename T>
+ static void CreateInArenaStorage(T* ptr, Arena* arena) {
+ CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value);
+ }
+ template <typename T>
+ static void CreateInArenaStorageInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::true_type) {
+ new (ptr) T(arena);
+ }
+
+ template <typename T>
+ static void CreateInArenaStorageInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::false_type) {
+ new (ptr) T;
+ }
+
// These implement Own(), which registers an object for deletion (destructor
// call and operator delete()). The second parameter has type 'true_type' if T
// is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing
@@ -410,20 +521,20 @@ class LIBPROTOBUF_EXPORT Arena {
// InternalArenaConstructable_ tags can be associated with an arena, and such
// objects must implement a GetArenaNoVirtual() method.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArenaInternal(T* value,
+ static inline ::google::protobuf::Arena* GetArenaInternal(const T* value,
typename T::InternalArenaConstructable_*) {
return value->GetArenaNoVirtual();
}
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- static inline ::google::protobuf::Arena* GetArenaInternal(T* value, ...) {
+ static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
return NULL;
}
void* AllocateAligned(size_t size);
- void Init(const ArenaOptions& options);
+ void Init();
// Free all blocks and return the total space used which is the sums of sizes
// of the all the allocated blocks.
@@ -444,8 +555,6 @@ class LIBPROTOBUF_EXPORT Arena {
}
int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
- size_t start_block_size_; // Starting block size of the arena.
- size_t max_block_size_; // Max block size of the arena.
google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks
google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access
@@ -470,6 +579,15 @@ class LIBPROTOBUF_EXPORT Arena {
Block* NewBlock(void* me, Block* my_last_block, size_t n,
size_t start_block_size, size_t max_block_size);
static void* AllocFromBlock(Block* b, size_t n);
+ template <typename Key, typename T>
+ friend class Map;
+
+ // The arena may save a cookie it receives from the external on_init hook
+ // and then use it when calling the on_reset and on_destruction hooks.
+ void* hooks_cookie_;
+
+ ArenaOptions options_;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
};
diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc
new file mode 100644
index 00000000..21f55c6e
--- /dev/null
+++ b/src/google/protobuf/arena_test_util.cc
@@ -0,0 +1,49 @@
+// 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/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
+
+
+#define EXPECT_EQ GOOGLE_CHECK_EQ
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+NoHeapChecker::~NoHeapChecker() {
+ capture_alloc.Unhook();
+ EXPECT_EQ(0, capture_alloc.alloc_count());
+ EXPECT_EQ(0, capture_alloc.free_count());
+}
+
+} // namespace internal
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
new file mode 100644
index 00000000..7db7a90e
--- /dev/null
+++ b/src/google/protobuf/arena_test_util.h
@@ -0,0 +1,59 @@
+// 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_ARENA_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+class NoHeapChecker {
+ public:
+ NoHeapChecker() {
+ capture_alloc.Hook();
+ }
+ ~NoHeapChecker();
+ private:
+ class NewDeleteCapture {
+ public:
+ // TOOD(xiaofeng): Implement this for opensource protobuf.
+ void Hook() {}
+ void Unhook() {}
+ int alloc_count() { return 0; }
+ int free_count() { return 0; }
+ } capture_alloc;
+};
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 9d3d3e3e..d9b198e0 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -30,6 +30,8 @@
#include <google/protobuf/arena.h>
+#include <stdint.h>
+
#include <algorithm>
#include <cstring>
#include <memory>
@@ -40,6 +42,7 @@
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_arena.pb.h>
@@ -91,6 +94,37 @@ class SimpleDataType {
private:
Notifier* notifier_;
};
+
+// A simple class that does not allow copying and so cannot be used as a
+// parameter type without "const &".
+class PleaseDontCopyMe {
+ public:
+ explicit PleaseDontCopyMe(int value) : value_(value) {}
+
+ int value() const { return value_; }
+
+ private:
+ int value_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe);
+};
+
+// A class that takes four different types as constructor arguments.
+class MustBeConstructedWithOneThroughFour {
+ public:
+ MustBeConstructedWithOneThroughFour(
+ int one, const char* two, const string& three,
+ const PleaseDontCopyMe* four)
+ : one_(one), two_(two), three_(three), four_(four) {}
+
+ int one_;
+ const char* const two_;
+ string three_;
+ const PleaseDontCopyMe* four_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour);
+};
+
} // namespace
TEST(ArenaTest, ArenaConstructable) {
@@ -122,6 +156,20 @@ TEST(ArenaTest, BasicCreate) {
EXPECT_EQ(2, notifier.GetCount());
}
+TEST(ArenaTest, CreateWithManyConstructorArguments) {
+ Arena arena;
+ const string three("3");
+ const PleaseDontCopyMe four(4);
+ const MustBeConstructedWithOneThroughFour* new_object =
+ Arena::Create<MustBeConstructedWithOneThroughFour>(
+ &arena, 1, "2", three, &four);
+ 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());
+}
+
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
@@ -380,6 +428,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) {
delete nested_string;
}
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
TestAllTypes::NestedMessage* nested_msg = NULL;
// Note: no string: reflection API only supports releasing submessages.
@@ -390,12 +439,13 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
const Reflection* r = arena_message->GetReflection();
const FieldDescriptor* f = arena_message->GetDescriptor()->FindFieldByName(
"optional_nested_message");
- nested_msg = dynamic_cast<TestAllTypes::NestedMessage*>(
+ nested_msg = static_cast<TestAllTypes::NestedMessage*>(
r->ReleaseMessage(arena_message, f));
}
EXPECT_EQ(42, nested_msg->bb());
delete nested_msg;
}
+#endif // !GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) {
Arena arena;
@@ -671,6 +721,57 @@ TEST(ArenaTest, UnsafeArenaAddAllocated) {
}
}
+TEST(ArenaTest, UnsafeArenaRelease) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+
+ string* s = new string("test string");
+ message->unsafe_arena_set_allocated_optional_string(s);
+ EXPECT_TRUE(message->has_optional_string());
+ EXPECT_EQ("test string", message->optional_string());
+ s = message->unsafe_arena_release_optional_string();
+ EXPECT_FALSE(message->has_optional_string());
+ delete s;
+
+ s = new string("test string");
+ message->unsafe_arena_set_allocated_oneof_string(s);
+ EXPECT_TRUE(message->has_oneof_string());
+ EXPECT_EQ("test string", message->oneof_string());
+ s = message->unsafe_arena_release_oneof_string();
+ EXPECT_FALSE(message->has_oneof_string());
+ delete s;
+}
+
+TEST(ArenaTest, ArenaOneofReflection) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ const Descriptor* desc = message->GetDescriptor();
+ const Reflection* refl = message->GetReflection();
+
+ const FieldDescriptor* string_field = desc->FindFieldByName(
+ "oneof_string");
+ const FieldDescriptor* msg_field = desc->FindFieldByName(
+ "oneof_nested_message");
+ const OneofDescriptor* oneof = desc->FindOneofByName(
+ "oneof_field");
+
+ refl->SetString(message, string_field, "Test value");
+ EXPECT_TRUE(refl->HasOneof(*message, oneof));
+ refl->ClearOneof(message, oneof);
+ EXPECT_FALSE(refl->HasOneof(*message, oneof));
+
+ Message* submsg = refl->MutableMessage(message, msg_field);
+ EXPECT_TRUE(refl->HasOneof(*message, oneof));
+ refl->ClearOneof(message, oneof);
+ EXPECT_FALSE(refl->HasOneof(*message, oneof));
+ refl->MutableMessage(message, msg_field);
+ EXPECT_TRUE(refl->HasOneof(*message, oneof));
+ submsg = refl->ReleaseMessage(message, msg_field);
+ EXPECT_FALSE(refl->HasOneof(*message, oneof));
+ EXPECT_TRUE(submsg->GetArena() == NULL);
+ delete submsg;
+}
+
namespace {
void TestSwapRepeatedField(Arena* arena1, Arena* arena2) {
// Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField
@@ -746,27 +847,6 @@ TEST(ArenaTest, ExtensionsOnArena) {
protobuf_unittest::optional_nested_message_extension)->set_bb(42);
}
-class NoHeapChecker {
- public:
- NoHeapChecker() {
- capture_alloc.Hook();
- }
- ~NoHeapChecker() {
- capture_alloc.Unhook();
- EXPECT_EQ(0, capture_alloc.alloc_count());
- EXPECT_EQ(0, capture_alloc.free_count());
- }
- private:
- class NewDeleteCapture {
- public:
- // TOOD(xiaofeng): Implement this for opensource protobuf.
- void Hook() {}
- void Unhook() {}
- int alloc_count() { return 0; }
- int free_count() { return 0; }
- } capture_alloc;
-};
-
TEST(ArenaTest, RepeatedFieldOnArena) {
// Preallocate an initial arena block to avoid mallocs during hooked region.
std::vector<char> arena_block(1024 * 1024);
@@ -776,7 +856,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) {
Arena arena(options);
{
- NoHeapChecker no_heap;
+ internal::NoHeapChecker no_heap;
// Fill some repeated fields on the arena to test for leaks. Also verify no
// memory allocations.
@@ -846,6 +926,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) {
}
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
TEST(ArenaTest, MutableMessageReflection) {
Arena arena;
TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -853,7 +934,7 @@ TEST(ArenaTest, MutableMessageReflection) {
const Descriptor* d = message->GetDescriptor();
const FieldDescriptor* field = d->FindFieldByName("optional_nested_message");
TestAllTypes::NestedMessage* submessage =
- dynamic_cast<TestAllTypes::NestedMessage*>(
+ static_cast<TestAllTypes::NestedMessage*>(
r->MutableMessage(message, field));
TestAllTypes::NestedMessage* submessage_expected =
message->mutable_optional_nested_message();
@@ -862,13 +943,14 @@ TEST(ArenaTest, MutableMessageReflection) {
EXPECT_EQ(&arena, submessage->GetArena());
const FieldDescriptor* oneof_field = d->FindFieldByName("oneof_nested_message");
- submessage = dynamic_cast<TestAllTypes::NestedMessage*>(
+ submessage = static_cast<TestAllTypes::NestedMessage*>(
r->MutableMessage(message, oneof_field));
submessage_expected = message->mutable_oneof_nested_message();
EXPECT_EQ(submessage_expected, submessage);
EXPECT_EQ(&arena, submessage->GetArena());
}
+#endif // !GOOGLE_PROTOBUF_NO_RTTI
namespace {
@@ -911,7 +993,7 @@ TEST(ArenaTest, NoHeapAllocationsTest) {
arena.Reset();
}
-
+#ifndef GOOGLE_PROTOBUF_NO_RTTI
// Test construction on an arena via generic MessageLite interface. We should be
// able to successfully deserialize on the arena without incurring heap
// allocations, i.e., everything should still be arena-allocation-aware.
@@ -921,8 +1003,7 @@ TEST(ArenaTest, MessageLiteOnArena) {
options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena(options);
- const google::protobuf::MessageLite* prototype = dynamic_cast<
- const google::protobuf::MessageLite*>(&TestAllTypes::default_instance());
+ const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance();
TestAllTypes initial_message;
FillArenaAwareFields(&initial_message);
@@ -935,13 +1016,13 @@ TEST(ArenaTest, MessageLiteOnArena) {
EXPECT_TRUE(generic_message != NULL);
EXPECT_EQ(&arena, generic_message->GetArena());
EXPECT_TRUE(generic_message->ParseFromString(serialized));
- TestAllTypes* deserialized = dynamic_cast<TestAllTypes*>(generic_message);
- EXPECT_TRUE(deserialized != NULL);
+ TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message);
EXPECT_EQ(42, deserialized->optional_int32());
}
arena.Reset();
}
+#endif // !GOOGLE_PROTOBUF_NO_RTTI
// RepeatedField should support non-POD types, and invoke constructors and
@@ -963,16 +1044,23 @@ TEST(ArenaTest, RepeatedFieldWithNonPODType) {
}
}
-TEST(ArenaTest, SpaceUsed) {
+// Align n to next multiple of 8
+namespace {
+uint64 Align8(uint64 n) { return (n + 7) & -8; }
+} // namespace
+
+TEST(ArenaTest, SpaceAllocated_and_Used) {
ArenaOptions options;
options.start_block_size = 256;
options.max_block_size = 8192;
Arena arena_1(options);
+ EXPECT_EQ(0, arena_1.SpaceAllocated());
EXPECT_EQ(0, arena_1.SpaceUsed());
EXPECT_EQ(0, arena_1.Reset());
::google::protobuf::Arena::CreateArray<char>(&arena_1, 320);
// Arena will allocate slightly more than 320 for the block headers.
- EXPECT_LE(320, arena_1.SpaceUsed());
+ EXPECT_LE(320, arena_1.SpaceAllocated());
+ EXPECT_EQ(Align8(320), arena_1.SpaceUsed());
EXPECT_LE(320, arena_1.Reset());
// Test with initial block.
@@ -980,20 +1068,25 @@ TEST(ArenaTest, SpaceUsed) {
options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena_2(options);
- EXPECT_EQ(1024, arena_2.SpaceUsed());
+ EXPECT_EQ(1024, arena_2.SpaceAllocated());
+ EXPECT_EQ(0, arena_2.SpaceUsed());
EXPECT_EQ(1024, arena_2.Reset());
::google::protobuf::Arena::CreateArray<char>(&arena_2, 55);
- EXPECT_EQ(1024, arena_2.SpaceUsed());
+ EXPECT_EQ(1024, arena_2.SpaceAllocated());
+ EXPECT_EQ(Align8(55), arena_2.SpaceUsed());
EXPECT_EQ(1024, arena_2.Reset());
// Reset options to test doubling policy explicitly.
options.initial_block = NULL;
options.initial_block_size = 0;
Arena arena_3(options);
+ EXPECT_EQ(0, arena_3.SpaceUsed());
::google::protobuf::Arena::CreateArray<char>(&arena_3, 190);
- EXPECT_EQ(256, arena_3.SpaceUsed());
+ EXPECT_EQ(256, arena_3.SpaceAllocated());
+ EXPECT_EQ(Align8(190), arena_3.SpaceUsed());
::google::protobuf::Arena::CreateArray<char>(&arena_3, 70);
- EXPECT_EQ(256 + 512, arena_3.SpaceUsed());
+ EXPECT_EQ(256 + 512, arena_3.SpaceAllocated());
+ EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed());
EXPECT_EQ(256 + 512, arena_3.Reset());
}
@@ -1005,5 +1098,76 @@ TEST(ArenaTest, Alignment) {
}
}
+TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) {
+ ::google::protobuf::Arena arena;
+ ArenaMessage* message = Arena::CreateMessage<ArenaMessage>(&arena);
+ const ArenaMessage* const_pointer_to_message = message;
+ EXPECT_EQ(&arena, Arena::GetArena(message));
+ EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message));
+}
+
+TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
+ ArenaMessage message;
+ const ArenaMessage* const_pointer_to_message = &message;
+ EXPECT_EQ(NULL, Arena::GetArena(&message));
+ EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
+}
+
+// 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.
+class ArenaHooksTestUtil {
+ public:
+ static void* on_init(::google::protobuf::Arena* arena) {
+ ++num_init;
+ int* cookie = new int(kCookieValue);
+ return static_cast<void*>(cookie);
+ }
+
+ static void on_reset(::google::protobuf::Arena* arena, void* cookie,
+ uint64 space_used) {
+ ++num_reset;
+ int cookie_value = *static_cast<int*>(cookie);
+ EXPECT_EQ(kCookieValue, cookie_value);
+ }
+
+ static void on_destruction(::google::protobuf::Arena* arena, void* cookie,
+ uint64 space_used) {
+ ++num_destruct;
+ int cookie_value = *static_cast<int*>(cookie);
+ EXPECT_EQ(kCookieValue, cookie_value);
+ delete static_cast<int*>(cookie);
+ }
+
+ static const int kCookieValue = 999;
+ static uint32 num_init;
+ static uint32 num_reset;
+ static uint32 num_destruct;
+};
+uint32 ArenaHooksTestUtil::num_init = 0;
+uint32 ArenaHooksTestUtil::num_reset = 0;
+uint32 ArenaHooksTestUtil::num_destruct = 0;
+const int ArenaHooksTestUtil::kCookieValue;
+
+// Test the hooks are correctly called and that the cookie is passed.
+TEST(ArenaTest, ArenaHooksSanity) {
+ ::google::protobuf::ArenaOptions options;
+ options.on_arena_init = ArenaHooksTestUtil::on_init;
+ options.on_arena_reset = ArenaHooksTestUtil::on_reset;
+ options.on_arena_destruction = ArenaHooksTestUtil::on_destruction;
+
+ // Scope for defining the arena
+ {
+ ::google::protobuf::Arena arena(options);
+ EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
+
+ arena.Reset();
+ arena.Reset();
+ EXPECT_EQ(2, ArenaHooksTestUtil::num_reset);
+ }
+ EXPECT_EQ(3, ArenaHooksTestUtil::num_reset);
+ EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct);
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 13250702..567238ae 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -48,7 +48,6 @@
#include <iostream>
#include <ctype.h>
-#include <google/protobuf/stubs/hash.h>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
@@ -152,7 +151,7 @@ bool VerifyDirectoryExists(const string& path) {
if (path.empty()) return true;
if (access(path.c_str(), F_OK) == -1) {
- cerr << path << ": " << strerror(errno) << endl;
+ std::cerr << path << ": " << strerror(errno) << std::endl;
return false;
} else {
return true;
@@ -171,8 +170,8 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) {
path_so_far += parts[i];
if (mkdir(path_so_far.c_str(), 0777) != 0) {
if (errno != EEXIST) {
- cerr << filename << ": while trying to create directory "
- << path_so_far << ": " << strerror(errno) << endl;
+ std::cerr << filename << ": while trying to create directory "
+ << path_so_far << ": " << strerror(errno) << std::endl;
return false;
}
}
@@ -201,9 +200,9 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
tree_ != NULL &&
tree_->VirtualFileToDiskFile(filename, &dfile)) {
- cerr << dfile;
+ std::cerr << dfile;
} else {
- cerr << filename;
+ std::cerr << filename;
}
// Users typically expect 1-based line/column numbers, so we add 1
@@ -212,15 +211,16 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
// Allow for both GCC- and Visual-Studio-compatible output.
switch (format_) {
case CommandLineInterface::ERROR_FORMAT_GCC:
- cerr << ":" << (line + 1) << ":" << (column + 1);
+ std::cerr << ":" << (line + 1) << ":" << (column + 1);
break;
case CommandLineInterface::ERROR_FORMAT_MSVS:
- cerr << "(" << (line + 1) << ") : error in column=" << (column + 1);
+ std::cerr << "(" << (line + 1)
+ << ") : error in column=" << (column + 1);
break;
}
}
- cerr << ": " << message << endl;
+ std::cerr << ": " << message << std::endl;
}
// implements io::ErrorCollector -----------------------------------
@@ -254,6 +254,9 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext {
// format, unless one has already been written.
void AddJarManifest();
+ // Get name of all output files.
+ void GetOutputFilenames(vector<string>* output_filenames);
+
// implements GeneratorContext --------------------------------------
io::ZeroCopyOutputStream* Open(const string& filename);
io::ZeroCopyOutputStream* OpenForAppend(const string& filename);
@@ -345,7 +348,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
if (file_descriptor < 0) {
int error = errno;
- cerr << filename << ": " << strerror(error);
+ std::cerr << filename << ": " << strerror(error);
return false;
}
@@ -369,9 +372,9 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
if (write_result < 0) {
int error = errno;
- cerr << filename << ": write: " << strerror(error);
+ std::cerr << filename << ": write: " << strerror(error);
} else {
- cerr << filename << ": write() returned zero?" << endl;
+ std::cerr << filename << ": write() returned zero?" << std::endl;
}
return false;
}
@@ -382,7 +385,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk(
if (close(file_descriptor) != 0) {
int error = errno;
- cerr << filename << ": close: " << strerror(error);
+ std::cerr << filename << ": close: " << strerror(error);
return false;
}
}
@@ -405,7 +408,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
if (file_descriptor < 0) {
int error = errno;
- cerr << filename << ": " << strerror(error);
+ std::cerr << filename << ": " << strerror(error);
return false;
}
@@ -421,11 +424,11 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip(
zip_writer.WriteDirectory();
if (stream.GetErrno() != 0) {
- cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+ std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
}
if (!stream.Close()) {
- cerr << filename << ": " << strerror(stream.GetErrno()) << endl;
+ std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
}
return true;
@@ -441,6 +444,14 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() {
}
}
+void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames(
+ vector<string>* output_filenames) {
+ for (map<string, string*>::iterator iter = files_.begin();
+ iter != files_.end(); ++iter) {
+ output_filenames->push_back(iter->first);
+ }
+}
+
io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open(
const string& filename) {
return new MemoryOutputStream(this, filename, false);
@@ -490,7 +501,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
if (append_mode_) {
(*map_slot)->append(data_);
} else {
- cerr << filename_ << ": Tried to write the same file twice." << endl;
+ std::cerr << filename_ << ": Tried to write the same file twice."
+ << std::endl;
directory_->had_error_ = true;
}
return;
@@ -508,8 +520,9 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
// Find the file we are going to insert into.
if (*map_slot == NULL) {
- cerr << filename_ << ": Tried to insert into file that doesn't exist."
- << endl;
+ std::cerr << filename_
+ << ": Tried to insert into file that doesn't exist."
+ << std::endl;
directory_->had_error_ = true;
return;
}
@@ -521,8 +534,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
string::size_type pos = target->find(magic_string);
if (pos == string::npos) {
- cerr << filename_ << ": insertion point \"" << insertion_point_
- << "\" not found." << endl;
+ std::cerr << filename_ << ": insertion point \"" << insertion_point_
+ << "\" not found." << std::endl;
directory_->had_error_ = true;
return;
}
@@ -670,7 +683,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
// We construct a separate GeneratorContext for each output location. Note
// that two code generators may output to the same location, in which case
// they should share a single GeneratorContext so that OpenForInsert() works.
- typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
GeneratorContextMap output_directories;
// Generate output.
@@ -717,6 +729,13 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
}
}
+ if (!dependency_out_name_.empty()) {
+ if (!GenerateDependencyManifestFile(parsed_files, output_directories,
+ &source_tree)) {
+ return 1;
+ }
+ }
+
STLDeleteValues(&output_directories);
if (!descriptor_set_name_.empty()) {
@@ -775,6 +794,7 @@ void CommandLineInterface::Clear() {
output_directives_.clear();
codec_type_.clear();
descriptor_set_name_.clear();
+ dependency_out_name_.clear();
mode_ = MODE_COMPILE;
print_mode_ = PRINT_NONE;
@@ -793,27 +813,31 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative(
input_files_[i] = virtual_file;
break;
case DiskSourceTree::SHADOWED:
- cerr << input_files_[i] << ": Input is shadowed in the --proto_path "
- "by \"" << shadowing_disk_file << "\". Either use the latter "
- "file as your input or reorder the --proto_path so that the "
- "former file's location comes first." << endl;
+ std::cerr << input_files_[i]
+ << ": Input is shadowed in the --proto_path by \""
+ << shadowing_disk_file
+ << "\". Either use the latter file as your input or reorder "
+ "the --proto_path so that the former file's location "
+ "comes first." << std::endl;
return false;
case DiskSourceTree::CANNOT_OPEN:
- cerr << input_files_[i] << ": " << strerror(errno) << endl;
+ std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl;
return false;
case DiskSourceTree::NO_MAPPING:
// First check if the file exists at all.
if (access(input_files_[i].c_str(), F_OK) < 0) {
// File does not even exist.
- cerr << input_files_[i] << ": " << strerror(ENOENT) << endl;
+ std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
} else {
- cerr << input_files_[i] << ": File does not reside within any path "
- "specified using --proto_path (or -I). You must specify a "
- "--proto_path which encompasses this file. Note that the "
- "proto_path must be an exact prefix of the .proto file "
- "names -- protoc is too dumb to figure out when two paths "
- "(e.g. absolute and relative) are equivalent (it's harder "
- "than you think)." << endl;
+ std::cerr
+ << input_files_[i]
+ << ": File does not reside within any path "
+ "specified using --proto_path (or -I). You must specify a "
+ "--proto_path which encompasses this file. Note that the "
+ "proto_path must be an exact prefix of the .proto file "
+ "names -- protoc is too dumb to figure out when two paths "
+ "(e.g. absolute and relative) are equivalent (it's harder "
+ "than you think)." << std::endl;
}
return false;
}
@@ -833,9 +857,10 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
if (ParseArgument(argv[i], &name, &value)) {
// Returned true => Use the next argument as the flag value.
if (i + 1 == argc || argv[i+1][0] == '-') {
- cerr << "Missing value for flag: " << name << endl;
+ std::cerr << "Missing value for flag: " << name << std::endl;
if (name == "--decode") {
- cerr << "To decode an unknown message, use --decode_raw." << endl;
+ std::cerr << "To decode an unknown message, use --decode_raw."
+ << std::endl;
}
return PARSE_ARGUMENT_FAIL;
} else {
@@ -860,24 +885,34 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) {
// Check some errror cases.
bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty();
if (decoding_raw && !input_files_.empty()) {
- cerr << "When using --decode_raw, no input files should be given." << endl;
+ std::cerr << "When using --decode_raw, no input files should be given."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
} else if (!decoding_raw && input_files_.empty()) {
- cerr << "Missing input file." << endl;
+ std::cerr << "Missing input file." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (mode_ == MODE_COMPILE && output_directives_.empty() &&
descriptor_set_name_.empty()) {
- cerr << "Missing output directives." << endl;
+ std::cerr << "Missing output directives." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) {
+ cerr << "Can only use --dependency_out=FILE when generating code." << 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;
return PARSE_ARGUMENT_FAIL;
}
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
- cerr << "--include_imports only makes sense when combined with "
- "--descriptor_set_out." << endl;
+ std::cerr << "--include_imports only makes sense when combined with "
+ "--descriptor_set_out." << std::endl;
}
if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
- cerr << "--include_source_info only makes sense when combined with "
- "--descriptor_set_out." << endl;
+ std::cerr << "--include_source_info only makes sense when combined with "
+ "--descriptor_set_out." << std::endl;
}
return PARSE_ARGUMENT_DONE_AND_CONTINUE;
@@ -950,10 +985,12 @@ CommandLineInterface::InterpretArgument(const string& name,
if (name.empty()) {
// Not a flag. Just a filename.
if (value.empty()) {
- cerr << "You seem to have passed an empty string as one of the "
- "arguments to " << executable_name_ << ". This is actually "
- "sort of hard to do. Congrats. Unfortunately it is not valid "
- "input so the program is going to die now." << endl;
+ std::cerr
+ << "You seem to have passed an empty string as one of the "
+ "arguments to " << executable_name_
+ << ". This is actually "
+ "sort of hard to do. Congrats. Unfortunately it is not valid "
+ "input so the program is going to die now." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -980,14 +1017,16 @@ CommandLineInterface::InterpretArgument(const string& name,
}
if (disk_path.empty()) {
- cerr << "--proto_path passed empty directory name. (Use \".\" for "
- "current directory.)" << endl;
+ std::cerr
+ << "--proto_path passed empty directory name. (Use \".\" for "
+ "current directory.)" << std::endl;
return PARSE_ARGUMENT_FAIL;
}
// Make sure disk path exists, warn otherwise.
if (access(disk_path.c_str(), F_OK) < 0) {
- cerr << disk_path << ": warning: directory does not exist." << endl;
+ std::cerr << disk_path << ": warning: directory does not exist."
+ << std::endl;
}
// Don't use make_pair as the old/default standard library on Solaris
@@ -998,30 +1037,42 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "-o" || name == "--descriptor_set_out") {
if (!descriptor_set_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;
}
if (mode_ != MODE_COMPILE) {
- cerr << "Cannot use --encode or --decode and generate descriptors at the "
- "same time." << endl;
+ std::cerr
+ << "Cannot use --encode or --decode and generate descriptors at the "
+ "same time." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
descriptor_set_name_ = value;
+ } else if (name == "--dependency_out") {
+ if (!dependency_out_name_.empty()) {
+ cerr << name << " may only be passed once." << endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ if (value.empty()) {
+ cerr << name << " requires a non-empty value." << endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+ dependency_out_name_ = value;
+
} else if (name == "--include_imports") {
if (imports_in_descriptor_set_) {
- cerr << name << " may only be passed once." << endl;
+ std::cerr << name << " may only be passed once." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
imports_in_descriptor_set_ = true;
} else if (name == "--include_source_info") {
if (source_info_in_descriptor_set_) {
- cerr << name << " may only be passed once." << endl;
+ std::cerr << name << " may only be passed once." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
source_info_in_descriptor_set_ = true;
@@ -1032,7 +1083,7 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--version") {
if (!version_info_.empty()) {
- cout << version_info_ << endl;
+ std::cout << version_info_ << std::endl;
}
cout << "libprotoc "
<< protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION)
@@ -1045,25 +1096,28 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--encode" || name == "--decode" ||
name == "--decode_raw") {
if (mode_ != MODE_COMPILE) {
- cerr << "Only one of --encode and --decode can be specified." << endl;
+ std::cerr << "Only one of --encode and --decode can be specified."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
- cerr << "Cannot use " << name
- << " and generate code or descriptors at the same time." << endl;
+ std::cerr << "Cannot use " << name
+ << " and generate code or descriptors at the same time."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE;
if (value.empty() && name != "--decode_raw") {
- cerr << "Type name for " << name << " cannot be blank." << endl;
+ std::cerr << "Type name for " << name << " cannot be blank." << std::endl;
if (name == "--decode") {
- cerr << "To decode an unknown message, use --decode_raw." << endl;
+ std::cerr << "To decode an unknown message, use --decode_raw."
+ << std::endl;
}
return PARSE_ARGUMENT_FAIL;
} else if (!value.empty() && name == "--decode_raw") {
- cerr << "--decode_raw does not take a parameter." << endl;
+ std::cerr << "--decode_raw does not take a parameter." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -1075,13 +1129,13 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (value == "msvs") {
error_format_ = ERROR_FORMAT_MSVS;
} else {
- cerr << "Unknown error format: " << value << endl;
+ std::cerr << "Unknown error format: " << value << std::endl;
return PARSE_ARGUMENT_FAIL;
}
} else if (name == "--plugin") {
if (plugin_prefix_.empty()) {
- cerr << "This compiler does not support plugins." << endl;
+ std::cerr << "This compiler does not support plugins." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -1107,13 +1161,15 @@ CommandLineInterface::InterpretArgument(const string& name,
} else if (name == "--print_free_field_numbers") {
if (mode_ != MODE_COMPILE) {
- cerr << "Cannot use " << name << " and use --encode, --decode or print "
- << "other info at the same time." << endl;
+ std::cerr << "Cannot use " << name
+ << " and use --encode, --decode or print "
+ << "other info at the same time." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
- cerr << "Cannot use " << name
- << " and generate code or descriptors at the same time." << endl;
+ std::cerr << "Cannot use " << name
+ << " and generate code or descriptors at the same time."
+ << std::endl;
return PARSE_ARGUMENT_FAIL;
}
mode_ = MODE_PRINT;
@@ -1127,7 +1183,7 @@ CommandLineInterface::InterpretArgument(const string& name,
// Check if it's a generator option flag.
generator_info = FindOrNull(generators_by_option_name_, name);
if (generator_info == NULL) {
- cerr << "Unknown flag: " << name << endl;
+ std::cerr << "Unknown flag: " << name << std::endl;
return PARSE_ARGUMENT_FAIL;
} else {
string* parameters = &generator_parameters_[generator_info->flag_name];
@@ -1139,8 +1195,8 @@ CommandLineInterface::InterpretArgument(const string& name,
} else {
// It's an output flag. Add it to the output directives.
if (mode_ != MODE_COMPILE) {
- cerr << "Cannot use --encode, --decode or print .proto info and "
- "generate code at the same time." << endl;
+ std::cerr << "Cannot use --encode, --decode or print .proto info and "
+ "generate code at the same time." << std::endl;
return PARSE_ARGUMENT_FAIL;
}
@@ -1172,7 +1228,7 @@ CommandLineInterface::InterpretArgument(const string& name,
void CommandLineInterface::PrintHelpText() {
// Sorry for indentation here; line wrapping would be uglier.
- cerr <<
+ std::cerr <<
"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n"
"Parse PROTO_FILES and generate output based on the options given:\n"
" -IPATH, --proto_path=PATH Specify the directory in which to search for\n"
@@ -1206,6 +1262,9 @@ void CommandLineInterface::PrintHelpText() {
" include information about the original\n"
" location of each decl in the source file as\n"
" well as surrounding comments.\n"
+" --dependency_out=FILE Write a dependency output file in the format\n"
+" expected by make. This writes the transitive\n"
+" set of input file paths to FILE\n"
" --error_format=FORMAT Set the format in which to print errors.\n"
" FORMAT may be 'gcc' (the default) or 'msvs'\n"
" (Microsoft Visual Studio format).\n"
@@ -1213,9 +1272,9 @@ 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." << endl;
+" occupied fields numbers." << std::endl;
if (!plugin_prefix_.empty()) {
- cerr <<
+ std::cerr <<
" --plugin=EXECUTABLE Specifies a plugin executable to use.\n"
" Normally, protoc searches the PATH for\n"
" plugins, but you may specify additional\n"
@@ -1223,7 +1282,7 @@ void CommandLineInterface::PrintHelpText() {
" Additionally, EXECUTABLE may be of the form\n"
" NAME=PATH, in which case the given plugin name\n"
" is mapped to the given executable even if\n"
-" the executable's own name differs." << endl;
+" the executable's own name differs." << std::endl;
}
for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
@@ -1231,9 +1290,9 @@ void CommandLineInterface::PrintHelpText() {
// FIXME(kenton): If the text is long enough it will wrap, which is ugly,
// but fixing this nicely (e.g. splitting on spaces) is probably more
// trouble than it's worth.
- cerr << " " << iter->first << "=OUT_DIR "
- << string(19 - iter->first.size(), ' ') // Spaces for alignment.
- << iter->second.help_text << endl;
+ std::cerr << " " << iter->first << "=OUT_DIR "
+ << string(19 - iter->first.size(), ' ') // Spaces for alignment.
+ << iter->second.help_text << std::endl;
}
}
@@ -1256,7 +1315,7 @@ bool CommandLineInterface::GenerateOutput(
if (!GeneratePluginOutput(parsed_files, plugin_name,
output_directive.parameter,
generator_context, &error)) {
- cerr << output_directive.name << ": " << error << endl;
+ std::cerr << output_directive.name << ": " << error << std::endl;
return false;
}
} else {
@@ -1272,8 +1331,8 @@ bool CommandLineInterface::GenerateOutput(
if (!output_directive.generator->Generate(parsed_files[i], parameters,
generator_context, &error)) {
// Generator returned an error.
- cerr << output_directive.name << ": " << parsed_files[i]->name() << ": "
- << error << endl;
+ std::cerr << output_directive.name << ": " << parsed_files[i]->name()
+ << ": " << error << std::endl;
return false;
}
}
@@ -1282,6 +1341,76 @@ bool CommandLineInterface::GenerateOutput(
return true;
}
+bool CommandLineInterface::GenerateDependencyManifestFile(
+ const vector<const FileDescriptor*>& parsed_files,
+ const GeneratorContextMap& output_directories,
+ DiskSourceTree* source_tree) {
+ FileDescriptorSet file_set;
+
+ set<const FileDescriptor*> already_seen;
+ for (int i = 0; i < parsed_files.size(); i++) {
+ GetTransitiveDependencies(parsed_files[i],
+ false,
+ &already_seen,
+ file_set.mutable_file());
+ }
+
+ vector<string> output_filenames;
+ for (GeneratorContextMap::const_iterator iter = output_directories.begin();
+ iter != output_directories.end(); ++iter) {
+ const string& location = iter->first;
+ GeneratorContextImpl* directory = iter->second;
+ vector<string> relative_output_filenames;
+ directory->GetOutputFilenames(&relative_output_filenames);
+ for (int i = 0; i < relative_output_filenames.size(); i++) {
+ string output_filename = location + relative_output_filenames[i];
+ if (output_filename.compare(0, 2, "./") == 0) {
+ output_filename = output_filename.substr(2);
+ }
+ output_filenames.push_back(output_filename);
+ }
+ }
+
+ int fd;
+ do {
+ fd = open(dependency_out_name_.c_str(),
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+ } while (fd < 0 && errno == EINTR);
+
+ if (fd < 0) {
+ perror(dependency_out_name_.c_str());
+ return false;
+ }
+
+ io::FileOutputStream out(fd);
+ io::Printer printer(&out, '$');
+
+ for (int i = 0; i < output_filenames.size(); i++) {
+ printer.Print(output_filenames[i].c_str());
+ if (i == output_filenames.size() - 1) {
+ printer.Print(":");
+ } else {
+ printer.Print(" \\\n");
+ }
+ }
+
+ for (int i = 0; i < file_set.file_size(); i++) {
+ const FileDescriptorProto& file = file_set.file(i);
+ const string& virtual_file = file.name();
+ string disk_file;
+ if (source_tree &&
+ source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) {
+ 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;
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool CommandLineInterface::GeneratePluginOutput(
const vector<const FileDescriptor*>& parsed_files,
const string& plugin_name,
@@ -1365,7 +1494,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
// Look up the type.
const Descriptor* type = pool->FindMessageTypeByName(codec_type_);
if (type == NULL) {
- cerr << "Type not defined: " << codec_type_ << endl;
+ std::cerr << "Type not defined: " << codec_type_ << std::endl;
return false;
}
@@ -1391,32 +1520,32 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) {
parser.AllowPartialMessage(true);
if (!parser.Parse(&in, message.get())) {
- cerr << "Failed to parse input." << endl;
+ std::cerr << "Failed to parse input." << std::endl;
return false;
}
} else {
// Input is binary.
if (!message->ParsePartialFromZeroCopyStream(&in)) {
- cerr << "Failed to parse input." << endl;
+ std::cerr << "Failed to parse input." << std::endl;
return false;
}
}
if (!message->IsInitialized()) {
- cerr << "warning: Input message is missing required fields: "
- << message->InitializationErrorString() << endl;
+ std::cerr << "warning: Input message is missing required fields: "
+ << message->InitializationErrorString() << std::endl;
}
if (mode_ == MODE_ENCODE) {
// Output is binary.
if (!message->SerializePartialToZeroCopyStream(&out)) {
- cerr << "output: I/O error." << endl;
+ std::cerr << "output: I/O error." << std::endl;
return false;
}
} else {
// Output is text.
if (!TextFormat::Print(*message, &out)) {
- cerr << "output: I/O error." << endl;
+ std::cerr << "output: I/O error." << std::endl;
return false;
}
}
@@ -1458,12 +1587,14 @@ bool CommandLineInterface::WriteDescriptorSet(
io::FileOutputStream out(fd);
if (!file_set.SerializeToZeroCopyStream(&out)) {
- cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
+ std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+ << std::endl;
out.Close();
return false;
}
if (!out.Close()) {
- cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl;
+ std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+ << std::endl;
return false;
}
@@ -1582,7 +1713,7 @@ void FormatFreeFieldNumbers(const string& name,
if (next_free_number <= FieldDescriptor::kMaxNumber) {
StringAppendF(&output, " %d-INF", next_free_number);
}
- cout << output << endl;
+ std::cout << output << std::endl;
}
} // namespace
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 74a0adb4..7e611c44 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -39,6 +39,7 @@
#define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/hash.h>
#include <string>
#include <vector>
#include <map>
@@ -190,6 +191,7 @@ class LIBPROTOC_EXPORT CommandLineInterface {
class ErrorPrinter;
class GeneratorContextImpl;
class MemoryOutputStream;
+ typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap;
// Clear state from previous Run().
void Clear();
@@ -247,6 +249,12 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// Implements the --descriptor_set_out option.
bool WriteDescriptorSet(const vector<const FileDescriptor*> parsed_files);
+ // Implements the --dependency_out option
+ bool GenerateDependencyManifestFile(
+ const vector<const FileDescriptor*>& parsed_files,
+ const GeneratorContextMap& output_directories,
+ DiskSourceTree* source_tree);
+
// Get all transitive dependencies of the given file (including the file
// itself), adding them to the given list of FileDescriptorProtos. The
// protos will be ordered such that every file is listed before any file that
@@ -353,6 +361,10 @@ class LIBPROTOC_EXPORT CommandLineInterface {
// FileDescriptorSet should be written. Otherwise, empty.
string descriptor_set_name_;
+ // If --dependency_out was given, this is the path to the file where the
+ // dependency file will be written. Otherwise, empty.
+ string dependency_out_name_;
+
// True if --include_imports was given, meaning that we should
// write all transitive dependencies to the DescriptorSet. Otherwise, only
// the .proto files listed on the command-line are added.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index dbaaa405..a2cbbdc6 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -64,6 +64,9 @@
#include <gtest/gtest.h>
+// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
+// which case tcmalloc will print warnings that fail the plugin tests.
+#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
namespace google {
namespace protobuf {
namespace compiler {
@@ -112,6 +115,11 @@ class CommandLineInterfaceTest : public testing::Test {
// Create a subdirectory within temp_directory_.
void CreateTempDir(const string& name);
+ // Change working directory to temp directory.
+ void SwitchToTempDirectory() {
+ File::ChangeWorkingDirectory(temp_directory_);
+ }
+
void SetInputsAreProtoPathRelative(bool enable) {
cli_.SetInputsAreProtoPathRelative(enable);
}
@@ -176,6 +184,9 @@ class CommandLineInterfaceTest : public testing::Test {
void ReadDescriptorSet(const string& filename,
FileDescriptorSet* descriptor_set);
+ void ExpectFileContent(const string& filename,
+ const string& content);
+
private:
// The object we are testing.
CommandLineInterface cli_;
@@ -456,6 +467,17 @@ void CommandLineInterfaceTest::ExpectCapturedStdout(
EXPECT_EQ(expected_text, captured_stdout_);
}
+
+void CommandLineInterfaceTest::ExpectFileContent(
+ const string& filename, const string& content) {
+ string path = temp_directory_ + "/" + filename;
+ string file_contents;
+ GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true));
+
+ EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true),
+ file_contents);
+}
+
// ===================================================================
TEST_F(CommandLineInterfaceTest, BasicOutput) {
@@ -940,6 +962,71 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) {
EXPECT_TRUE(descriptor_set.file(1).has_source_code_info());
}
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --dependency_out=$tmpdir/manifest "
+ "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto");
+
+ ExpectErrorText(
+ "Can only process one input file when using --dependency_out=FILE.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ string current_working_directory = getcwd(NULL, 0);
+ SwitchToTempDirectory();
+
+ Run("protocol_compiler --dependency_out=manifest --test_out=. "
+ "bar.proto");
+
+ ExpectNoErrors();
+
+ ExpectFileContent("manifest",
+ "bar.proto.MockCodeGenerator.test_generator: "
+ "foo.proto\\\n bar.proto");
+
+ File::ChangeWorkingDirectory(current_working_directory);
+}
+
+TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "message Foo {}\n");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Bar {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --dependency_out=$tmpdir/manifest "
+ "--test_out=$tmpdir --proto_path=$tmpdir bar.proto");
+
+ ExpectNoErrors();
+
+ ExpectFileContent("manifest",
+ "$tmpdir/bar.proto.MockCodeGenerator.test_generator: "
+ "$tmpdir/foo.proto\\\n $tmpdir/bar.proto");
+}
+
// -------------------------------------------------------------------
TEST_F(CommandLineInterfaceTest, ParseErrors) {
@@ -1662,4 +1749,6 @@ TEST_F(EncodeDecodeTest, ProtoParseError) {
} // namespace compiler
} // namespace protobuf
+
+#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
} // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 48788197..13ed0b64 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -98,7 +98,8 @@ class MockGeneratorContext : public GeneratorContext {
&actual_contents, true));
EXPECT_TRUE(actual_contents == *expected_contents)
<< physical_filename << " needs to be regenerated. Please run "
- "generate_descriptor_proto.sh and add this file "
+ "google/protobuf/compiler/release_compiler.sh and "
+ "generate_descriptor_proto.sh. Then add this file "
"to your CL.";
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 3ce1f120..3eb20ab1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -47,7 +47,7 @@ namespace cpp {
namespace {
// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
-// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
+// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
// generation of the GOOGLE_ARRAYSIZE constant.
bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
int32 max_value = descriptor->value(0)->number();
@@ -56,7 +56,7 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
max_value = descriptor->value(i)->number();
}
}
- return max_value != kint32max;
+ return max_value != ::google::protobuf::kint32max;
}
} // namespace
@@ -82,7 +82,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
const EnumValueDescriptor* max_value = descriptor_->value(0);
for (int i = 0; i < descriptor_->value_count(); i++) {
- vars["name"] = descriptor_->value(i)->name();
+ vars["name"] = EnumValueName(descriptor_->value(i));
// In C++, an value of -2147483648 gets interpreted as the negative of
// 2147483648, and since 2147483648 can't fit in an integer, this produces a
// compiler warning. This works around that issue.
@@ -90,6 +90,7 @@ 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$");
@@ -113,8 +114,8 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
printer->Outdent();
printer->Print("\n};\n");
- vars["min_name"] = min_value->name();
- vars["max_name"] = max_value->name();
+ vars["min_name"] = EnumValueName(min_value);
+ vars["max_name"] = EnumValueName(max_value);
if (options_.dllexport_decl.empty()) {
vars["dllexport"] = "";
@@ -153,9 +154,12 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
void EnumGenerator::
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
+ printer->Print(
+ "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type "
+ "{};\n",
+ "classname", ClassName(descriptor_, true));
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(
- "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n"
"template <>\n"
"inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n"
" return $classname$_descriptor();\n"
@@ -171,7 +175,7 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) {
printer->Print(vars, "typedef $classname$ $nested_name$;\n");
for (int j = 0; j < descriptor_->value_count(); j++) {
- vars["tag"] = descriptor_->value(j)->name();
+ vars["tag"] = EnumValueName(descriptor_->value(j));
printer->Print(vars,
"static const $nested_name$ $tag$ = $classname$_$tag$;\n");
}
@@ -275,7 +279,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
vars["parent"] = ClassName(descriptor_->containing_type(), false);
vars["nested_name"] = descriptor_->name();
for (int i = 0; i < descriptor_->value_count(); i++) {
- vars["value"] = descriptor_->value(i)->name();
+ vars["value"] = EnumValueName(descriptor_->value(i));
printer->Print(vars,
"const $classname$ $parent$::$value$;\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 17926135..74989703 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -76,23 +76,26 @@ GeneratePrivateMembers(io::Printer* printer) const {
void EnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$() const$deprecation$;\n"
- "inline void set_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$() const$deprecation$;\n"
+ "void set_$name$($type$ value)$deprecation$;\n");
}
void EnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_);\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n");
+ "$inline$ void $classname$::set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -181,21 +184,24 @@ EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
void EnumOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return static_cast< $type$ >($oneof_prefix$$name$_);\n"
" }\n"
" return static_cast< $type$ >($default$);\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n");
+ "$inline$ void $classname$::set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -246,46 +252,49 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$(int index) const$deprecation$;\n"
- "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
- "inline void add_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$(int index) const$deprecation$;\n"
+ "void set_$name$(int index, $type$ value)$deprecation$;\n"
+ "void add_$name$($type$ value)$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
+ "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
+ "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n");
}
void RepeatedEnumFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
- "inline void $classname$::set_$name$(int index, $type$ value) {\n");
+ "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::add_$name$($type$ value) {\n");
+ "$inline$ void $classname$::add_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
- printer->Print(variables_,
+ printer->Print(variables,
" assert($type$_IsValid(value));\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField<int>&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedField<int>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedField<int>*\n"
+ "$inline$ ::google::protobuf::RepeatedField<int>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
@@ -344,20 +353,34 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
if (!descriptor_->options().packed()) {
- // We use a non-inlined implementation in this case, since this path will
- // rarely be executed.
- printer->Print(variables_,
- "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
- " input,\n");
+ // This path is rarely executed, so we use a non-inlined implementation.
if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables_,
- " NULL,\n");
+ "DO_((::google::protobuf::internal::"
+ "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+ " input,\n"
+ " $number$,\n"
+ " NULL,\n"
+ " NULL,\n"
+ " this->mutable_$name$())));\n");
+ } else if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(variables_,
+ "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n"
+ " input,\n"
+ " $number$,\n"
+ " $type$_IsValid,\n"
+ " mutable_unknown_fields(),\n"
+ " this->mutable_$name$())));\n");
} else {
printer->Print(variables_,
- " &$type$_IsValid,\n");
+ "DO_((::google::protobuf::internal::"
+ "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
+ " input,\n"
+ " $number$,\n"
+ " $type$_IsValid,\n"
+ " &unknown_fields_stream,\n"
+ " this->mutable_$name$())));\n");
}
- printer->Print(variables_,
- " this->mutable_$name$())));\n");
} else {
printer->Print(variables_,
"::google::protobuf::uint32 length;\n"
@@ -376,6 +399,16 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
printer->Print(variables_,
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
+ " } else {\n");
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(variables_,
+ " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ } else {
+ printer->Print(variables_,
+ " unknown_fields_stream.WriteVarint32(tag);\n"
+ " unknown_fields_stream.WriteVarint32(value);\n");
+ }
+ printer->Print(
" }\n");
}
printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index def2b232..5b1d01ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -53,7 +53,8 @@ class EnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +79,8 @@ class EnumOneofFieldGenerator : public EnumFieldGenerator {
~EnumOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -96,7 +98,8 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index c37fe0be..cd2b6b75 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -89,7 +89,7 @@ class FieldGenerator {
// Generate inline definitions of accessor functions for this field.
// These are placed inside the header after all class definitions.
virtual void GenerateInlineAccessorDefinitions(
- io::Printer* printer) const = 0;
+ io::Printer* printer, bool is_inline) const = 0;
// Generate definitions of accessors that aren't inlined. These are
// placed somewhere in the .cc file.
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index fae4df40..a98c7d92 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -136,8 +136,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(
"#include <google/protobuf/arena.h>\n"
"#include <google/protobuf/arenastring.h>\n"
- "#include <google/protobuf/generated_message_util.h>\n"
- "#include <google/protobuf/metadata.h>\n");
+ "#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(
@@ -152,13 +155,24 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"#include <google/protobuf/extension_set.h>\n");
if (HasMapFields(file_)) {
printer->Print(
- "#include <google/protobuf/map.h>\n"
- "#include <google/protobuf/map_field_inl.h>\n");
+ "#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 (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
- printer->Print(
- "#include <google/protobuf/generated_enum_reflection.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_)) {
@@ -272,15 +286,17 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
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);
+ message_generators_[i]->GenerateInlineMethods(printer,
+ /* is_inline = */ true);
}
+ printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
printer->Print(
"\n"
@@ -290,7 +306,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
GenerateNamespaceClosers(printer);
// Emit GetEnumDescriptor specializations into google::protobuf namespace:
- if (HasDescriptorMethods(file_)) {
+ 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>(); }
@@ -417,6 +433,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
printer->Print(kThickSeparator);
printer->Print("\n");
message_generators_[i]->GenerateClassMethods(printer);
+
+ printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+ // Generate class inline methods.
+ message_generators_[i]->GenerateInlineMethods(printer,
+ /* is_inline = */ false);
+ printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
}
if (HasGenericServices(file_)) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 28c4dd54..4e7155c3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -176,6 +176,14 @@ string FieldName(const FieldDescriptor* field) {
return result;
}
+string EnumValueName(const EnumValueDescriptor* enum_value) {
+ string result = enum_value->name();
+ if (kKeywords.count(result) > 0) {
+ result.append("_");
+ }
+ return result;
+}
+
string FieldConstantName(const FieldDescriptor *field) {
string field_name = UnderscoresToCamelCase(field->name(), true);
string result = "k" + field_name + "FieldNumber";
@@ -352,9 +360,7 @@ string FilenameIdentifier(const string& filename) {
} else {
// Not alphanumeric. To avoid any possibility of name conflicts we
// use the hex code for the character.
- result.push_back('_');
- char buffer[kFastToBufferSize];
- result.append(FastHexToBuffer(static_cast<uint8>(filename[i]), buffer));
+ StrAppend(&result, "_", ToHex(static_cast<uint8>(filename[i])));
}
}
return result;
@@ -508,6 +514,13 @@ bool IsStringOrMessage(const FieldDescriptor* field) {
return false;
}
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) {
+ GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
+ // Open-source protobuf release only supports STRING ctype.
+ return FieldOptions::STRING;
+
+}
+
} // 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 e60fa7c2..284fa2c1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -74,6 +74,9 @@ string SuperClassName(const Descriptor* descriptor);
// anyway, so normally this just returns field->name().
string FieldName(const FieldDescriptor* field);
+// Get the sanitized name that should be used for the given enum in C++ code.
+string EnumValueName(const EnumValueDescriptor* enum_value);
+
// Get the unqualified name that should be used for a field's field
// number constant.
string FieldConstantName(const FieldDescriptor *field);
@@ -211,6 +214,10 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) {
// Returns true if the field's CPPTYPE is string or message.
bool IsStringOrMessage(const FieldDescriptor* field);
+// For a string field, returns the effective ctype. If the actual ctype is
+// not supported, returns the default of STRING.
+FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field);
+
string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
inline bool HasFieldPresence(const FileDescriptor* file) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 0154eeb8..8c38db2b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -31,6 +31,7 @@
#include <google/protobuf/compiler/cpp/cpp_map_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -72,14 +73,21 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type());
(*variables)["wrapper"] = "EntryWrapper";
}
- (*variables)["key_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["key_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(key->type()));
- (*variables)["val_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["val_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(val->type()));
(*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
- (*variables)["number"] = Int32ToString(descriptor->number());
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
+
+ if (HasDescriptorMethods(descriptor->file())) {
+ (*variables)["lite"] = "";
+ } else {
+ (*variables)["lite"] = "Lite";
+ }
if (!IsProto3Field(descriptor) &&
val->type() == FieldDescriptor::TYPE_ENUM) {
@@ -102,33 +110,40 @@ MapFieldGenerator::~MapFieldGenerator() {}
void MapFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "typedef ::google::protobuf::internal::MapEntry<\n"
+ "typedef ::google::protobuf::internal::MapEntryLite<\n"
" $key_cpp$, $val_cpp$,\n"
- " $key_type$,\n"
- " $val_type$, $default_enum_value$>\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
+ " $default_enum_value$ >\n"
" $map_classname$;\n"
- "::google::protobuf::internal::MapField< $key_cpp$, $val_cpp$,"
- "$key_type$, $val_type$, $default_enum_value$ > $name$_;\n");
+ "::google::protobuf::internal::MapField$lite$<\n"
+ " $key_cpp$, $val_cpp$,\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
+ " $default_enum_value$ > $name$_;\n");
}
void MapFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+ "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
" $name$() const$deprecation$;\n"
- "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+ "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void MapFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_map:$full_name$)\n"
" return $name$_.GetMap();\n"
"}\n"
- "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+ "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_map:$full_name$)\n"
" return $name$_.MutableMap();\n"
@@ -198,11 +213,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" if ($val_cpp$_IsValid(*entry->mutable_value())) {\n"
" (*mutable_$name$())[entry->key()] =\n"
" static_cast<$val_cpp$>(*entry->mutable_value());\n"
- " } else {\n"
- " mutable_unknown_fields()->AddLengthDelimited($number$, data);\n"
+ " } else {\n");
+ if (HasDescriptorMethods(descriptor_->file())) {
+ printer->Print(variables_,
+ " mutable_unknown_fields()"
+ "->AddLengthDelimited($number$, data);\n");
+ } else {
+ printer->Print(variables_,
+ " unknown_fields_stream.WriteVarint32($tag$);\n"
+ " unknown_fields_stream.WriteVarint32(data.size());\n"
+ " unknown_fields_stream.WriteString(data);\n");
+ }
+
+
+ printer->Print(variables_,
" }\n"
"}\n");
}
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "if (entry->GetArena() != NULL) entry.release();\n");
+ }
}
void MapFieldGenerator::
@@ -211,12 +244,31 @@ 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 = $name$().begin(); it != $name$().end(); ++it) {\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
" $number$, *entry, output);\n"
- " }\n"
- "}\n");
+ " }\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print("}\n");
}
void MapFieldGenerator::
@@ -225,13 +277,32 @@ 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 = $name$().begin(); it != $name$().end(); ++it) {\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoVirtualToArray(\n"
" $number$, *entry, target);\n"
- " }\n"
- "}\n");
+ " }\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print("}\n");
}
void MapFieldGenerator::
@@ -241,12 +312,31 @@ 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 = $name$().begin(); it != $name$().end(); ++it) {\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" total_size += ::google::protobuf::internal::WireFormatLite::\n"
" $declared_type$SizeNoVirtual(*entry);\n"
- " }\n"
- "}\n");
+ " }\n");
+
+ // If entry is allocated by arena, its desctructor should be avoided.
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ " if (entry.get() != NULL && entry->GetArena() != NULL) {\n"
+ " entry.release();\n"
+ " }\n");
+ }
+
+ printer->Print("}\n");
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index 0ff032fd..d27d4851 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -50,7 +50,8 @@ class MapFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index e71d35fa..bafa36f5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -87,8 +87,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
for (int i = 0; i < descriptor->field_count(); i++) {
fields[i] = descriptor->field(i);
}
- sort(fields, fields + descriptor->field_count(),
- FieldOrderingByNumber());
+ std::sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByNumber());
return fields;
}
@@ -253,7 +253,7 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
// Sort by preferred location to keep fields as close to their original
// location as possible. Using stable_sort ensures that the output is
// consistent across runs.
- stable_sort(aligned_to_4.begin(), aligned_to_4.end());
+ std::stable_sort(aligned_to_4.begin(), aligned_to_4.end());
// Now group fields aligned to 4 bytes (or the 4-field groups created above)
// into pairs, and treat those like a single field aligned to 8 bytes.
@@ -269,7 +269,7 @@ void OptimizePadding(vector<const FieldDescriptor*>* fields) {
aligned_to_8.push_back(field_group);
}
// Sort by preferred location.
- stable_sort(aligned_to_8.begin(), aligned_to_8.end());
+ std::stable_sort(aligned_to_8.begin(), aligned_to_8.end());
// Now pull out all the FieldDescriptors in order.
fields->clear();
@@ -280,10 +280,6 @@ 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
@@ -351,11 +347,11 @@ void CollectMapInfo(const Descriptor* descriptor,
default:
(*variables)["val"] = PrimitiveTypeName(val->cpp_type());
}
- (*variables)["key_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["key_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(key->type()));
- (*variables)["val_type"] =
- "::google::protobuf::FieldDescriptor::TYPE_" +
+ (*variables)["val_wire_type"] =
+ "::google::protobuf::internal::WireFormatLite::TYPE_" +
ToUpper(DeclaredTypeMethodName(val->type()));
}
@@ -457,17 +453,17 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
vars["constant_name"] = FieldConstantName(field);
if (field->is_repeated()) {
- printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
+ printer->Print(vars, "int $name$_size() const$deprecation$;\n");
} else if (HasHasMethod(field)) {
- printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
+ printer->Print(vars, "bool has_$name$() const$deprecation$;\n");
} else if (HasPrivateHasMethod(field)) {
printer->Print(vars,
"private:\n"
- "inline bool has_$name$() const$deprecation$;\n"
+ "bool has_$name$() const$deprecation$;\n"
"public:\n");
}
- printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
+ printer->Print(vars, "void clear_$name$()$deprecation$;\n");
printer->Print(vars, "static const int $constant_name$ = $number$;\n");
// Generate type-specific accessor declarations.
@@ -486,7 +482,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
printer->Print(
- "inline $camel_oneof_name$Case $oneof_name$_case() const;\n",
+ "$camel_oneof_name$Case $oneof_name$_case() const;\n",
"camel_oneof_name",
UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true),
"oneof_name", descriptor_->oneof_decl(i)->name());
@@ -494,7 +490,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
}
void MessageGenerator::
-GenerateFieldAccessorDefinitions(io::Printer* printer) {
+GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
printer->Print("// $classname$\n\n", "classname", classname_);
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -504,11 +500,12 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
map<string, string> vars;
SetCommonFieldVariables(field, &vars, options_);
+ 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()) {
@@ -522,11 +519,11 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
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"
+ "$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"
+ "$inline$ void $classname$::set_has_$name$() {\n"
" _oneof_case_[$oneof_index$] = k$field_name$;\n"
"}\n");
} else {
@@ -539,13 +536,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32),
buffer);
printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
+ "$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"
+ "$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"
+ "$inline$ void $classname$::clear_has_$name$() {\n"
" _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
"}\n"
);
@@ -555,12 +552,12 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
bool is_lazy = false;
if (is_lazy) {
printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
+ "$inline$ bool $classname$::has_$name$() const {\n"
" return !$name$_.IsCleared();\n"
"}\n");
} else {
printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
+ "$inline$ bool $classname$::has_$name$() const {\n"
" return !_is_default_instance_ && $name$_ != NULL;\n"
"}\n");
}
@@ -570,7 +567,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
// Generate clear_$name$()
printer->Print(vars,
- "inline void $classname$::clear_$name$() {\n");
+ "$inline$ void $classname$::clear_$name$() {\n");
printer->Indent();
@@ -599,7 +596,8 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
printer->Print("}\n");
// Generate type-specific accessors.
- field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
+ field_generators_.get(field).GenerateInlineAccessorDefinitions(printer,
+ is_inline);
printer->Print("\n");
}
@@ -612,12 +610,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
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"
+ "$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"
+ "$inline$ void $classname$::clear_has_$oneof_name$() {\n"
" _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
"}\n");
}
@@ -1173,18 +1172,18 @@ GenerateClassDefinition(io::Printer* printer) {
}
void MessageGenerator::
-GenerateInlineMethods(io::Printer* printer) {
+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
// cannot be a top level class, we just need to avoid calling
// GenerateInlineMethods here.
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
- nested_generators_[i]->GenerateInlineMethods(printer);
+ nested_generators_[i]->GenerateInlineMethods(printer, is_inline);
printer->Print(kThinSeparator);
printer->Print("\n");
}
- GenerateFieldAccessorDefinitions(printer);
+ GenerateFieldAccessorDefinitions(printer, is_inline);
// Generate oneof_case() functions.
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
@@ -1194,9 +1193,10 @@ GenerateInlineMethods(io::Printer* printer) {
descriptor_->oneof_decl(i)->name(), true);
vars["oneof_name"] = descriptor_->oneof_decl(i)->name();
vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index());
+ 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"
@@ -1226,7 +1226,9 @@ GenerateDescriptorDeclarations(io::Printer* printer) {
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(" ");
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING &&
+ EffectiveStringCType(field) != FieldOptions::STRING)) {
printer->Print("const ");
}
field_generators_.get(field).GeneratePrivateMembers(printer);
@@ -1395,8 +1397,8 @@ GenerateTypeRegistrations(io::Printer* printer) {
" ::google::protobuf::internal::MapEntry<\n"
" $key$,\n"
" $val$,\n"
- " $key_type$,\n"
- " $val_type$,\n"
+ " $key_wire_type$,\n"
+ " $val_wire_type$,\n"
" $default_enum_value$>::CreateDefaultInstance(\n"
" $classname$_descriptor_));\n");
}
@@ -2038,17 +2040,16 @@ GenerateClear(io::Printer* printer) {
// Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0.
// The generated code uses two macros to help it clear runs of fields:
- // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message.
+ // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the
+ // positions of two fields in the Message.
// ZR_ zeroes a non-empty range of fields via memset.
const char* macros =
- "#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \\\n"
- " &reinterpret_cast<$classname$*>(16)->f) - \\\n"
- " reinterpret_cast<char*>(16))\n\n"
- "#define ZR_(first, last) do { \\\n"
- " size_t f = OFFSET_OF_FIELD_(first); \\\n"
- " size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \\\n"
- " ::memset(&first, 0, n); \\\n"
- " } while (0)\n\n";
+ "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
+ " &reinterpret_cast<$classname$*>(16)->f)\n\n"
+ "#define ZR_(first, last) do {\\\n"
+ " ::memset(&first, 0,\\\n"
+ " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n"
+ "} while (0)\n\n";
for (int i = 0; i < runs_of_fields_.size(); i++) {
const vector<string>& run = runs_of_fields_[i];
if (run.size() < 2) continue;
@@ -2137,7 +2138,7 @@ GenerateClear(io::Printer* printer) {
}
if (macros_are_needed) {
printer->Outdent();
- printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n");
+ printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n");
printer->Indent();
}
@@ -2923,8 +2924,8 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor_->extension_range(i));
}
- sort(sorted_extensions.begin(), sorted_extensions.end(),
- ExtensionRangeSorter());
+ std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeSorter());
// Merge the fields and the extension ranges, both sorted by field number.
int i, j;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index dfbc9af5..ea96581d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -82,7 +82,7 @@ class MessageGenerator {
// Generate definitions of inline methods (placed at the end of the header
// file).
- void GenerateInlineMethods(io::Printer* printer);
+ void GenerateInlineMethods(io::Printer* printer, bool is_inline);
// Source file stuff.
@@ -116,7 +116,7 @@ class MessageGenerator {
private:
// Generate declarations and definitions of accessors for fields.
void GenerateFieldAccessorDeclarations(io::Printer* printer);
- void GenerateFieldAccessorDefinitions(io::Printer* printer);
+ void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline);
// Generate the field offsets array.
void GenerateOffsets(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index b3cd0ba1..467b6bf6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -85,76 +85,141 @@ GeneratePrivateMembers(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "private:\n"
+ "void _slow_mutable_$name$()$deprecation$;\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ "void _slow_set_allocated_$name$(\n"
+ " ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n");
+ }
+ printer->Print(variables_,
+ "$type$* _slow_$release_name$()$deprecation$;\n"
+ "public:\n");
+ }
printer->Print(variables_,
- "inline const $type$& $name$() const$deprecation$;\n"
- "inline $type$* mutable_$name$()$deprecation$;\n"
- "inline $type$* $release_name$()$deprecation$;\n"
- "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ "const $type$& $name$() const$deprecation$;\n"
+ "$type$* mutable_$name$()$deprecation$;\n"
+ "$type$* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "inline $type$* unsafe_arena_release_$name$()$deprecation$;\n"
- "inline void unsafe_arena_set_allocated_$name$(\n"
+ "$type$* unsafe_arena_release_$name$()$deprecation$;\n"
+ "void unsafe_arena_set_allocated_$name$(\n"
" $type$* $name$)$deprecation$;\n");
}
}
+void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
+ io::Printer* printer) const {
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "void $classname$::_slow_mutable_$name$() {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ }
+ printer->Print(variables_,
+ "}\n"
+ "$type$* $classname$::_slow_$release_name$() {\n"
+ " if ($name$_ == NULL) {\n"
+ " return NULL;\n"
+ " } else {\n"
+ " $type$* temp = new $type$;\n"
+ " temp->MergeFrom(*$name$_);\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ "}\n"
+ "$type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " $clear_hasbit$\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ "void $classname$::_slow_set_allocated_$name$(\n"
+ " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
+ " if (message_arena != NULL && \n"
+ " ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n"
+ " message_arena->Own(*$name$);\n"
+ " } else if (message_arena !=\n"
+ " ::google::protobuf::Arena::GetArena(*$name$)) {\n"
+ " $type$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " message_arena);\n"
+ " new_$name$->CopyFrom(**$name$);\n"
+ " *$name$ = new_$name$;\n"
+ " }\n"
+ "}\n");
+ }
+ printer->Print(variables_,
+ "void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$) {\n"
+ // If we're not on an arena, free whatever we were holding before.
+ // (If we are on arena, we can just forget the earlier pointer.)
+ " if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
+ ":$full_name$)\n"
+ "}\n");
+ }
+}
+
void MessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n");
PrintHandlingOptionalStaticInitializers(
- variables_, descriptor_->file(), printer,
+ variables, descriptor_->file(), printer,
// With static initializers.
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
// Without.
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
+ printer->Print(variables,
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
- " if ($name$_ == NULL) {\n");
- if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
- } else {
- printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
- }
- printer->Print(variables_, " }\n"
+ " if ($name$_ == NULL) {\n"
+ " _slow_mutable_$name$();"
+ " }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" if (GetArenaNoVirtual() != NULL) {\n"
- " if ($name$_ == NULL) {\n"
- " return NULL;\n"
- " } else {\n"
- " $type$* temp = new $type$;\n"
- " temp->MergeFrom(*$name$_);\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
- " }\n"
+ " return _slow_$release_name$();\n"
" } else {\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
" }\n"
"}\n"
- "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
- " $clear_hasbit$\n"
- " $type$* temp = $name$_;\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " if (GetArenaNoVirtual() == NULL) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
+ " if (message_arena == NULL) {\n"
" delete $name$_;\n"
" }\n"
" if ($name$ != NULL) {\n");
@@ -164,26 +229,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
// so we might as well defer it. Otherwise, if incoming message is on a
// different ownership domain (specific arena, or the heap) than we are,
// copy to our arena (or heap, as the case may be).
- printer->Print(variables_,
- " if (GetArenaNoVirtual() != NULL && \n"
- " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
- " } else if (GetArenaNoVirtual() !=\n"
- " ::google::protobuf::Arena::GetArena($name$)) {\n"
- " $type$* new_$name$ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n"
- " new_$name$->CopyFrom(*$name$);\n"
- " $name$ = new_$name$;\n"
- " }\n");
+ printer->Print(variables,
+ " _slow_set_allocated_$name$(message_arena, &$name$);\n");
} else {
- printer->Print(variables_,
- " if (GetArenaNoVirtual() != NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
+ printer->Print(variables,
+ " if (message_arena != NULL) {\n"
+ " message_arena->Own($name$);\n"
" }\n");
}
-
- printer->Print(variables_,
+ printer->Print(variables,
" }\n"
" $name$_ = $name$;\n"
" if ($name$) {\n"
@@ -192,27 +246,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $clear_hasbit$\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
- "}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
- " $type$* $name$) {\n"
- // If we're not on an arena, free whatever we were holding before.
- // (If we are on arena, we can just forget the earlier pointer.)
- " if (GetArenaNoVirtual() == NULL) {\n"
- " delete $name$_;\n"
- " }\n"
- " $name$_ = $name$;\n"
- " if ($name$) {\n"
- " $set_hasbit$\n"
- " } else {\n"
- " $clear_hasbit$\n"
- " }\n"
- " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
- ":$full_name$)\n"
"}\n");
} else {
- printer->Print(variables_,
+ printer->Print(variables,
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" if ($name$_ == NULL) {\n"
" $name$_ = new $type$;\n"
@@ -220,17 +258,17 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" $type$* temp = $name$_;\n"
" $name$_ = NULL;\n"
" return temp;\n"
"}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
" delete $name$_;\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
" if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
" $type$* new_$name$ = new $type$;\n"
" new_$name$->CopyFrom(*$name$);\n"
@@ -238,7 +276,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" }\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" $name$_ = $name$;\n"
" if ($name$) {\n"
" $set_hasbit$\n"
@@ -328,35 +366,38 @@ MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
void MessageOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return has_$name$() ? *$oneof_prefix$$name$_\n"
" : $type$::default_instance();\n"
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
" $oneof_prefix$$name$_ = \n"
" ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
" GetArenaNoVirtual());\n");
} else {
- printer->Print(variables_,
+ printer->Print(variables,
" $oneof_prefix$$name$_ = \n"
" ::google::protobuf::Arena::Create< $type$ >(\n"
" GetArenaNoVirtual());\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $oneof_prefix$$name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" if (GetArenaNoVirtual() != NULL) {\n"
@@ -375,7 +416,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $oneof_prefix$$name$_;\n"
@@ -385,12 +426,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
" clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
// If incoming message is on the heap and we are on an arena, just Own()
// it (see above). If it's on a different arena than we are or one of us
// is on the heap, we make a copy to our arena/heap.
@@ -406,19 +447,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $name$ = new_$name$;\n"
" }\n");
} else {
- printer->Print(variables_,
+ printer->Print(variables,
" if (GetArenaNoVirtual() != NULL) {\n"
" GetArenaNoVirtual()->Own($name$);\n"
" }\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
"$type$* $name$) {\n"
// We rely on the oneof clear method to free the earlier contents of this
// oneof. We can directly use the pointer we're given to set the new
@@ -432,13 +473,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"$full_name$)\n"
"}\n");
} else {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return has_$name$() ? *$oneof_prefix$$name$_\n"
" : $type$::default_instance();\n"
"}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
+ "$inline$ $type$* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -447,7 +488,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $oneof_prefix$$name$_;\n"
"}\n"
- "inline $type$* $classname$::$release_name$() {\n"
+ "$inline$ $type$* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" $type$* temp = $oneof_prefix$$name$_;\n"
@@ -457,18 +498,18 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
" clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
- printer->Print(variables_,
+ printer->Print(variables,
" if ($name$->GetArena() != NULL) {\n"
" $type$* new_$name$ = new $type$;\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
}
- printer->Print(variables_,
+ printer->Print(variables,
" set_has_$name$();\n"
" $oneof_prefix$$name$_ = $name$;\n"
" }\n"
@@ -521,38 +562,41 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline const $type$& $name$(int index) const$deprecation$;\n"
- "inline $type$* mutable_$name$(int index)$deprecation$;\n"
- "inline $type$* add_$name$()$deprecation$;\n");
+ "const $type$& $name$(int index) const$deprecation$;\n"
+ "$type$* mutable_$name$(int index)$deprecation$;\n"
+ "$type$* add_$name$()$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
" $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "::google::protobuf::RepeatedPtrField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const $type$& $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.$cppget$(index);\n"
"}\n"
- "inline $type$* $classname$::mutable_$name$(int index) {\n"
+ "$inline$ $type$* $classname$::mutable_$name$(int index) {\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable(index);\n"
"}\n"
- "inline $type$* $classname$::add_$name$() {\n"
+ "$inline$ $type$* $classname$::add_$name$() {\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
" return $name$_.Add();\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$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 2dff3144..c1704fc1 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -53,7 +53,9 @@ class MessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
+ void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +80,9 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
~MessageOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
+ void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {}
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -96,7 +100,8 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 9a2c930e..329eae32 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -117,18 +117,20 @@ GeneratePrivateMembers(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$() const$deprecation$;\n"
- "inline void set_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$() const$deprecation$;\n"
+ "void set_$name$($type$ value)$deprecation$;\n");
}
void PrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n"
+ "$inline$ void $classname$::set_$name$($type$ value) {\n"
" $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -204,16 +206,18 @@ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
void PrimitiveOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$() const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_;\n"
" }\n"
" return $default$;\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n"
+ "$inline$ void $classname$::set_$name$($type$ value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -282,38 +286,40 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "inline $type$ $name$(int index) const$deprecation$;\n"
- "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
- "inline void add_$name$($type$ value)$deprecation$;\n");
+ "$type$ $name$(int index) const$deprecation$;\n"
+ "void set_$name$(int index, $type$ value)$deprecation$;\n"
+ "void add_$name$($type$ value)$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ "const ::google::protobuf::RepeatedField< $type$ >&\n"
" $name$() const$deprecation$;\n"
- "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ "::google::protobuf::RepeatedField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedPrimitiveFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline $type$ $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ $type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get(index);\n"
"}\n"
- "inline void $classname$::set_$name$(int index, $type$ value) {\n"
+ "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::add_$name$($type$ value) {\n"
+ "$inline$ void $classname$::add_$name$($type$ value) {\n"
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedField< $type$ >*\n"
+ "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 97b5e867..fcd7d684 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -53,7 +53,8 @@ class PrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
@@ -78,7 +79,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
~PrimitiveOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -97,7 +99,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 04ed08c9..1a1bcd3d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -127,7 +127,11 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
// files that applied the ctype. The field can still be accessed via the
// reflection interface since the reflection interface is independent of
// the string's underlying representation.
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+
+ bool unknown_ctype =
+ descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -136,23 +140,23 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "inline const ::std::string& $name$() const$deprecation$;\n"
- "inline void set_$name$(const ::std::string& value)$deprecation$;\n"
- "inline void set_$name$(const char* value)$deprecation$;\n"
- "inline void set_$name$(const $pointer_type$* value, size_t size)"
+ "const ::std::string& $name$() const$deprecation$;\n"
+ "void set_$name$(const ::std::string& value)$deprecation$;\n"
+ "void set_$name$(const char* value)$deprecation$;\n"
+ "void set_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
- "inline ::std::string* mutable_$name$()$deprecation$;\n"
- "inline ::std::string* $release_name$()$deprecation$;\n"
- "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+ "::std::string* mutable_$name$()$deprecation$;\n"
+ "::std::string* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "inline ::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
- "inline void unsafe_arena_set_allocated_$name$(\n"
+ "::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
+ "void unsafe_arena_set_allocated_$name$(\n"
" ::std::string* $name$)$deprecation$;\n");
}
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -160,25 +164,28 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
void StringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get($default_variable$);\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" $set_hasbit$\n"
" $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" $set_hasbit$\n"
" $name$_.Set($default_variable$, $string_piece$(value),\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value,\n"
" size_t size) {\n"
" $set_hasbit$\n"
@@ -186,22 +193,22 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
"}\n"
- "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" $clear_hasbit$\n"
" return $name$_.UnsafeArenaRelease($default_variable$,\n"
" GetArenaNoVirtual());\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if ($name$ != NULL) {\n"
" $set_hasbit$\n"
" } else {\n"
@@ -211,7 +218,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n"
" ::std::string* $name$) {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if ($name$ != NULL) {\n"
@@ -226,22 +233,22 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"}\n");
} else {
// No-arena case.
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.GetNoArena($default_variable$);\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value, "
"size_t size) {\n"
" $set_hasbit$\n"
@@ -249,16 +256,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $string_piece$(reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.MutableNoArena($default_variable$);\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" $clear_hasbit$\n"
" return $name$_.ReleaseNoArena($default_variable$);\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if ($name$ != NULL) {\n"
" $set_hasbit$\n"
" } else {\n"
@@ -422,17 +429,20 @@ StringOneofFieldGenerator(const FieldDescriptor* descriptor,
StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
void StringOneofFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_.Get($default_variable$);\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -442,7 +452,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -452,7 +462,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $string_piece$(value), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value,\n"
" size_t size) {\n"
" if (!has_$name$()) {\n"
@@ -465,7 +475,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -475,7 +485,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" return $oneof_prefix$$name$_.Release($default_variable$,\n"
@@ -484,7 +494,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
@@ -494,7 +504,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if (!has_$name$()) {\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
@@ -506,7 +516,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
"::std::string* $name$) {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if (!has_$name$()) {\n"
@@ -522,15 +532,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
"}\n");
} else {
// No-arena case.
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
@@ -540,7 +550,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -550,7 +560,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" $string_piece$(value));\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline "
+ "$inline$ "
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
@@ -561,7 +571,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -570,7 +580,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
"}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
+ "$inline$ ::std::string* $classname$::$release_name$() {\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
" return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
@@ -578,7 +588,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return NULL;\n"
" }\n"
"}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if (!has_$name$()) {\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
@@ -670,7 +680,10 @@ GeneratePrivateMembers(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer* printer) const {
// See comment above about unknown ctypes.
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+ bool unknown_ctype =
+ descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
+
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(
" private:\n"
@@ -679,26 +692,26 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
printer->Print(variables_,
- "inline const ::std::string& $name$(int index) const$deprecation$;\n"
- "inline ::std::string* mutable_$name$(int index)$deprecation$;\n"
- "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
- "inline void set_$name$(int index, const char* value)$deprecation$;\n"
- "inline "
+ "const ::std::string& $name$(int index) const$deprecation$;\n"
+ "::std::string* mutable_$name$(int index)$deprecation$;\n"
+ "void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
+ "void set_$name$(int index, const char* value)$deprecation$;\n"
+ ""
"void set_$name$(int index, const $pointer_type$* value, size_t size)"
"$deprecation$;\n"
- "inline ::std::string* add_$name$()$deprecation$;\n"
- "inline void add_$name$(const ::std::string& value)$deprecation$;\n"
- "inline void add_$name$(const char* value)$deprecation$;\n"
- "inline void add_$name$(const $pointer_type$* value, size_t size)"
+ "::std::string* add_$name$()$deprecation$;\n"
+ "void add_$name$(const ::std::string& value)$deprecation$;\n"
+ "void add_$name$(const char* value)$deprecation$;\n"
+ "void add_$name$(const $pointer_type$* value, size_t size)"
"$deprecation$;\n");
printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
+ "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
"$deprecation$;\n"
- "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+ "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
"$deprecation$;\n");
- if (descriptor_->options().ctype() != FieldOptions::STRING) {
+ if (unknown_ctype) {
printer->Outdent();
printer->Print(" public:\n");
printer->Indent();
@@ -706,54 +719,57 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
}
void RepeatedStringFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$(int index) const {\n"
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline" : "";
+ printer->Print(variables,
+ "$inline$ const ::std::string& $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.$cppget$(index);\n"
"}\n"
- "inline ::std::string* $classname$::mutable_$name$(int index) {\n"
+ "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable(index);\n"
"}\n"
- "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n"
+ "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" $name$_.Mutable(index)->assign(value);\n"
"}\n"
- "inline void $classname$::set_$name$(int index, const char* value) {\n"
+ "$inline$ void $classname$::set_$name$(int index, const char* value) {\n"
" $name$_.Mutable(index)->assign(value);\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "inline void "
+ "$inline$ void "
"$classname$::set_$name$"
"(int index, const $pointer_type$* value, size_t size) {\n"
" $name$_.Mutable(index)->assign(\n"
" reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "inline ::std::string* $classname$::add_$name$() {\n"
+ "$inline$ ::std::string* $classname$::add_$name$() {\n"
" return $name$_.Add();\n"
"}\n"
- "inline void $classname$::add_$name$(const ::std::string& value) {\n"
+ "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
- "inline void $classname$::add_$name$(const char* value) {\n"
+ "$inline$ void $classname$::add_$name$(const char* value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add_char:$full_name$)\n"
"}\n"
- "inline void "
+ "$inline$ void "
"$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
" $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
"}\n");
- printer->Print(variables_,
- "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+ printer->Print(variables,
+ "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+ "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 0a5ca440..d1f19cd9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -54,7 +54,8 @@ class StringFieldGenerator : public FieldGenerator {
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateStaticMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
@@ -83,7 +84,8 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
~StringOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
@@ -103,7 +105,8 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GeneratePrivateMembers(io::Printer* printer) const;
void GenerateAccessorDeclarations(io::Printer* printer) const;
- void GenerateInlineAccessorDefinitions(io::Printer* printer) const;
+ void GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
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 4fa3c144..9f63155b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -131,6 +131,24 @@ 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 DummyMessage {}
service TestConflictingMethodNames {
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
new file mode 100644
index 00000000..cb6ca1b1
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/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/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 2a04b293..cc758cf5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -794,6 +794,21 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) {
message.GetExtension(ExtensionMessage::repeated_int32_ext, 0));
}
+TEST(GeneratedMessageTest, TestConflictingEnumNames) {
+ protobuf_unittest::TestConflictingEnumNames message;
+ message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_);
+ EXPECT_EQ(1, message.conflicting_enum());
+ message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR);
+ EXPECT_EQ(5, message.conflicting_enum());
+
+
+ protobuf_unittest::ConflictingEnum conflicting_enum;
+ conflicting_enum = protobuf_unittest::NOT_EQ;
+ EXPECT_EQ(1, conflicting_enum);
+ conflicting_enum = protobuf_unittest::return_;
+ EXPECT_EQ(3, conflicting_enum);
+}
+
#ifndef PROTOBUF_TEST_NO_DESCRIPTORS
TEST(GeneratedMessageTest, TestOptimizedForSize) {
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index e8d6f3a2..1cf360c1 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -83,6 +83,7 @@ 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;
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 23685385..e24894b1 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -690,8 +690,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
for (int i = 0; i < descriptor->field_count(); i++) {
fields[i] = descriptor->field(i);
}
- sort(fields, fields + descriptor->field_count(),
- FieldOrderingByNumber());
+ std::sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByNumber());
return fields;
}
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index d957fdc4..62efbefa 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -297,6 +297,16 @@ struct ExtensionRangeOrdering {
// and return it. The caller should delete the returned array.
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor);
+// Does this message class have any packed fields?
+inline bool HasPackedFields(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (descriptor->field(i)->is_packed()) {
+ return true;
+ }
+ }
+ return false;
+}
+
// Check a message type and its sub-message types recursively to see if any of
// them has a required field. Return true if a required field is found.
bool HasRequiredFields(const Descriptor* descriptor);
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 21cab7db..6e29a40b 100644
--- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
@@ -243,9 +243,8 @@ GenerateBuildingCode(io::Printer* printer) const {
"}\n");
printer->Print(variables_,
- "result.$name$_.setByteString(\n"
- " $name$_.toByteString(),\n"
- " $name$_.getExtensionRegistry());\n");
+ "result.$name$_.set(\n"
+ " $name$_);\n");
}
void ImmutableLazyMessageFieldGenerator::
@@ -425,9 +424,8 @@ GenerateBuildingCode(io::Printer* printer) const {
printer->Print(variables_,
"result.$oneof_name$_ = new $lazy_type$();\n"
- "(($lazy_type$) result.$oneof_name$_).setByteString(\n"
- " (($lazy_type$) $oneof_name$_).toByteString(),\n"
- " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n");
+ "(($lazy_type$) result.$oneof_name$_).set(\n"
+ " (($lazy_type$) $oneof_name$_));\n");
printer->Outdent();
printer->Print("}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 2986f51f..cf1ef589 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -198,25 +198,38 @@ 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"
- " 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");
+ " $type_parameters$> $name$DefaultEntry;\n");
printer->Print(
variables_,
"private com.google.protobuf.MapField$lite$<\n"
- " $type_parameters$> $name$_ =\n"
- " com.google.protobuf.MapField$lite$.emptyMapField(\n"
- " $map_field_parameter$);\n"
- "\n");
+ " $type_parameters$> $name$_;\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " if ($name$_ == null) {\n"
+ " return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
printer->Print(
variables_,
@@ -233,7 +246,7 @@ GenerateMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
"get$capitalized_name$Value() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
}
WriteFieldDocComment(printer, descriptor_);
@@ -244,7 +257,8 @@ GenerateMembers(io::Printer* printer) const {
"get$capitalized_name$() {\n"
" return new com.google.protobuf.Internal.MapAdapter<\n"
" $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
- " $name$_.getMap(), $name$ValueConverter);\n"
+ " internalGet$capitalized_name$().getMap(),\n"
+ " $name$ValueConverter);\n"
"}\n");
} else {
WriteFieldDocComment(printer, descriptor_);
@@ -252,7 +266,7 @@ GenerateMembers(io::Printer* printer) const {
variables_,
"$deprecation$\n"
"public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
}
}
@@ -262,10 +276,24 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(
variables_,
"private com.google.protobuf.MapField$lite$<\n"
- " $type_parameters$> $name$_ =\n"
- " com.google.protobuf.MapField$lite$.newMapField(\n"
- " $map_field_parameter$);\n"
- "\n");
+ " $type_parameters$> $name$_;\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGet$capitalized_name$() {\n"
+ " if ($name$_ == null) {\n"
+ " return com.google.protobuf.MapField$lite$.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n"
+ "private com.google.protobuf.MapField$lite$<$type_parameters$>\n"
+ "internalGetMutable$capitalized_name$() {\n"
+ " $on_changed$;\n"
+ " if ($name$_ == null) {\n"
+ " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+ " $map_field_parameter$);\n"
+ " }\n"
+ " return $name$_;\n"
+ "}\n");
if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -275,7 +303,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"get$capitalized_name$() {\n"
" return new com.google.protobuf.Internal.MapAdapter<\n"
" $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
- " $name$_.getMap(), $name$ValueConverter);\n"
+ " internalGet$capitalized_name$().getMap(),\n"
+ " $name$ValueConverter);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -283,10 +312,10 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
"getMutable$capitalized_name$() {\n"
- " $on_changed$\n"
" return new com.google.protobuf.Internal.MapAdapter<\n"
" $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
- " $name$_.getMutableMap(), $name$ValueConverter);\n"
+ " internalGetMutable$capitalized_name$().getMutableMap(),\n"
+ " $name$ValueConverter);\n"
"}\n");
if (SupportUnknownEnumValue(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
@@ -295,7 +324,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
"get$capitalized_name$Value() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -303,8 +332,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$\n"
"public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
"getMutable$capitalized_name$Value() {\n"
- " $on_changed$\n"
- " return $name$_.getMutableMap();\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
}
} else {
@@ -312,15 +340,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(
variables_,
"public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
- " return $name$_.getMap();\n"
+ " return internalGet$capitalized_name$().getMap();\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(
variables_,
"public java.util.Map<$type_parameters$>\n"
"getMutable$capitalized_name$() {\n"
- " $on_changed$\n"
- " return $name$_.getMutableMap();\n"
+ " return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
}
}
@@ -339,14 +366,15 @@ void ImmutableMapFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
printer->Print(
variables_,
- "$name$_.clear();\n");
+ "internalGetMutable$capitalized_name$().clear();\n");
}
void ImmutableMapFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(
variables_,
- "$name$_.mergeFrom(other.$name$_);\n");
+ "internalGetMutable$capitalized_name$().mergeFrom(\n"
+ " other.internalGet$capitalized_name$());\n");
}
void ImmutableMapFieldGenerator::
@@ -356,7 +384,7 @@ GenerateBuildingCode(io::Printer* printer) const {
// We do a copy of the map field to ensure that the built result is
// immutable. Implementation of this copy() method can do copy-on-write
// to defer this copy until further modifications are made on the field.
- "result.$name$_ = $name$_.copy();\n");
+ "result.$name$_ = internalGet$capitalized_name$().copy();\n");
}
void ImmutableMapFieldGenerator::
@@ -402,7 +430,7 @@ GenerateSerializationCode(io::Printer* printer) const {
printer->Print(
variables_,
"for (java.util.Map.Entry<$type_parameters$> entry\n"
- " : $name$_.getMap().entrySet()) {\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
" com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
" $name$ = $name$DefaultEntry.newBuilderForType()\n"
" .setKey(entry.getKey())\n"
@@ -417,7 +445,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(
variables_,
"for (java.util.Map.Entry<$type_parameters$> entry\n"
- " : $name$_.getMap().entrySet()) {\n"
+ " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
" com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
" $name$ = $name$DefaultEntry.newBuilderForType()\n"
" .setKey(entry.getKey())\n"
@@ -432,16 +460,17 @@ void ImmutableMapFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(
variables_,
- "result = result && $name$_.equals(other.$name$_);\n");
+ "result = result && internalGet$capitalized_name$().equals(\n"
+ " other.internalGet$capitalized_name$());\n");
}
void ImmutableMapFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(
variables_,
- "if (!$name$_.getMap().isEmpty()) {\n"
+ "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n"
" hash = (37 * hash) + $constant_name$;\n"
- " hash = (53 * hash) + $name$_.hashCode();\n"
+ " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
index 80a94f45..3e6dd973 100644
--- a/src/google/protobuf/compiler/java/java_map_field.h
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -60,6 +60,7 @@ 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_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 1171b718..e982a17b 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -234,7 +234,8 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
"public interface $classname$OrBuilder extends \n"
" $extra_interfaces$\n"
" com.google.protobuf.GeneratedMessageLite.\n"
- " ExtendableMessageOrBuilder<$classname$> {\n",
+ " ExtendableMessageOrBuilder<\n"
+ " $classname$, $classname$.Builder> {\n",
"extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
"classname", descriptor_->name());
}
@@ -285,22 +286,41 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
// 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.GeneratedMessage$lite$.ExtendableMessage<\n"
- " $classname$> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n");
+ 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");
+ }
builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
- name_resolver_->GetImmutableClassName(descriptor_),
- variables["lite"]);
+ "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_),
+ variables["lite"]);
} else {
- printer->Print(variables,
- "public $static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage$lite$ implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n");
+ 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");
+ }
+
builder_type = strings::Substitute(
"com.google.protobuf.GeneratedMessage$0.Builder",
variables["lite"]);
@@ -349,7 +369,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
GenerateParsingConstructor(printer);
}
- GenerateDescriptorMethods(printer);
+ GenerateDescriptorMethods(printer, false);
GenerateParser(printer);
// Nested types
@@ -481,7 +501,7 @@ 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;",
+ "private static final $classname$ defaultInstance;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
@@ -494,15 +514,11 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
// LITE_RUNTIME only has one constructor.
printer->Print(
"static {\n"
- " try {\n"
- " defaultInstance = new $classname$(\n"
- " com.google.protobuf.Internal\n"
- " .EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
- " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " throw new ExceptionInInitializerError(e);\n"
- " }\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());
@@ -511,12 +527,30 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"public static $classname$ getDefaultInstance() {\n"
" return defaultInstance;\n"
"}\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_));
+ }
// Extensions must be declared after the defaultInstance is initialized
// because the defaultInstance is used by the extension to lazily retrieve
@@ -526,6 +560,19 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
.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");
}
@@ -542,37 +589,55 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor_->extension_range(i));
}
- sort(sorted_extensions.begin(), sorted_extensions.end(),
- ExtensionRangeOrdering());
+ 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();
- // 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 for all messages.
- // 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 (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.GeneratedMessage$lite$\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
- " newMessageSetExtensionWriter();\n",
- "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ 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_));
+ }
} else {
- printer->Print(
- "com.google.protobuf.GeneratedMessage$lite$\n"
- " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n"
- " newExtensionWriter();\n",
- "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ 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_));
+ }
}
}
@@ -727,13 +792,23 @@ 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");
+ }
+
printer->Print(
- "public static Builder newBuilder() { return new Builder(); }\n"
- "public Builder newBuilderForType() { return newBuilder(); }\n"
+ "public static Builder newBuilder() {\n"
+ " return defaultInstance.toBuilder();\n"
+ "}\n"
"public static Builder newBuilder($classname$ prototype) {\n"
- " return newBuilder().mergeFrom(prototype);\n"
+ " return defaultInstance.toBuilder().mergeFrom(prototype);\n"
+ "}\n"
+ "public Builder toBuilder() {\n"
+ " return this == defaultInstance\n"
+ " ? new Builder() : new Builder().mergeFrom(this);\n"
"}\n"
- "public Builder toBuilder() { return newBuilder(this); }\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -792,7 +867,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
}
printer->Indent();
- GenerateDescriptorMethods(printer);
+ GenerateDescriptorMethods(printer, true);
GenerateCommonBuilderMethods(printer);
if (HasGeneratedMethods(descriptor_)) {
@@ -876,7 +951,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
}
void ImmutableMessageGenerator::
-GenerateDescriptorMethods(io::Printer* printer) {
+GenerateDescriptorMethods(io::Printer* printer, bool is_builder) {
if (HasDescriptorMethods(descriptor_)) {
if (!descriptor_->options().no_standard_descriptor_accessor()) {
printer->Print(
@@ -909,9 +984,9 @@ GenerateDescriptorMethods(io::Printer* printer) {
const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
printer->Print(
"case $number$:\n"
- " return $name$_;\n",
+ " return internalGet$capitalized_name$();\n",
"number", SimpleItoa(field->number()),
- "name", info->name);
+ "capitalized_name", info->capitalized_name);
}
printer->Print(
"default:\n"
@@ -922,6 +997,34 @@ GenerateDescriptorMethods(io::Printer* printer) {
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");
+ }
}
printer->Print(
"protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
@@ -959,7 +1062,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
"classname", name_resolver_->GetImmutableClassName(descriptor_));
} else {
// LITE runtime passes along the default instance to implement
- // getDefaultInstanceForType() at the GneratedMessageLite level.
+ // getDefaultInstanceForType() at the GeneratedMessageLite level.
printer->Print(
"// Construct using $classname$.newBuilder()\n"
"private Builder() {\n"
@@ -1062,22 +1165,17 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
"public $classname$ buildPartial() {\n"
- " $classname$ result = new $classname$(this);\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ " $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 = null;\n"
- " try {\n"
- " result = new $classname$(\n"
- " com.google.protobuf.Internal\n"
- " .EMPTY_CODED_INPUT_STREAM,\n"
- " com.google.protobuf.ExtensionRegistryLite\n"
- " .getEmptyRegistry());\n"
- " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " throw new RuntimeException(e);\n"
- " }\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_));
@@ -1271,6 +1369,12 @@ GenerateBuilderParsingMethods(io::Printer* printer) {
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
@@ -1558,8 +1662,7 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Print(
"private $classname$(\n"
" com.google.protobuf.CodedInputStream input,\n"
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
- " throws com.google.protobuf.InvalidProtocolBufferException {\n",
+ " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n",
"classname", descriptor_->name());
printer->Indent();
@@ -1695,10 +1798,11 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Outdent();
printer->Print(
"} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " throw e.setUnfinishedMessage(this);\n"
+ " throw new RuntimeException(e.setUnfinishedMessage(this));\n"
"} catch (java.io.IOException e) {\n"
- " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
- " e.getMessage()).setUnfinishedMessage(this);\n"
+ " throw new RuntimeException(\n"
+ " new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " e.getMessage()).setUnfinishedMessage(this));\n"
"} finally {\n");
printer->Indent();
@@ -1747,8 +1851,19 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
" throws com.google.protobuf.InvalidProtocolBufferException {\n",
"classname", descriptor_->name());
if (HasGeneratedMethods(descriptor_)) {
+ // The parsing constructor throws an InvalidProtocolBufferException via a
+ // RuntimeException to aid in method pruning. We unwrap it here.
printer->Print(
- " return new $classname$(input, extensionRegistry);\n",
+ " try {\n"
+ " return new $classname$(input, extensionRegistry);\n"
+ " } catch (RuntimeException e) {\n"
+ " if (e.getCause() instanceof\n"
+ " com.google.protobuf.InvalidProtocolBufferException) {\n"
+ " throw (com.google.protobuf.InvalidProtocolBufferException)\n"
+ " e.getCause();\n"
+ " }\n"
+ " throw e;\n"
+ " }\n",
"classname", descriptor_->name());
} else {
// When parsing constructor isn't generated, use builder to parse messages.
@@ -1775,13 +1890,16 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
"};\n"
"\n");
- printer->Print(
- "@java.lang.Override\n"
- "public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
- " return PARSER;\n"
- "}\n"
- "\n",
- "classname", descriptor_->name());
+ 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());
+ }
}
// ===================================================================
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 91eb2876..016fdd5d 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -117,7 +117,7 @@ class ImmutableMessageGenerator : public MessageGenerator {
void GenerateBuilder(io::Printer* printer);
void GenerateCommonBuilderMethods(io::Printer* printer);
- void GenerateDescriptorMethods(io::Printer* printer);
+ void GenerateDescriptorMethods(io::Printer* printer, bool is_builder);
void GenerateBuilderParsingMethods(io::Printer* printer);
void GenerateIsInitialized(io::Printer* printer,
UseMemoization useMemoization);
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index 538f1248..a2d12a38 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -718,6 +718,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" $oneof_name$_ = null;\n"
" }\n"
" $set_oneof_case_message$;\n"
+ " $on_changed$;\n"
" return $name$Builder_;\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index e331d7a4..48757c60 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -772,6 +772,9 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void RepeatedImmutablePrimitiveFieldGenerator::
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"
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 2e61ea8a..70177367 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -171,7 +171,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
string classname = FileJavaPackage(file_->dependency(i)) + "." +
name_resolver_->GetDescriptorClassName(
file_->dependency(i));
- dependencies.push_back(make_pair(filename, classname));
+ dependencies.push_back(std::make_pair(filename, classname));
}
}
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 1c9302af..8aa5699c 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -667,7 +667,7 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"String s = input.readStringRequireUtf8();\n"
"$set_oneof_case_message$;\n"
- "$oneof_name$_ = s;\n}\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
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
index e3e4cefe..85257f3f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/compiler/javanano/javanano_helpers.h>
#include <google/protobuf/compiler/javanano/javanano_primitive_field.h>
#include <google/protobuf/compiler/javanano/javanano_enum_field.h>
+#include <google/protobuf/compiler/javanano/javanano_map_field.h>
#include <google/protobuf/compiler/javanano/javanano_message_field.h>
#include <google/protobuf/stubs/common.h>
@@ -97,12 +98,24 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field,
if (field->is_repeated()) {
switch (java_type) {
case JAVATYPE_MESSAGE:
- return new RepeatedMessageFieldGenerator(field, params);
+ if (IsMapEntry(field->message_type())) {
+ return new MapFieldGenerator(field, params);
+ } else {
+ return new RepeatedMessageFieldGenerator(field, params);
+ }
case JAVATYPE_ENUM:
return new RepeatedEnumFieldGenerator(field, params);
default:
return new RepeatedPrimitiveFieldGenerator(field, params);
}
+ } else if (field->containing_oneof()) {
+ switch (java_type) {
+ case JAVATYPE_MESSAGE:
+ return new MessageOneofFieldGenerator(field, params);
+ case JAVATYPE_ENUM:
+ default:
+ return new PrimitiveOneofFieldGenerator(field, params);
+ }
} else if (params.optional_field_accessors() && field->is_optional()
&& java_type != JAVATYPE_MESSAGE) {
// We need a has-bit for each primitive/enum field because their default
@@ -137,6 +150,59 @@ const FieldGenerator& FieldGeneratorMap::get(
return *field_generators_[field->index()];
}
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ (*variables)["oneof_name"] =
+ UnderscoresToCamelCase(descriptor->containing_oneof());
+ (*variables)["oneof_capitalized_name"] =
+ UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof());
+ (*variables)["oneof_index"] =
+ SimpleItoa(descriptor->containing_oneof()->index());
+ (*variables)["set_oneof_case"] =
+ "this." + (*variables)["oneof_name"] +
+ "Case_ = " + SimpleItoa(descriptor->number());
+ (*variables)["clear_oneof_case"] =
+ "this." + (*variables)["oneof_name"] + "Case_ = 0";
+ (*variables)["has_oneof_case"] =
+ "this." + (*variables)["oneof_name"] + "Case_ == " +
+ SimpleItoa(descriptor->number());
+}
+
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer) {
+ if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+ printer->Print(variables,
+ "if (this.has$capitalized_name$()) {\n"
+ " if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n"
+ " (byte[]) other.$oneof_name$_)) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n");
+ } else {
+ printer->Print(variables,
+ "if (this.has$capitalized_name$()) {\n"
+ " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n"
+ " return false;\n"
+ " }\n"
+ "}\n");
+ }
+}
+
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer) {
+ if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
+ printer->Print(variables,
+ "result = 31 * result + ($has_oneof_case$\n"
+ " ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n");
+ } else {
+ printer->Print(variables,
+ "result = 31 * result +\n"
+ " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n");
+ }
+}
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
index 6170c2c0..c2cf091c 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -35,6 +35,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__
+#include <map>
#include <string>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
@@ -111,6 +112,15 @@ class FieldGeneratorMap {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
};
+void SetCommonOneofVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables);
+void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer);
+void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
+ const map<string, string>& variables,
+ io::Printer* printer);
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 2149418a..0d2ae9db 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -154,6 +154,14 @@ string UnderscoresToCamelCase(const MethodDescriptor* method) {
return UnderscoresToCamelCaseImpl(method->name(), false);
}
+string UnderscoresToCamelCase(const OneofDescriptor* oneof) {
+ return UnderscoresToCamelCaseImpl(oneof->name(), false);
+}
+
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) {
+ return UnderscoresToCamelCaseImpl(oneof->name(), true);
+}
+
string RenameJavaKeywords(const string& input) {
return sRenameKeywords.RenameJavaKeywordsImpl(input);
}
@@ -560,6 +568,17 @@ void SetBitOperationVariables(const string name,
(*variables)["different_" + name] = GenerateDifferentBit(bitIndex);
}
+bool HasMapField(const Descriptor* descriptor) {
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ const FieldDescriptor* field = descriptor->field(i);
+ if (field->type() == FieldDescriptor::TYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
index 29310743..014c85ae 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.h
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -54,7 +54,9 @@ extern const char kThinSeparator[];
// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
// "fooBarBaz" or "FooBarBaz", respectively.
string UnderscoresToCamelCase(const FieldDescriptor* field);
+string UnderscoresToCamelCase(const OneofDescriptor* oneof);
string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
+string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof);
// Appends an "_" to the end of a field where the name is a reserved java
// keyword. For example int32 public = 1 will generate int public_.
@@ -181,6 +183,14 @@ string GenerateDifferentBit(int bit_index);
void SetBitOperationVariables(const string name,
int bitIndex, map<string, string>* variables);
+inline bool IsMapEntry(const Descriptor* descriptor) {
+ // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
+ return descriptor->options().map_entry() &&
+ descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+bool HasMapField(const Descriptor* descriptor);
+
} // namespace javanano
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
new file mode 100644
index 00000000..83b2b0ce
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
@@ -0,0 +1,186 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/javanano/javanano_map_field.h>
+#include <google/protobuf/compiler/javanano/javanano_helpers.h>
+#include <google/protobuf/stubs/common.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 javanano {
+
+namespace {
+
+string TypeName(const Params& params, const FieldDescriptor* field,
+ bool boxed) {
+ JavaType java_type = GetJavaType(field);
+ switch (java_type) {
+ case JAVATYPE_MESSAGE:
+ return ClassName(params, field->message_type());
+ case JAVATYPE_INT:
+ case JAVATYPE_LONG:
+ case JAVATYPE_FLOAT:
+ case JAVATYPE_DOUBLE:
+ case JAVATYPE_BOOLEAN:
+ case JAVATYPE_STRING:
+ case JAVATYPE_BYTES:
+ case JAVATYPE_ENUM:
+ if (boxed) {
+ return BoxedPrimitiveTypeName(java_type);
+ } else {
+ return PrimitiveTypeName(java_type);
+ }
+ // No default because we want the compiler to complain if any new JavaTypes
+ // are added..
+ }
+
+ GOOGLE_LOG(FATAL) << "should not reach here.";
+ return "";
+}
+
+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");
+}
+
+void SetMapVariables(const Params& params,
+ const FieldDescriptor* descriptor, map<string, string>* variables) {
+ const FieldDescriptor* key = KeyField(descriptor);
+ const FieldDescriptor* value = ValueField(descriptor);
+ (*variables)["name"] =
+ RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
+ (*variables)["number"] = SimpleItoa(descriptor->number());
+ (*variables)["key_type"] = TypeName(params, key, false);
+ (*variables)["boxed_key_type"] = TypeName(params,key, true);
+ (*variables)["key_desc_type"] =
+ "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type()));
+ (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key));
+ (*variables)["value_type"] = TypeName(params, value, false);
+ (*variables)["boxed_value_type"] = TypeName(params, value, true);
+ (*variables)["value_desc_type"] =
+ "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type()));
+ (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value));
+ (*variables)["type_parameters"] =
+ (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+ (*variables)["value_default"] =
+ value->type() == FieldDescriptor::TYPE_MESSAGE
+ ? "new " + (*variables)["value_type"] + "()"
+ : "null";
+}
+} // namespace
+
+// ===================================================================
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetMapVariables(params, descriptor, &variables_);
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public java.util.Map<$type_parameters$> $name$;\n");
+}
+
+void MapFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "$name$ = null;\n");
+}
+
+void MapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n"
+ " input, this.$name$, mapFactory,\n"
+ " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+ " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n"
+ " $value_default$,\n"
+ " $key_tag$, $value_tag$);\n"
+ "\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " com.google.protobuf.nano.InternalNano.serializeMapField(\n"
+ " output, this.$name$, $number$,\n"
+ " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+ " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+ "}\n");
+}
+
+void MapFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n"
+ " this.$name$, $number$,\n"
+ " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n"
+ " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n"
+ "}\n");
+}
+
+void MapFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!com.google.protobuf.nano.InternalNano.equals(\n"
+ " this.$name$, other.$name$)) {\n"
+ " return false;\n"
+ "}\n");
+}
+
+void MapFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "result = 31 * result +\n"
+ " com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n");
+}
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h
new file mode 100644
index 00000000..c01bde38
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.h
@@ -0,0 +1,70 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include <google/protobuf/compiler/javanano/javanano_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace javanano {
+
+class MapFieldGenerator : public FieldGenerator {
+ public:
+ explicit MapFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
+ ~MapFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+} // namespace javanano
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
index 7c52ca31..707f6b84 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -90,6 +90,7 @@ void MessageGenerator::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?
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
MessageGenerator(descriptor_->nested_type(i), params_)
.GenerateStaticVariables(printer);
}
@@ -100,6 +101,7 @@ void MessageGenerator::GenerateStaticVariableInitializers(
// Generate static member initializers for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
MessageGenerator(descriptor_->nested_type(i), params_)
.GenerateStaticVariableInitializers(printer);
}
@@ -159,9 +161,44 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer);
}
+ // oneof
+ map<string, string> vars;
+ vars["message_name"] = descriptor_->name();
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+ vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc);
+ vars["oneof_capitalized_name"] =
+ UnderscoresToCapitalizedCamelCase(oneof_desc);
+ vars["oneof_index"] = SimpleItoa(oneof_desc->index());
+ // Oneof Constants
+ for (int j = 0; j < oneof_desc->field_count(); j++) {
+ const FieldDescriptor* field = oneof_desc->field(j);
+ vars["number"] = SimpleItoa(field->number());
+ vars["cap_field_name"] = ToUpper(field->name());
+ printer->Print(vars,
+ "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n");
+ }
+ // oneofCase_ and oneof_
+ printer->Print(vars,
+ "private int $oneof_name$Case_ = 0;\n"
+ "private java.lang.Object $oneof_name$_;\n");
+ printer->Print(vars,
+ "public int get$oneof_capitalized_name$Case() {\n"
+ " return this.$oneof_name$Case_;\n"
+ "}\n");
+ // Oneof clear
+ printer->Print(vars,
+ "public $message_name$ clear$oneof_capitalized_name$() {\n"
+ " this.$oneof_name$Case_ = 0;\n"
+ " this.$oneof_name$_ = null;\n"
+ " return this;\n"
+ "}\n");
+ }
+
// Lazy initialization of otherwise static final fields can help prevent the
// class initializer from being generated. We want to prevent it because it
// stops ProGuard from inlining any methods in this class into call sites and
@@ -342,6 +379,11 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) {
"classname", descriptor_->name());
printer->Indent();
+ if (HasMapField(descriptor_)) {
+ printer->Print(
+ "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n"
+ " com.google.protobuf.nano.MapFactories.getMapFactory();\n");
+ }
printer->Print(
"while (true) {\n");
@@ -466,6 +508,14 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
field_generators_.get(field).GenerateClearCode(printer);
}
+ // Clear oneofs.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "clear$oneof_capitalized_name$();\n",
+ "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase(
+ descriptor_->oneof_decl(i)));
+ }
+
// Clear unknown fields.
if (params_.store_unknown_fields()) {
printer->Print("unknownFieldData = null;\n");
@@ -501,6 +551,16 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) {
"$classname$ other = ($classname$) o;\n",
"classname", descriptor_->name());
+ // Checking oneof case before checking each oneof field.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
+ printer->Print(
+ "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n"
+ " return false;\n"
+ "}\n",
+ "oneof_name", UnderscoresToCamelCase(oneof_desc));
+ }
+
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
field_generators_.get(field).GenerateEqualsCode(printer);
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
index a46081d0..181c4060 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -146,12 +146,87 @@ GenerateHashCodeCode(io::Printer* printer) const {
"result = 31 * result +\n"
" (this.$name$ == null ? 0 : this.$name$.hashCode());\n");
}
+// ===================================================================
+
+MessageOneofFieldGenerator::MessageOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetMessageVariables(params, descriptor, &variables_);
+ SetCommonOneofVariables(descriptor, &variables_);
+}
+
+MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::
+GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_,
+ "public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case$;\n"
+ "}\n"
+ "public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case$) {\n"
+ " return ($type$) this.$oneof_name$_;\n"
+ " }\n"
+ " return null;\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$($type$ value) {\n"
+ " if (value == null) { throw new java.lang.NullPointerException(); }\n"
+ " $set_oneof_case$;\n"
+ " this.$oneof_name$_ = value;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateClearCode(io::Printer* printer) const {
+ // No clear method for oneof fields.
+}
+
+void MessageOneofFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (!($has_oneof_case$)) {\n"
+ " this.$oneof_name$_ = new $type$();\n"
+ "}\n"
+ "input.readMessage(\n"
+ " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+ "$set_oneof_case$;\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " output.writeMessage($number$,\n"
+ " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .computeMessageSize($number$,\n"
+ " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateHashCodeCode(io::Printer* printer) const {
+ GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
// ===================================================================
-RepeatedMessageFieldGenerator::
-RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
- : FieldGenerator(params), descriptor_(descriptor) {
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
SetMessageVariables(params, descriptor, &variables_);
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
index 5d35fd24..6c615f5e 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -66,6 +66,28 @@ class MessageFieldGenerator : public FieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
};
+class MessageOneofFieldGenerator : public FieldGenerator {
+ public:
+ explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params);
+ ~MessageOneofFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
+};
+
class RepeatedMessageFieldGenerator : public FieldGenerator {
public:
explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
index a3bc3a84..41bad0a6 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -155,28 +155,6 @@ int FixedSize(FieldDescriptor::Type type) {
return -1;
}
-// Return true if the type is a that has variable length
-// for instance String's.
-bool IsVariableLenType(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return false;
- case JAVATYPE_LONG : return false;
- case JAVATYPE_FLOAT : return false;
- case JAVATYPE_DOUBLE : return false;
- case JAVATYPE_BOOLEAN: return false;
- case JAVATYPE_STRING : return true;
- case JAVATYPE_BYTES : return true;
- case JAVATYPE_ENUM : return false;
- case JAVATYPE_MESSAGE: return true;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return false;
-}
-
bool AllAscii(const string& text) {
for (int i = 0; i < text.size(); i++) {
if ((text[i] & 0x80) != 0) {
@@ -186,6 +164,7 @@ bool AllAscii(const string& text) {
return true;
}
+
void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
map<string, string>* variables) {
(*variables)["name"] =
@@ -706,8 +685,79 @@ GenerateHashCodeCode(io::Printer* printer) const {
// ===================================================================
-RepeatedPrimitiveFieldGenerator::
-RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params)
+PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
+ : FieldGenerator(params), descriptor_(descriptor) {
+ SetPrimitiveVariables(descriptor, params, &variables_);
+ SetCommonOneofVariables(descriptor, &variables_);
+}
+
+PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
+
+void PrimitiveOneofFieldGenerator::GenerateMembers(
+ io::Printer* printer, bool /*unused lazy_init*/) const {
+ printer->Print(variables_,
+ "public boolean has$capitalized_name$() {\n"
+ " return $has_oneof_case$;\n"
+ "}\n"
+ "public $type$ get$capitalized_name$() {\n"
+ " if ($has_oneof_case$) {\n"
+ " return ($type$) ($boxed_type$) this.$oneof_name$_;\n"
+ " }\n"
+ " return $default$;\n"
+ "}\n"
+ "public $message_name$ set$capitalized_name$($type$ value) {\n"
+ " $set_oneof_case$;\n"
+ " this.$oneof_name$_ = value;\n"
+ " return this;\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateClearCode(
+ io::Printer* printer) const {
+ // No clear method for oneof fields.
+}
+
+void PrimitiveOneofFieldGenerator::GenerateMergingCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "this.$oneof_name$_ = input.read$capitalized_type$();\n"
+ "$set_oneof_case$;\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializationCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " output.write$capitalized_type$(\n"
+ " $number$, ($boxed_type$) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode(
+ io::Printer* printer) const {
+ printer->Print(variables_,
+ "if ($has_oneof_case$) {\n"
+ " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
+ " .compute$capitalized_type$Size(\n"
+ " $number$, ($boxed_type$) this.$oneof_name$_);\n"
+ "}\n");
+}
+
+void PrimitiveOneofFieldGenerator::GenerateEqualsCode(
+ io::Printer* printer) const {
+ GenerateOneofFieldEquals(descriptor_, variables_, printer);
+}
+
+void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(
+ io::Printer* printer) const {
+ GenerateOneofFieldHashCode(descriptor_, variables_, printer);
+}
+
+// ===================================================================
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params)
: FieldGenerator(params), descriptor_(descriptor) {
SetPrimitiveVariables(descriptor, params, &variables_);
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
index c04a19b7..ca7116ff 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -47,7 +47,7 @@ namespace javanano {
class PrimitiveFieldGenerator : public FieldGenerator {
public:
explicit PrimitiveFieldGenerator(
- const FieldDescriptor* descriptor, const Params &params);
+ const FieldDescriptor* descriptor, const Params& params);
~PrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
@@ -94,9 +94,32 @@ class AccessorPrimitiveFieldGenerator : public FieldGenerator {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
};
+class PrimitiveOneofFieldGenerator : public FieldGenerator {
+ public:
+ explicit PrimitiveOneofFieldGenerator(
+ const FieldDescriptor* descriptor, const Params& params);
+ ~PrimitiveOneofFieldGenerator();
+
+ // implements FieldGenerator ---------------------------------------
+ void GenerateMembers(io::Printer* printer, bool lazy_init) const;
+ void GenerateClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCodeCode(io::Printer* printer) const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
+};
+
class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
public:
- explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params);
+ explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
+ const Params& params);
~RepeatedPrimitiveFieldGenerator();
// implements FieldGenerator ---------------------------------------
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index e7d5117e..98261431 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -133,10 +133,10 @@ bool MockCodeGenerator::Generate(
*error = "Saw message type MockCodeGenerator_Error.";
return false;
} else if (command == "Exit") {
- cerr << "Saw message type MockCodeGenerator_Exit." << endl;
+ std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl;
exit(123);
} else if (command == "Abort") {
- cerr << "Saw message type MockCodeGenerator_Abort." << endl;
+ std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl;
abort();
} else if (command == "HasSourceCodeInfo") {
FileDescriptorProto file_descriptor_proto;
@@ -144,8 +144,8 @@ bool MockCodeGenerator::Generate(
bool has_source_code_info =
file_descriptor_proto.has_source_code_info() &&
file_descriptor_proto.source_code_info().location_size() > 0;
- cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
- << has_source_code_info << "." << endl;
+ std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: "
+ << has_source_code_info << "." << std::endl;
abort();
} else {
GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index fe697acf..c50cdf54 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -277,27 +277,39 @@ bool Parser::ConsumeString(string* output, const char* error) {
}
}
-bool Parser::TryConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location) {
+bool Parser::TryConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location) {
if (LookingAt(text)) {
string leading, trailing;
- input_->NextWithComments(&trailing, NULL, &leading);
+ vector<string> detached;
+ input_->NextWithComments(&trailing, &detached, &leading);
// Save the leading comments for next time, and recall the leading comments
// from last time.
leading.swap(upcoming_doc_comments_);
if (location != NULL) {
- location->AttachComments(&leading, &trailing);
+ upcoming_detached_comments_.swap(detached);
+ location->AttachComments(&leading, &trailing, &detached);
+ } else if (strcmp(text, "}") == 0) {
+ // If the current location is null and we are finishing the current scope,
+ // drop pending upcoming detached comments.
+ upcoming_detached_comments_.swap(detached);
+ } else {
+ // Otherwise, append the new detached comments to the existing upcoming
+ // detached comments.
+ upcoming_detached_comments_.insert(upcoming_detached_comments_.end(),
+ detached.begin(), detached.end());
}
+
return true;
} else {
return false;
}
}
-bool Parser::ConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location) {
+bool Parser::ConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location) {
if (TryConsumeEndOfDeclaration(text, location)) {
return true;
} else {
@@ -390,7 +402,8 @@ void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor,
}
void Parser::LocationRecorder::AttachComments(
- string* leading, string* trailing) const {
+ string* leading, string* trailing,
+ vector<string>* detached_comments) const {
GOOGLE_CHECK(!location_->has_leading_comments());
GOOGLE_CHECK(!location_->has_trailing_comments());
@@ -400,6 +413,11 @@ void Parser::LocationRecorder::AttachComments(
if (!trailing->empty()) {
location_->mutable_trailing_comments()->swap(*trailing);
}
+ for (int i = 0; i < detached_comments->size(); ++i) {
+ location_->add_leading_detached_comments()->swap(
+ (*detached_comments)[i]);
+ }
+ detached_comments->clear();
}
// -------------------------------------------------------------------
@@ -451,16 +469,18 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
SourceCodeInfo source_code_info;
source_code_info_ = &source_code_info;
+ vector<string> top_doc_comments;
if (LookingAtType(io::Tokenizer::TYPE_START)) {
// Advance to first token.
- input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
+ input_->NextWithComments(NULL, &upcoming_detached_comments_,
+ &upcoming_doc_comments_);
}
{
LocationRecorder root_location(this);
if (require_syntax_identifier_ || LookingAt("syntax")) {
- if (!ParseSyntaxIdentifier()) {
+ if (!ParseSyntaxIdentifier(root_location)) {
// Don't attempt to parse the file if we didn't recognize the syntax
// identifier.
return false;
@@ -469,9 +489,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
if (file != NULL) file->set_syntax(syntax_identifier_);
} else if (!stop_after_syntax_identifier_) {
GOOGLE_LOG(WARNING) << "No syntax specified for the proto file. "
- << "Please use 'syntax = \"proto2\";' or "
- << "'syntax = \"proto3\";' to specify a syntax "
- << "version. (Defaulted to proto2 syntax.)";
+ << "Please use 'syntax = \"proto2\";' or "
+ << "'syntax = \"proto3\";' to specify a syntax "
+ << "version. (Defaulted to proto2 syntax.)";
syntax_identifier_ = "proto2";
}
@@ -486,7 +506,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
if (LookingAt("}")) {
AddError("Unmatched \"}\".");
- input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_);
+ input_->NextWithComments(NULL, &upcoming_detached_comments_,
+ &upcoming_doc_comments_);
}
}
}
@@ -498,7 +519,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
return !had_errors_;
}
-bool Parser::ParseSyntaxIdentifier() {
+bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) {
+ LocationRecorder syntax_location(parent,
+ FileDescriptorProto::kSyntaxFieldNumber);
DO(Consume(
"syntax",
"File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
@@ -506,7 +529,7 @@ bool Parser::ParseSyntaxIdentifier() {
io::Tokenizer::Token syntax_token = input_->current();
string syntax;
DO(ConsumeString(&syntax, "Expected syntax identifier."));
- DO(ConsumeEndOfDeclaration(";", NULL));
+ DO(ConsumeEndOfDeclaration(";", &syntax_location));
syntax_identifier_ = syntax;
@@ -1271,7 +1294,6 @@ bool Parser::ParseOption(Message* options,
DO(ConsumeEndOfDeclaration(";", &location));
}
-
return true;
}
@@ -1636,8 +1658,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
// Parse input type.
DO(Consume("("));
{
- if (TryConsume("stream")) {
+ if (LookingAt("stream")) {
+ LocationRecorder location(
+ method_location, MethodDescriptorProto::kClientStreamingFieldNumber);
+ location.RecordLegacyLocation(
+ method, DescriptorPool::ErrorCollector::OTHER);
method->set_client_streaming(true);
+ DO(Consume("stream"));
+
}
LocationRecorder location(method_location,
MethodDescriptorProto::kInputTypeFieldNumber);
@@ -1651,8 +1679,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
DO(Consume("returns"));
DO(Consume("("));
{
- if (TryConsume("stream")) {
+ if (LookingAt("stream")) {
+ LocationRecorder location(
+ method_location, MethodDescriptorProto::kServerStreamingFieldNumber);
+ location.RecordLegacyLocation(
+ method, DescriptorPool::ErrorCollector::OTHER);
+ DO(Consume("stream"));
method->set_server_streaming(true);
+
}
LocationRecorder location(method_location,
MethodDescriptorProto::kOutputTypeFieldNumber);
@@ -1664,10 +1698,9 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
if (LookingAt("{")) {
// Options!
- DO(ParseOptions(method_location,
- containing_file,
- MethodDescriptorProto::kOptionsFieldNumber,
- method->mutable_options()));
+ DO(ParseMethodOptions(method_location, containing_file,
+ MethodDescriptorProto::kOptionsFieldNumber,
+ method->mutable_options()));
} else {
DO(ConsumeEndOfDeclaration(";", &method_location));
}
@@ -1676,10 +1709,10 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
}
-bool Parser::ParseOptions(const LocationRecorder& parent_location,
- const FileDescriptorProto* containing_file,
- const int optionsFieldNumber,
- Message* mutable_options) {
+bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
+ const FileDescriptorProto* containing_file,
+ const int optionsFieldNumber,
+ Message* mutable_options) {
// Options!
ConsumeEndOfDeclaration("{", &parent_location);
while (!TryConsumeEndOfDeclaration("}", NULL)) {
@@ -1693,8 +1726,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location,
} else {
LocationRecorder location(parent_location,
optionsFieldNumber);
- if (!ParseOption(mutable_options, location, containing_file,
- OPTION_STATEMENT)) {
+ if (!ParseOption(mutable_options, location,
+ containing_file, OPTION_STATEMENT)) {
// This statement failed to parse. Skip it, but keep looping to
// parse other statements.
SkipStatement();
@@ -1847,7 +1880,7 @@ bool SourceLocationTable::Find(
DescriptorPool::ErrorCollector::ErrorLocation location,
int* line, int* column) const {
const pair<int, int>* result =
- FindOrNull(location_map_, make_pair(descriptor, location));
+ FindOrNull(location_map_, std::make_pair(descriptor, location));
if (result == NULL) {
*line = -1;
*column = 0;
@@ -1863,7 +1896,8 @@ void SourceLocationTable::Add(
const Message* descriptor,
DescriptorPool::ErrorCollector::ErrorLocation location,
int line, int column) {
- location_map_[make_pair(descriptor, location)] = make_pair(line, column);
+ location_map_[std::make_pair(descriptor, location)] =
+ std::make_pair(line, column);
}
void SourceLocationTable::Clear() {
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index a15cc705..7cb1678a 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -185,10 +185,13 @@ class LIBPROTOBUF_EXPORT Parser {
// have been passed around by const reference, for no particularly good
// reason. We should probably go through and change them all to mutable
// pointer to make this more intuitive.
- bool TryConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location);
- bool ConsumeEndOfDeclaration(const char* text,
- const LocationRecorder* location);
+ bool TryConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location);
+ bool TryConsumeEndOfDeclarationFinishScope(
+ const char* text, const LocationRecorder* location);
+
+ bool ConsumeEndOfDeclaration(
+ const char* text, const LocationRecorder* location);
// -----------------------------------------------------------------
// Error logging helpers
@@ -253,9 +256,13 @@ class LIBPROTOBUF_EXPORT Parser {
//
// TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for
// why this is const.
- void AttachComments(string* leading, string* trailing) const;
+ void AttachComments(string* leading, string* trailing,
+ vector<string>* detached_comments) const;
private:
+ // Indexes of parent and current location in the parent
+ // SourceCodeInfo.location repeated field. For top-level elements,
+ // parent_index_ is -1.
Parser* parser_;
SourceCodeInfo::Location* location_;
@@ -268,7 +275,7 @@ class LIBPROTOBUF_EXPORT Parser {
// Parses the "syntax = \"proto2\";" line at the top of the file. Returns
// false if it failed to parse or if the syntax identifier was not
// recognized.
- bool ParseSyntaxIdentifier();
+ bool ParseSyntaxIdentifier(const LocationRecorder& parent);
// These methods parse various individual bits of code. They return
// false if they completely fail to parse the construct. In this case,
@@ -302,9 +309,6 @@ class LIBPROTOBUF_EXPORT Parser {
RepeatedField<int32>* weak_dependency,
const LocationRecorder& root_location,
const FileDescriptorProto* containing_file);
- bool ParseOption(Message* options,
- const LocationRecorder& options_location,
- const FileDescriptorProto* containing_file);
// These methods parse the contents of a message, enum, or service type and
// add them to the given object. They consume the entire block including
@@ -397,10 +401,10 @@ class LIBPROTOBUF_EXPORT Parser {
// Parse options of a single method or stream.
- bool ParseOptions(const LocationRecorder& parent_location,
- const FileDescriptorProto* containing_file,
- const int optionsFieldNumber,
- Message* mutable_options);
+ bool ParseMethodOptions(const LocationRecorder& parent_location,
+ const FileDescriptorProto* containing_file,
+ const int optionsFieldNumber,
+ Message* mutable_options);
// Parse "required", "optional", or "repeated" and fill in "label"
// with the value. Returns true if shuch a label is consumed.
@@ -497,6 +501,13 @@ class LIBPROTOBUF_EXPORT Parser {
// yet; use ConsumeEndOfDeclaration() to get the complete comments.
string upcoming_doc_comments_;
+ // Detached comments are not connected to any syntax entities. Elements in
+ // this vector are paragraphs of comments separated by empty lines. The
+ // detached comments will be put into the leading_detached_comments field for
+ // the next element (See SourceCodeInfo.Location in descriptor.proto), when
+ // ConsumeEndOfDeclaration() is called.
+ vector<string> upcoming_detached_comments_;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
};
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 638a83b9..1684bebe 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -401,13 +401,27 @@ TEST_F(ParseMessageTest, FieldDefaults) {
" field { type:TYPE_BOOL default_value:\"true\" " ETC " }"
" field { type_name:\"Foo\" default_value:\"FOO\" " ETC " }"
- " field { type:TYPE_INT32 default_value:\"2147483647\" " ETC " }"
- " field { type:TYPE_INT32 default_value:\"-2147483648\" " ETC " }"
- " field { type:TYPE_UINT32 default_value:\"4294967295\" " ETC " }"
- " field { type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC " }"
- " field { type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC " }"
- " field { type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC " }"
- " field { type:TYPE_DOUBLE default_value:\"43981\" " ETC " }"
+ " field {"
+ " type:TYPE_INT32 default_value:\"2147483647\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT32 default_value:\"-2147483648\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_UINT32 default_value:\"4294967295\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC
+ " }"
+ " field {"
+ " type:TYPE_DOUBLE default_value:\"43981\" " ETC
+ " }"
"}");
#undef ETC
}
@@ -1557,7 +1571,7 @@ void SortMessages(DescriptorProto *descriptor_proto) {
}
DescriptorProto **data =
descriptor_proto->mutable_nested_type()->mutable_data();
- sort(data, data + size, CompareDescriptorNames());
+ std::sort(data, data + size, CompareDescriptorNames());
}
// Sorts DescriptorProtos belonging to a FileDescriptorProto, by name.
@@ -1569,7 +1583,7 @@ void SortMessages(FileDescriptorProto *file_descriptor_proto) {
}
DescriptorProto **data =
file_descriptor_proto->mutable_message_type()->mutable_data();
- sort(data, data + size, CompareDescriptorNames());
+ std::sort(data, data + size, CompareDescriptorNames());
}
// Strips the message and enum field type names for comparison purpose only.
@@ -1689,25 +1703,52 @@ TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
// places.
TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
SetupParser(
+ "// Detached comment before syntax.\n"
+ "\n"
+ "// Syntax comment.\n"
+ "syntax = \"proto2\";\n"
+ "\n"
+ "// Detached comment before package.\n"
+ "\n"
+ "// Package comment.\n"
+ "package comment_test;\n"
+ "\n"
+ "// Detached comment before TestMessage1.\n"
+ "\n"
"// Message comment.\n"
"message TestMessage1 {\n"
+ "\n"
+ " // Detached comment before foo.\n"
+ "\n"
" // Field comment.\n"
" optional int32 foo = 1;\n"
"\n"
+ " // Detached comment before NestedMessage.\n"
+ "\n"
" // Nested-message comment.\n"
" message NestedMessage {\n"
" optional int32 bar = 1;\n"
" }\n"
"}\n"
"\n"
+ "// Detached comment before MyEnumType.\n"
+ "\n"
"// Enum comment.\n"
"enum MyEnumType {\n"
+ "\n"
+ " // Detached comment before ASDF.\n"
+ "\n"
" // Enum-value comment.\n"
" ASDF = 1;\n"
"}\n"
"\n"
+ "// Detached comment before MyService.\n"
+ "\n"
"// Service comment.\n"
"service MyService {\n"
+ "\n"
+ " // Detached comment before MyRPCCall.\n"
+ "\n"
" // RPC comment.\n"
" rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
"}\n");
@@ -1731,22 +1772,34 @@ TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
const string debug_string =
descriptor->DebugStringWithOptions(debug_string_options);
- // Ensure that each of the comments appears somewhere in the DebugString(),
- // and that these comments appear in order. We don't test the exact comment
- // placement or formatting, because we do not want to be too fragile here.
+ // Ensure that each of the comments appears somewhere in the DebugString().
+ // We don't test the exact comment placement or formatting, because we do not
+ // want to be too fragile here.
const char* expected_comments[] = {
+ "Detached comment before syntax.",
+ "Syntax comment.",
+ "Detached comment before package.",
+ "Package comment.",
+ "Detached comment before TestMessage1.",
"Message comment.",
+ "Detached comment before foo.",
"Field comment",
+ "Detached comment before NestedMessage.",
"Nested-message comment",
+ "Detached comment before MyEnumType.",
"Enum comment",
+ "Detached comment before ASDF.",
"Enum-value comment",
+ "Detached comment before MyService.",
"Service comment",
+ "Detached comment before MyRPCCall.",
"RPC comment",
};
for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
string::size_type found_pos = debug_string.find(expected_comments[i]);
- ASSERT_TRUE(found_pos != string::npos);
+ EXPECT_TRUE(found_pos != string::npos)
+ << "\"" << expected_comments[i] << "\" not found.";
}
}
@@ -1916,8 +1969,8 @@ class SourceInfoTest : public ParserTest {
return false;
}
- spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index),
- &location));
+ spans_.insert(
+ std::make_pair(SpanKey(*descriptor_proto, field, index), &location));
}
return true;
@@ -1938,16 +1991,18 @@ class SourceInfoTest : public ParserTest {
bool HasSpan(char start_marker, char end_marker,
const Message& descriptor_proto) {
return HasSpanWithComment(
- start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL);
+ start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL);
}
bool HasSpanWithComment(char start_marker, char end_marker,
const Message& descriptor_proto,
const char* expected_leading_comments,
- const char* expected_trailing_comments) {
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
return HasSpanWithComment(
start_marker, end_marker, descriptor_proto, NULL, -1,
- expected_leading_comments, expected_trailing_comments);
+ expected_leading_comments, expected_trailing_comments,
+ expected_leading_detached_comments);
}
bool HasSpan(char start_marker, char end_marker,
@@ -1959,14 +2014,15 @@ class SourceInfoTest : public ParserTest {
const Message& descriptor_proto, const string& field_name,
int index) {
return HasSpan(start_marker, end_marker, descriptor_proto,
- field_name, index, NULL, NULL);
+ field_name, index, NULL, NULL, NULL);
}
bool HasSpan(char start_marker, char end_marker,
const Message& descriptor_proto,
const string& field_name, int index,
const char* expected_leading_comments,
- const char* expected_trailing_comments) {
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
const FieldDescriptor* field =
descriptor_proto.GetDescriptor()->FindFieldByName(field_name);
if (field == NULL) {
@@ -1977,12 +2033,13 @@ class SourceInfoTest : public ParserTest {
return HasSpanWithComment(
start_marker, end_marker, descriptor_proto, field, index,
- expected_leading_comments, expected_trailing_comments);
+ expected_leading_comments, expected_trailing_comments,
+ expected_leading_detached_comments);
}
bool HasSpan(const Message& descriptor_proto) {
return HasSpanWithComment(
- '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL);
+ '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL);
}
bool HasSpan(const Message& descriptor_proto, const string& field_name) {
@@ -1994,11 +2051,12 @@ class SourceInfoTest : public ParserTest {
return HasSpan('\0', '\0', descriptor_proto, field_name, index);
}
- bool HasSpanWithComment(char start_marker, char end_marker,
- const Message& descriptor_proto,
- const FieldDescriptor* field, int index,
- const char* expected_leading_comments,
- const char* expected_trailing_comments) {
+ bool HasSpanWithComment(
+ char start_marker, char end_marker, const Message& descriptor_proto,
+ const FieldDescriptor* field, int index,
+ const char* expected_leading_comments,
+ const char* expected_trailing_comments,
+ const char* expected_leading_detached_comments) {
pair<SpanMap::iterator, SpanMap::iterator> range =
spans_.equal_range(SpanKey(descriptor_proto, field, index));
@@ -2037,6 +2095,13 @@ class SourceInfoTest : public ParserTest {
EXPECT_EQ(expected_trailing_comments,
iter->second->trailing_comments());
}
+ if (expected_leading_detached_comments == NULL) {
+ EXPECT_EQ(0, iter->second->leading_detached_comments_size());
+ } else {
+ EXPECT_EQ(
+ expected_leading_detached_comments,
+ Join(iter->second->leading_detached_comments(), "\n"));
+ }
spans_.erase(iter);
return true;
@@ -2087,7 +2152,7 @@ class SourceInfoTest : public ParserTest {
text_without_markers_ += '$';
++column;
} else {
- markers_[*text] = make_pair(line, column);
+ markers_[*text] = std::make_pair(line, column);
++text;
GOOGLE_CHECK_EQ('$', *text);
}
@@ -2106,7 +2171,7 @@ class SourceInfoTest : public ParserTest {
TEST_F(SourceInfoTest, BasicFileDecls) {
EXPECT_TRUE(Parse(
- "$a$syntax = \"proto2\";\n"
+ "$a$syntax = \"proto2\";$i$\n"
"package $b$foo.bar$c$;\n"
"import $d$\"baz.proto\"$e$;\n"
"import $f$\"qux.proto\"$g$;$h$\n"
@@ -2117,6 +2182,7 @@ TEST_F(SourceInfoTest, BasicFileDecls) {
EXPECT_TRUE(HasSpan('b', 'c', file_, "package"));
EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0));
EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1));
+ EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax"));
}
TEST_F(SourceInfoTest, Messages) {
@@ -2547,6 +2613,9 @@ TEST_F(SourceInfoTest, ScopedOptions) {
" rpc M(X) returns(Y) {\n"
" $g$option mopt = 1;$h$\n"
" }\n"
+ " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n"
+ " $k$option mopt = 1;$l$\n"
+ " }\n"
"}\n"));
EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options()));
@@ -2606,6 +2675,26 @@ TEST_F(SourceInfoTest, ScopedOptions) {
.uninterpreted_option(0).name(0), "name_part"));
EXPECT_TRUE(HasSpan(file_.service(0).method(0).options()
.uninterpreted_option(0), "positive_int_value"));
+
+ EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options()));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1)));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0)));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0), "name"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0).name(0)));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0).name(0), "name_part"));
+ EXPECT_TRUE(HasSpan(file_.service(0).method(1).options()
+ .uninterpreted_option(0), "positive_int_value"));
+ EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1),
+ "client_streaming"));
+ EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1),
+ "server_streaming"));
}
TEST_F(SourceInfoTest, FieldOptions) {
@@ -2691,7 +2780,7 @@ TEST_F(SourceInfoTest, DocComments) {
" // Foo trailing\n"
" // line 2\n"
"\n"
- " // ignored\n"
+ " // detached\n"
"\n"
" // bar leading\n"
" $b$optional int32 bar = 1;$c$\n"
@@ -2705,10 +2794,12 @@ TEST_F(SourceInfoTest, DocComments) {
EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
" Foo leading\n line 2\n",
- " Foo trailing\n line 2\n"));
+ " Foo trailing\n line 2\n",
+ NULL));
EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
" bar leading\n",
- " bar trailing\n"));
+ " bar trailing\n",
+ " detached\n"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2721,21 +2812,23 @@ TEST_F(SourceInfoTest, DocComments) {
TEST_F(SourceInfoTest, DocComments2) {
EXPECT_TRUE(Parse(
- "// ignored\n"
- "syntax = \"proto2\";\n"
+ "// detached before message.\n"
+ "\n"
"// Foo leading\n"
"// line 2\n"
"$a$message Foo {\n"
" /* Foo trailing\n"
" * line 2 */\n"
- " // ignored\n"
+ " // detached\n"
" /* bar leading\n"
" */"
" $b$optional int32 bar = 1;$c$ // bar trailing\n"
- " // ignored\n"
+ " // ignored detached\n"
"}$d$\n"
"// ignored\n"
"\n"
+ "// detached before option\n"
+ "\n"
"// option leading\n"
"$e$option baz = 123;$f$\n"
"// option trailing\n"
@@ -2747,13 +2840,16 @@ TEST_F(SourceInfoTest, DocComments2) {
EXPECT_TRUE(HasSpanWithComment('a', 'd', foo,
" Foo leading\n line 2\n",
- " Foo trailing\n line 2 "));
+ " Foo trailing\n line 2 ",
+ " detached before message.\n"));
EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
" bar leading\n",
- " bar trailing\n"));
+ " bar trailing\n",
+ " detached\n"));
EXPECT_TRUE(HasSpanWithComment('e', 'f', baz,
" option leading\n",
- " option trailing\n"));
+ " option trailing\n",
+ " detached before option\n"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2784,7 +2880,8 @@ TEST_F(SourceInfoTest, DocComments3) {
EXPECT_TRUE(HasSpanWithComment('b', 'c', bar,
" bar leading\n",
- " bar trailing\n"));
+ " bar trailing\n",
+ NULL));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
@@ -2804,25 +2901,63 @@ TEST_F(SourceInfoTest, DocComments3) {
bar.options().uninterpreted_option(0), "aggregate_value"));
}
+TEST_F(SourceInfoTest, DocCommentsTopLevel) {
+ EXPECT_TRUE(Parse(
+ "// detached before syntax paragraph 1\n"
+ "\n"
+ "// detached before syntax paragraph 2\n"
+ "\n"
+ "// syntax leading\n"
+ "$a$syntax = \"proto2\";$b$\n"
+ "// syntax trailing\n"
+ "\n"
+ "// syntax-package detached comments\n"
+ "\n"
+ ";\n"
+ "\n"
+ "// detached after empty before package\n"
+ "\n"
+ "// package leading\n"
+ "package $c$foo$d$;\n"
+ "// package trailing\n"
+ "\n"
+ "// ignored detach\n"
+ "\n"));
+
+ EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1,
+ " syntax leading\n",
+ " syntax trailing\n",
+ " detached before syntax paragraph 1\n"
+ "\n"
+ " detached before syntax paragraph 2\n"));
+ EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1,
+ " package leading\n",
+ " package trailing\n",
+ " syntax-package detached comments\n"
+ "\n"
+ " detached after empty before package\n"));
+
+ // ignore these.
+ EXPECT_TRUE(HasSpan(file_));
+}
+
TEST_F(SourceInfoTest, DocCommentsOneof) {
EXPECT_TRUE(Parse(
- "// ignored\n"
- "syntax = \"proto2\";\n"
"// Foo leading\n"
"$a$message Foo {\n"
" /* Foo trailing\n"
" */\n"
- " // ignored\n"
+ " // detached before oneof\n"
" /* bar leading\n"
" * line 2 */\n"
" $b$oneof bar {\n"
" /* bar trailing\n"
" * line 2 */\n"
- " // ignored\n"
+ " // detached before bar_int\n"
" /* bar_int leading\n"
" */\n"
" $c$int32 bar_int = 1;$d$ // bar_int trailing\n"
- " // ignored\n"
+ " // detach comment ignored\n"
" }$e$\n"
"}$f$\n"));
@@ -2832,13 +2967,16 @@ TEST_F(SourceInfoTest, DocCommentsOneof) {
EXPECT_TRUE(HasSpanWithComment('a', 'f', foo,
" Foo leading\n",
- " Foo trailing\n"));
+ " Foo trailing\n",
+ NULL));
EXPECT_TRUE(HasSpanWithComment('b', 'e', bar,
" bar leading\n line 2 ",
- " bar trailing\n line 2 "));
+ " bar trailing\n line 2 ",
+ " detached before oneof\n"));
EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int,
" bar_int leading\n",
- " bar_int trailing\n"));
+ " bar_int trailing\n",
+ " detached before bar_int\n"));
// Ignore these.
EXPECT_TRUE(HasSpan(file_));
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 9011a6bd..ad501acf 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -95,7 +95,7 @@ class GeneratorResponseContext : public GeneratorContext {
int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
if (argc > 1) {
- cerr << argv[0] << ": Unknown option: " << argv[1] << endl;
+ std::cerr << argv[0] << ": Unknown option: " << argv[1] << std::endl;
return 1;
}
@@ -106,7 +106,8 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
CodeGeneratorRequest request;
if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
- cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl;
+ std::cerr << argv[0] << ": protoc sent unparseable request to plugin."
+ << std::endl;
return 1;
}
@@ -123,9 +124,9 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
for (int i = 0; i < request.file_to_generate_size(); i++) {
parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i)));
if (parsed_files.back() == NULL) {
- cerr << argv[0] << ": protoc asked plugin to generate a file but "
- "did not provide a descriptor for the file: "
- << request.file_to_generate(i) << endl;
+ std::cerr << argv[0] << ": protoc asked plugin to generate a file but "
+ "did not provide a descriptor for the file: "
+ << request.file_to_generate(i) << std::endl;
return 1;
}
}
@@ -151,7 +152,7 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
}
if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
- cerr << argv[0] << ": Error writing to stdout." << endl;
+ std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
return 1;
}
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 5118de15..fed1726a 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -140,8 +140,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
"\01324.google.protobuf.compiler.CodeGenerat"
"orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
"\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB"
- ",\n\034com.google.protobuf.compilerB\014PluginP"
- "rotos", 445);
+ "7\n\034com.google.protobuf.compilerB\014PluginP"
+ "rotosZ\tplugin_go", 456);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
@@ -509,6 +509,147 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+ int CodeGeneratorRequest::file_to_generate_size() const {
+ return file_to_generate_.size();
+}
+ void CodeGeneratorRequest::clear_file_to_generate() {
+ file_to_generate_.Clear();
+}
+ const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_.Get(index);
+}
+ ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_.Mutable(index);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ file_to_generate_.Mutable(index)->assign(value);
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+ file_to_generate_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+ file_to_generate_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+ return file_to_generate_.Add();
+}
+ void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+ file_to_generate_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+ file_to_generate_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+ file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return file_to_generate_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
+ return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+ bool CodeGeneratorRequest::has_parameter() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void CodeGeneratorRequest::set_has_parameter() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void CodeGeneratorRequest::clear_has_parameter() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void CodeGeneratorRequest::clear_parameter() {
+ parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_parameter();
+}
+ const ::std::string& CodeGeneratorRequest::parameter() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+ return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+ set_has_parameter();
+ parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value) {
+ set_has_parameter();
+ parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+ set_has_parameter();
+ parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+ ::std::string* CodeGeneratorRequest::mutable_parameter() {
+ set_has_parameter();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+ return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorRequest::release_parameter() {
+ clear_has_parameter();
+ return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+ if (parameter != NULL) {
+ set_has_parameter();
+ } else {
+ clear_has_parameter();
+ }
+ parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+ int CodeGeneratorRequest::proto_file_size() const {
+ return proto_file_.size();
+}
+ void CodeGeneratorRequest::clear_proto_file() {
+ proto_file_.Clear();
+}
+ const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_.Get(index);
+}
+ ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_.Mutable(index);
+}
+ ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return &proto_file_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -1162,6 +1303,256 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+ bool CodeGeneratorResponse_File::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void CodeGeneratorResponse_File::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void CodeGeneratorResponse_File::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void CodeGeneratorResponse_File::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& CodeGeneratorResponse_File::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+
+// optional string insertion_point = 2;
+ bool CodeGeneratorResponse_File::has_insertion_point() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void CodeGeneratorResponse_File::set_has_insertion_point() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void CodeGeneratorResponse_File::clear_has_insertion_point() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void CodeGeneratorResponse_File::clear_insertion_point() {
+ insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_insertion_point();
+}
+ const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+ return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+ set_has_insertion_point();
+ insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+ set_has_insertion_point();
+ insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+ set_has_insertion_point();
+ insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+ set_has_insertion_point();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+ return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+ clear_has_insertion_point();
+ return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+ if (insertion_point != NULL) {
+ set_has_insertion_point();
+ } else {
+ clear_has_insertion_point();
+ }
+ insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+
+// optional string content = 15;
+ bool CodeGeneratorResponse_File::has_content() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void CodeGeneratorResponse_File::set_has_content() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void CodeGeneratorResponse_File::clear_has_content() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void CodeGeneratorResponse_File::clear_content() {
+ content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_content();
+}
+ const ::std::string& CodeGeneratorResponse_File::content() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+ set_has_content();
+ content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value) {
+ set_has_content();
+ content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+ set_has_content();
+ content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+ ::std::string* CodeGeneratorResponse_File::mutable_content() {
+ set_has_content();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+ return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse_File::release_content() {
+ clear_has_content();
+ return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+ if (content != NULL) {
+ set_has_content();
+ } else {
+ clear_has_content();
+ }
+ content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+ bool CodeGeneratorResponse::has_error() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void CodeGeneratorResponse::set_has_error() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void CodeGeneratorResponse::clear_has_error() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void CodeGeneratorResponse::clear_error() {
+ error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_error();
+}
+ const ::std::string& CodeGeneratorResponse::error() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
+ return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_error(const ::std::string& value) {
+ set_has_error();
+ error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value) {
+ set_has_error();
+ error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+ set_has_error();
+ error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+ ::std::string* CodeGeneratorResponse::mutable_error() {
+ set_has_error();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
+ return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* CodeGeneratorResponse::release_error() {
+ clear_has_error();
+ return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+ if (error != NULL) {
+ set_has_error();
+ } else {
+ clear_has_error();
+ }
+ error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+ int CodeGeneratorResponse::file_size() const {
+ return file_.size();
+}
+ void CodeGeneratorResponse::clear_file() {
+ file_.Clear();
+}
+ const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_.Get(index);
+}
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_.Mutable(index);
+}
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+ // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return &file_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index ad017005..ea48b8b5 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -110,43 +110,43 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
// accessors -------------------------------------------------------
// repeated string file_to_generate = 1;
- inline int file_to_generate_size() const;
- inline void clear_file_to_generate();
+ int file_to_generate_size() const;
+ void clear_file_to_generate();
static const int kFileToGenerateFieldNumber = 1;
- inline const ::std::string& file_to_generate(int index) const;
- inline ::std::string* mutable_file_to_generate(int index);
- inline void set_file_to_generate(int index, const ::std::string& value);
- inline void set_file_to_generate(int index, const char* value);
- inline void set_file_to_generate(int index, const char* value, size_t size);
- inline ::std::string* add_file_to_generate();
- inline void add_file_to_generate(const ::std::string& value);
- inline void add_file_to_generate(const char* value);
- inline void add_file_to_generate(const char* value, size_t size);
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
+ const ::std::string& file_to_generate(int index) const;
+ ::std::string* mutable_file_to_generate(int index);
+ void set_file_to_generate(int index, const ::std::string& value);
+ void set_file_to_generate(int index, const char* value);
+ void set_file_to_generate(int index, const char* value, size_t size);
+ ::std::string* add_file_to_generate();
+ void add_file_to_generate(const ::std::string& value);
+ void add_file_to_generate(const char* value);
+ void add_file_to_generate(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
// optional string parameter = 2;
- inline bool has_parameter() const;
- inline void clear_parameter();
+ bool has_parameter() const;
+ void clear_parameter();
static const int kParameterFieldNumber = 2;
- inline const ::std::string& parameter() const;
- inline void set_parameter(const ::std::string& value);
- inline void set_parameter(const char* value);
- inline void set_parameter(const char* value, size_t size);
- inline ::std::string* mutable_parameter();
- inline ::std::string* release_parameter();
- inline void set_allocated_parameter(::std::string* parameter);
+ const ::std::string& parameter() const;
+ void set_parameter(const ::std::string& value);
+ void set_parameter(const char* value);
+ void set_parameter(const char* value, size_t size);
+ ::std::string* mutable_parameter();
+ ::std::string* release_parameter();
+ void set_allocated_parameter(::std::string* parameter);
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
- inline int proto_file_size() const;
- inline void clear_proto_file();
+ int proto_file_size() const;
+ void clear_proto_file();
static const int kProtoFileFieldNumber = 15;
- inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
- inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
- inline ::google::protobuf::FileDescriptorProto* add_proto_file();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
+ ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
+ ::google::protobuf::FileDescriptorProto* add_proto_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
proto_file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_proto_file();
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
@@ -234,40 +234,40 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional string insertion_point = 2;
- inline bool has_insertion_point() const;
- inline void clear_insertion_point();
+ bool has_insertion_point() const;
+ void clear_insertion_point();
static const int kInsertionPointFieldNumber = 2;
- inline const ::std::string& insertion_point() const;
- inline void set_insertion_point(const ::std::string& value);
- inline void set_insertion_point(const char* value);
- inline void set_insertion_point(const char* value, size_t size);
- inline ::std::string* mutable_insertion_point();
- inline ::std::string* release_insertion_point();
- inline void set_allocated_insertion_point(::std::string* insertion_point);
+ const ::std::string& insertion_point() const;
+ void set_insertion_point(const ::std::string& value);
+ void set_insertion_point(const char* value);
+ void set_insertion_point(const char* value, size_t size);
+ ::std::string* mutable_insertion_point();
+ ::std::string* release_insertion_point();
+ void set_allocated_insertion_point(::std::string* insertion_point);
// optional string content = 15;
- inline bool has_content() const;
- inline void clear_content();
+ bool has_content() const;
+ void clear_content();
static const int kContentFieldNumber = 15;
- inline const ::std::string& content() const;
- inline void set_content(const ::std::string& value);
- inline void set_content(const char* value);
- inline void set_content(const char* value, size_t size);
- inline ::std::string* mutable_content();
- inline ::std::string* release_content();
- inline void set_allocated_content(::std::string* content);
+ const ::std::string& content() const;
+ void set_content(const ::std::string& value);
+ void set_content(const char* value);
+ void set_content(const char* value, size_t size);
+ ::std::string* mutable_content();
+ ::std::string* release_content();
+ void set_allocated_content(::std::string* content);
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
private:
@@ -360,27 +360,27 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// optional string error = 1;
- inline bool has_error() const;
- inline void clear_error();
+ bool has_error() const;
+ void clear_error();
static const int kErrorFieldNumber = 1;
- inline const ::std::string& error() const;
- inline void set_error(const ::std::string& value);
- inline void set_error(const char* value);
- inline void set_error(const char* value, size_t size);
- inline ::std::string* mutable_error();
- inline ::std::string* release_error();
- inline void set_allocated_error(::std::string* error);
+ const ::std::string& error() const;
+ void set_error(const ::std::string& value);
+ void set_error(const char* value);
+ void set_error(const char* value, size_t size);
+ ::std::string* mutable_error();
+ ::std::string* release_error();
+ void set_allocated_error(::std::string* error);
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
- inline int file_size() const;
- inline void clear_file();
+ int file_size() const;
+ void clear_file();
static const int kFileFieldNumber = 15;
- inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
- inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
- inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+ const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+ ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
mutable_file();
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
@@ -405,6 +405,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
// ===================================================================
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// CodeGeneratorRequest
// repeated string file_to_generate = 1;
@@ -794,6 +795,7 @@ CodeGeneratorResponse::mutable_file() {
return &file_;
}
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
@@ -801,15 +803,6 @@ CodeGeneratorResponse::mutable_file() {
} // namespace protobuf
} // namespace google
-#ifndef SWIG
-namespace google {
-namespace protobuf {
-
-
-} // namespace protobuf
-} // namespace google
-#endif // SWIG
-
// @@protoc_insertion_point(global_scope)
#endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index e627289b..acaee1f4 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -49,6 +49,8 @@ package google.protobuf.compiler;
option java_package = "com.google.protobuf.compiler";
option java_outer_classname = "PluginProtos";
+option go_package = "plugin_go";
+
import "google/protobuf/descriptor.proto";
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index b30d1972..7b3b5fa3 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -273,6 +273,19 @@ string StringifyDefaultValue(const FieldDescriptor& field) {
return "";
}
+string StringifySyntax(FileDescriptor::Syntax syntax) {
+ switch (syntax) {
+ case FileDescriptor::SYNTAX_PROTO2:
+ return "proto2";
+ case FileDescriptor::SYNTAX_PROTO3:
+ return "proto3";
+ case FileDescriptor::SYNTAX_UNKNOWN:
+ default:
+ GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 "
+ "and proto3 syntax.";
+ return "";
+ }
+}
} // namespace
@@ -367,10 +380,12 @@ void Generator::PrintFileDescriptor() const {
m["descriptor_name"] = kDescriptorKey;
m["name"] = file_->name();
m["package"] = file_->package();
+ m["syntax"] = StringifySyntax(file_->syntax());
const char file_descriptor_template[] =
"$descriptor_name$ = _descriptor.FileDescriptor(\n"
" name='$name$',\n"
- " package='$package$',\n";
+ " package='$package$',\n"
+ " syntax='$syntax$',\n";
printer_->Print(m, file_descriptor_template);
printer_->Indent();
printer_->Print(
@@ -414,7 +429,7 @@ void Generator::PrintTopLevelEnums() const {
for (int j = 0; j < enum_descriptor.value_count(); ++j) {
const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j);
top_level_enum_values.push_back(
- make_pair(value_descriptor.name(), value_descriptor.number()));
+ std::make_pair(value_descriptor.name(), value_descriptor.number()));
}
}
@@ -581,14 +596,15 @@ void Generator::PrintServiceDescriptor(
}
-void Generator::PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const {
+void Generator::PrintDescriptorKeyAndModuleName(
+ const ServiceDescriptor& descriptor) const {
printer_->Print(
"$descriptor_key$ = $descriptor_name$,\n",
"descriptor_key", kDescriptorKey,
"descriptor_name", ModuleLevelServiceDescriptorName(descriptor));
printer_->Print(
"__module__ = '$module_name$'\n",
- "module_name", ModuleName(file_->name()));
+ "module_name", ModuleName(file_->name()));
}
void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
@@ -664,10 +680,12 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
message_descriptor.options().SerializeToString(&options_string);
printer_->Print(
"options=$options_value$,\n"
- "is_extendable=$extendable$",
+ "is_extendable=$extendable$,\n"
+ "syntax='$syntax$'",
"options_value", OptionsValue("MessageOptions", options_string),
"extendable", message_descriptor.extension_range_count() > 0 ?
- "True" : "False");
+ "True" : "False",
+ "syntax", StringifySyntax(message_descriptor.file()->syntax()));
printer_->Print(",\n");
// Extension ranges
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index ee68ad72..2ddac601 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -127,7 +127,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
void PrintServiceClass(const ServiceDescriptor& descriptor) const;
void PrintServiceStub(const ServiceDescriptor& descriptor) const;
- void PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const ;
+ void PrintDescriptorKeyAndModuleName(
+ const ServiceDescriptor& descriptor) const ;
void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
string OptionsValue(const string& class_name,
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index be59fafd..a9b6837e 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -102,24 +102,53 @@ std::string TypeName(const google::protobuf::FieldDescriptor* field) {
void GenerateField(const google::protobuf::FieldDescriptor* field,
google::protobuf::io::Printer* printer) {
- printer->Print(
- "$label$ :$name$, ",
- "label", LabelForField(field),
- "name", field->name());
- printer->Print(
- ":$type$, $number$",
- "type", TypeName(field),
- "number", IntToString(field->number()));
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
- printer->Print(
- ", \"$subtype$\"\n",
- "subtype", field->message_type()->full_name());
- } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+
+ if (field->is_map()) {
+ const FieldDescriptor* key_field =
+ field->message_type()->FindFieldByNumber(1);
+ const FieldDescriptor* value_field =
+ field->message_type()->FindFieldByNumber(2);
+
printer->Print(
- ", \"$subtype$\"\n",
- "subtype", field->enum_type()->full_name());
+ "map :$name$, :$key_type$, :$value_type$, $number$",
+ "name", field->name(),
+ "key_type", TypeName(key_field),
+ "value_type", TypeName(value_field),
+ "number", IntToString(field->number()));
+
+ if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", value_field->message_type()->full_name());
+ } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", value_field->enum_type()->full_name());
+ } else {
+ printer->Print("\n");
+ }
} else {
- printer->Print("\n");
+
+ printer->Print(
+ "$label$ :$name$, ",
+ "label", LabelForField(field),
+ "name", field->name());
+ printer->Print(
+ ":$type$, $number$",
+ "type", TypeName(field),
+ "number", IntToString(field->number()));
+
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", field->message_type()->full_name());
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer->Print(
+ ", \"$subtype$\"\n",
+ "subtype", field->enum_type()->full_name());
+ } else {
+ printer->Print("\n");
+ }
}
}
@@ -141,6 +170,13 @@ void GenerateOneof(const google::protobuf::OneofDescriptor* oneof,
void GenerateMessage(const google::protobuf::Descriptor* message,
google::protobuf::io::Printer* printer) {
+
+ // Don't generate MapEntry messages -- we use the Ruby extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+
printer->Print(
"add_message \"$name$\" do\n",
"name", message->full_name());
@@ -213,6 +249,13 @@ void GenerateMessageAssignment(
const std::string& prefix,
const google::protobuf::Descriptor* message,
google::protobuf::io::Printer* printer) {
+
+ // Don't generate MapEntry messages -- we use the Ruby extension's native
+ // support for map fields instead.
+ if (message->options().map_entry()) {
+ return;
+ }
+
printer->Print(
"$prefix$$name$ = ",
"prefix", prefix,
@@ -335,7 +378,8 @@ bool Generator::Generate(
std::string filename =
StripDotProto(file->name()) + ".rb";
- scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(filename));
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(filename));
io::Printer printer(output.get(), '$');
GenerateFile(file, &printer);
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h
index 48dbefd1..75555c31 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.h
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -40,7 +40,8 @@ namespace protobuf {
namespace compiler {
namespace ruby {
-class Generator : public google::protobuf::compiler::CodeGenerator {
+class LIBPROTOC_EXPORT Generator
+ : public google::protobuf::compiler::CodeGenerator {
virtual bool Generate(
const FileDescriptor* file,
const string& parameter,
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index b8dd198d..bfdacd95 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -783,7 +783,7 @@ inline const FileDescriptor* DescriptorPool::Tables::FindFile(
inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
const Descriptor* parent, int number) const {
- return FindPtrOrNull(fields_by_number_, make_pair(parent, number));
+ return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
}
inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
@@ -800,7 +800,7 @@ inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
const EnumDescriptor* parent, int number) const {
- return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number));
+ return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
}
inline const EnumValueDescriptor*
@@ -808,8 +808,8 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
const EnumDescriptor* parent, int number) const {
// First try, with map of compiled-in values.
{
- const EnumValueDescriptor* desc = FindPtrOrNull(
- enum_values_by_number_, make_pair(parent, number));
+ const EnumValueDescriptor* desc =
+ FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number));
if (desc != NULL) {
return desc;
}
@@ -818,7 +818,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
{
ReaderMutexLock l(&unknown_enum_values_mu_);
const EnumValueDescriptor* desc = FindPtrOrNull(
- unknown_enum_values_by_number_, make_pair(parent, number));
+ unknown_enum_values_by_number_, std::make_pair(parent, number));
if (desc != NULL) {
return desc;
}
@@ -828,7 +828,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
{
WriterMutexLock l(&unknown_enum_values_mu_);
const EnumValueDescriptor* desc = FindPtrOrNull(
- unknown_enum_values_by_number_, make_pair(parent, number));
+ unknown_enum_values_by_number_, std::make_pair(parent, number));
if (desc != NULL) {
return desc;
}
@@ -850,8 +850,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
result->type_ = parent;
result->options_ = &EnumValueOptions::default_instance();
InsertIfNotPresent(&unknown_enum_values_by_number_,
- make_pair(parent, number),
- result);
+ std::make_pair(parent, number), result);
return result;
}
}
@@ -859,13 +858,13 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
const Descriptor* extendee, int number) {
- return FindPtrOrNull(extensions_, make_pair(extendee, number));
+ return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
}
inline void DescriptorPool::Tables::FindAllExtensions(
const Descriptor* extendee, vector<const FieldDescriptor*>* out) const {
ExtensionsGroupedByDescriptorMap::const_iterator it =
- extensions_.lower_bound(make_pair(extendee, 0));
+ extensions_.lower_bound(std::make_pair(extendee, 0));
for (; it != extensions_.end() && it->first.first == extendee; ++it) {
out->push_back(it->second);
}
@@ -993,7 +992,7 @@ void FileDescriptorTables::BuildLocationsByPath(
const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
const vector<int>& path, const SourceCodeInfo* info) const {
pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
- make_pair(this, info));
+ std::make_pair(this, info));
locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p);
return FindPtrOrNull(locations_by_path_, Join(path, ","));
}
@@ -1929,9 +1928,9 @@ bool FormatLineOptions(int depth, const Message &options, string *output) {
return !all_options.empty();
}
-template<typename DescType>
class SourceLocationCommentPrinter {
public:
+ template<typename DescType>
SourceLocationCommentPrinter(const DescType* desc,
const string& prefix,
const DebugStringOptions& options)
@@ -1941,9 +1940,27 @@ class SourceLocationCommentPrinter {
have_source_loc_ = options.include_comments &&
desc->GetSourceLocation(&source_loc_);
}
+ SourceLocationCommentPrinter(const FileDescriptor* file,
+ const vector<int>& path,
+ const string& prefix,
+ const DebugStringOptions& options)
+ : options_(options), prefix_(prefix) {
+ // Perform the SourceLocation lookup only if we're including user comments,
+ // because the lookup is fairly expensive.
+ have_source_loc_ = options.include_comments &&
+ file->GetSourceLocation(path, &source_loc_);
+ }
void AddPreComment(string* output) {
- if (have_source_loc_ && source_loc_.leading_comments.size() > 0) {
- *output += FormatComment(source_loc_.leading_comments);
+ if (have_source_loc_) {
+ // Detached leading comments.
+ for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) {
+ *output += FormatComment(source_loc_.leading_detached_comments[i]);
+ *output += "\n";
+ }
+ // Attached leading comments.
+ if (!source_loc_.leading_comments.empty()) {
+ *output += FormatComment(source_loc_.leading_comments);
+ }
}
}
void AddPostComment(string* output) {
@@ -1967,7 +1984,6 @@ class SourceLocationCommentPrinter {
}
private:
- const DescType* desc_;
bool have_source_loc_;
SourceLocation source_loc_;
DebugStringOptions options_;
@@ -1984,10 +2000,18 @@ string FileDescriptor::DebugString() const {
string FileDescriptor::DebugStringWithOptions(
const DebugStringOptions& debug_string_options) const {
string contents;
- strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
- SyntaxName(syntax()));
+ {
+ vector<int> path;
+ path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
+ SourceLocationCommentPrinter syntax_comment(
+ this, path, "", debug_string_options);
+ syntax_comment.AddPreComment(&contents);
+ strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
+ SyntaxName(syntax()));
+ syntax_comment.AddPostComment(&contents);
+ }
- SourceLocationCommentPrinter<FileDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, "", debug_string_options);
comment_printer.AddPreComment(&contents);
@@ -2012,7 +2036,13 @@ string FileDescriptor::DebugStringWithOptions(
}
if (!package().empty()) {
+ vector<int> path;
+ path.push_back(FileDescriptorProto::kPackageFieldNumber);
+ SourceLocationCommentPrinter package_comment(
+ this, path, "", debug_string_options);
+ package_comment.AddPreComment(&contents);
strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
+ package_comment.AddPostComment(&contents);
}
if (FormatLineOptions(0, options(), &contents)) {
@@ -2087,7 +2117,7 @@ void Descriptor::DebugString(int depth, string *contents,
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<Descriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2217,7 +2247,7 @@ void FieldDescriptor::DebugString(int depth,
label.push_back(' ');
}
- SourceLocationCommentPrinter<FieldDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2274,7 +2304,7 @@ void OneofDescriptor::DebugString(int depth, string* contents,
debug_string_options) const {
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<OneofDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
strings::SubstituteAndAppend(
@@ -2305,7 +2335,7 @@ void EnumDescriptor::DebugString(int depth, string *contents,
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<EnumDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2339,7 +2369,7 @@ void EnumValueDescriptor::DebugString(int depth, string *contents,
debug_string_options) const {
string prefix(depth * 2, ' ');
- SourceLocationCommentPrinter<EnumValueDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2370,7 +2400,7 @@ string ServiceDescriptor::DebugStringWithOptions(
void ServiceDescriptor::DebugString(string *contents,
const DebugStringOptions&
debug_string_options) const {
- SourceLocationCommentPrinter<ServiceDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, /* prefix */ "", debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2405,7 +2435,7 @@ void MethodDescriptor::DebugString(int depth, string *contents,
string prefix(depth * 2, ' ');
++depth;
- SourceLocationCommentPrinter<MethodDescriptor>
+ SourceLocationCommentPrinter
comment_printer(this, prefix, debug_string_options);
comment_printer.AddPreComment(contents);
@@ -2445,6 +2475,9 @@ bool FileDescriptor::GetSourceLocation(const vector<int>& path,
out_location->leading_comments = loc->leading_comments();
out_location->trailing_comments = loc->trailing_comments();
+ out_location->leading_detached_comments.assign(
+ loc->leading_detached_comments().begin(),
+ loc->leading_detached_comments().end());
return true;
}
}
@@ -3697,7 +3730,6 @@ const FileDescriptor* DescriptorBuilder::BuildFile(
"Unrecognized syntax: " + proto.syntax());
}
-
result->name_ = tables_->AllocateString(proto.name());
if (proto.has_package()) {
result->package_ = tables_->AllocateString(proto.package());
@@ -5110,7 +5142,7 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
case FieldDescriptor::TYPE_SFIXED64:
// Legal cases
break;
- // Do not add a default, so that the compiler will complian when new types
+ // Do not add a default, so that the compiler will complain when new types
// are added.
}
@@ -5123,7 +5155,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
for (int i = 0; i < message->nested_type_count(); ++i) {
const Descriptor* nested = message->nested_type(i);
pair<map<string, const Descriptor*>::iterator, bool> result =
- seen_types.insert(make_pair(nested->name(), nested));
+ seen_types.insert(std::make_pair(nested->name(), nested));
if (!result.second) {
if (result.first->second->options().map_entry() ||
nested->options().map_entry()) {
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 52df47f3..0e264f54 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -117,8 +117,10 @@ struct SourceLocation {
int end_column;
// Doc comments found at the source location.
+ // See the comments in SourceCodeInfo.Location (descriptor.proto) for details.
string leading_comments;
string trailing_comments;
+ vector<string> leading_detached_comments;
};
// Options when generating machine-parsable output from a descriptor with
@@ -312,7 +314,7 @@ class LIBPROTOBUF_EXPORT Descriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -594,7 +596,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -688,7 +690,7 @@ class LIBPROTOBUF_EXPORT OneofDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -790,7 +792,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -874,7 +876,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -949,7 +951,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -1028,7 +1030,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptor {
// Walks up the descriptor tree to generate the source location path
// to this descriptor from the file root.
- void GetLocationPath(vector<int>* output) const;
+ void GetLocationPath(std::vector<int>* output) const;
const string* name_;
const string* full_name_;
@@ -1173,17 +1175,15 @@ class LIBPROTOBUF_EXPORT FileDescriptor {
// this file declaration (namely, the empty path).
bool GetSourceLocation(SourceLocation* out_location) const;
- private:
- // Source Location ---------------------------------------------------
-
// Updates |*out_location| to the source location of the complete
// extent of the declaration or declaration-part denoted by |path|.
// Returns false and leaves |*out_location| unchanged iff location
// information was not available. (See SourceCodeInfo for
// description of path encoding.)
- bool GetSourceLocation(const vector<int>& path,
+ bool GetSourceLocation(const std::vector<int>& path,
SourceLocation* out_location) const;
+ private:
typedef FileOptions OptionsType;
const string* name_;
@@ -1326,7 +1326,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// found: extensions defined in the fallback database might not be found
// depending on the database implementation.
void FindAllExtensions(const Descriptor* extendee,
- vector<const FieldDescriptor*>* out) const;
+ std::vector<const FieldDescriptor*>* out) const;
// Building descriptors --------------------------------------------
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 97121fa9..9556206c 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -289,7 +289,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_),
-1);
FileOptions_descriptor_ = file->message_type(9);
- static const int FileOptions_offsets_[13] = {
+ static const int FileOptions_offsets_[14] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_),
@@ -302,6 +302,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
};
FileOptions_reflection_ =
@@ -474,11 +475,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_),
-1);
SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0);
- static const int SourceCodeInfo_Location_offsets_[4] = {
+ static const int SourceCodeInfo_Location_offsets_[5] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_detached_comments_),
};
SourceCodeInfo_Location_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
@@ -661,7 +663,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"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\"\314\004\n\013FileOptions\022\024\n\014java_package\030"
+ ":\005false\"\347\004\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"
@@ -672,49 +674,51 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"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\022C\n\024uninterpreted_opti"
+ "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030"
+ "$ \001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g"
+ "oogle.protobuf.UninterpretedOption\":\n\014Op"
+ "timizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014"
+ "LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOpt"
+ "ions\022&\n\027message_set_wire_format\030\001 \001(\010:\005f"
+ "alse\022.\n\037no_standard_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_opti"
"on\030\347\007 \003(\0132$.google.protobuf.Uninterprete"
- "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO"
- "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346"
- "\001\n\016MessageOptions\022&\n\027message_set_wire_fo"
- "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip"
- "tor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030"
- "\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024unint"
- "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
- ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014Fiel"
- "dOptions\022:\n\005ctype\030\001 \001(\0162#.google.protobu"
- "f.FieldOptions.CType:\006STRING\022\016\n\006packed\030\002"
- " \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030"
- "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni"
- "nterpreted_option\030\347\007 \003(\0132$.google.protob"
- "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN"
- "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200"
- "\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022"
- "\031\n\ndeprecated\030\003 \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\020EnumValueO"
- "ptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uni"
- "nterpreted_option\030\347\007 \003(\0132$.google.protob"
- "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016Ser"
- "viceOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C"
- "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p"
- "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z"
- "\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:\005fal"
- "se\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog"
- "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200"
- "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013"
- "2-.google.protobuf.UninterpretedOption.N"
- "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos"
- "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va"
- "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin"
- "g_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_exte"
- "nsion\030\002 \002(\010\"\261\001\n\016SourceCodeInfo\022:\n\010locati"
- "on\030\001 \003(\0132(.google.protobuf.SourceCodeInf"
- "o.Location\032c\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001"
- "\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003"
- " \001(\t\022\031\n\021trailing_comments\030\004 \001(\tB)\n\023com.g"
- "oogle.protobufB\020DescriptorProtosH\001", 4554);
+ "dOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005c"
+ "type\030\001 \001(\0162#.google.protobuf.FieldOption"
+ "s.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030"
+ "\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022"
+ "\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_op"
+ "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+ "tedOption\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001"
+ "\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOp"
+ "tions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated"
+ "\030\003 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007"
+ " \003(\0132$.google.protobuf.UninterpretedOpti"
+ "on*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndep"
+ "recated\030\001 \001(\010:\005false\022C\n\024uninterpreted_op"
+ "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+ "tedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031"
+ "\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninterpret"
+ "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
+ "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptio"
+ "ns\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninter"
+ "preted_option\030\347\007 \003(\0132$.google.protobuf.U"
+ "ninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninte"
+ "rpretedOption\022;\n\004name\030\002 \003(\0132-.google.pro"
+ "tobuf.UninterpretedOption.NamePart\022\030\n\020id"
+ "entifier_value\030\003 \001(\t\022\032\n\022positive_int_val"
+ "ue\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014"
+ "double_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\016SourceCodeInfo\022:\n\010location\030\001 \003(\0132(.go"
+ "ogle.protobuf.SourceCodeInfo.Location\032\206\001"
+ "\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003"
+ "(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trai"
+ "ling_comments\030\004 \001(\t\022!\n\031leading_detached_"
+ "comments\030\006 \003(\tB)\n\023com.google.protobufB\020D"
+ "escriptorProtosH\001", 4617);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -1009,6 +1013,40 @@ void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorSet
+
+// repeated .google.protobuf.FileDescriptorProto file = 1;
+ int FileDescriptorSet::file_size() const {
+ return file_.size();
+}
+ void FileDescriptorSet::clear_file() {
+ file_.Clear();
+}
+ const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file)
+ return file_.Get(index);
+}
+ ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file)
+ return file_.Mutable(index);
+}
+ ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
+ return file_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+ return file_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+FileDescriptorSet::mutable_file() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
+ return &file_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -1771,6 +1809,489 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileDescriptorProto
+
+// optional string name = 1;
+ bool FileDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FileDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void FileDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void FileDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& FileDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
+}
+ void FileDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
+}
+ ::std::string* FileDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name)
+}
+
+// optional string package = 2;
+ bool FileDescriptorProto::has_package() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FileDescriptorProto::set_has_package() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void FileDescriptorProto::clear_has_package() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void FileDescriptorProto::clear_package() {
+ package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_package();
+}
+ const ::std::string& FileDescriptorProto::package() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
+ return package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_package(const ::std::string& value) {
+ set_has_package();
+ package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value) {
+ set_has_package();
+ package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
+}
+ void FileDescriptorProto::set_package(const char* value, size_t size) {
+ set_has_package();
+ package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
+}
+ ::std::string* FileDescriptorProto::mutable_package() {
+ set_has_package();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package)
+ return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_package() {
+ clear_has_package();
+ return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_package(::std::string* package) {
+ if (package != NULL) {
+ set_has_package();
+ } else {
+ clear_has_package();
+ }
+ package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package)
+}
+
+// repeated string dependency = 3;
+ int FileDescriptorProto::dependency_size() const {
+ return dependency_.size();
+}
+ void FileDescriptorProto::clear_dependency() {
+ dependency_.Clear();
+}
+ const ::std::string& FileDescriptorProto::dependency(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency)
+ return dependency_.Get(index);
+}
+ ::std::string* FileDescriptorProto::mutable_dependency(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency)
+ return dependency_.Mutable(index);
+}
+ void FileDescriptorProto::set_dependency(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
+ dependency_.Mutable(index)->assign(value);
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value) {
+ dependency_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) {
+ dependency_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ ::std::string* FileDescriptorProto::add_dependency() {
+ return dependency_.Add();
+}
+ void FileDescriptorProto::add_dependency(const ::std::string& value) {
+ dependency_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value) {
+ dependency_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency)
+}
+ void FileDescriptorProto::add_dependency(const char* value, size_t size) {
+ dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+FileDescriptorProto::dependency() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency)
+ return dependency_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+FileDescriptorProto::mutable_dependency() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency)
+ return &dependency_;
+}
+
+// repeated int32 public_dependency = 10;
+ int FileDescriptorProto::public_dependency_size() const {
+ return public_dependency_.size();
+}
+ void FileDescriptorProto::clear_public_dependency() {
+ public_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency)
+ return public_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) {
+ public_dependency_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) {
+ public_dependency_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::public_dependency() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency)
+ return public_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_public_dependency() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency)
+ return &public_dependency_;
+}
+
+// repeated int32 weak_dependency = 11;
+ int FileDescriptorProto::weak_dependency_size() const {
+ return weak_dependency_.size();
+}
+ void FileDescriptorProto::clear_weak_dependency() {
+ weak_dependency_.Clear();
+}
+ ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency)
+ return weak_dependency_.Get(index);
+}
+ void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) {
+ weak_dependency_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) {
+ weak_dependency_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+FileDescriptorProto::weak_dependency() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency)
+ return weak_dependency_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+FileDescriptorProto::mutable_weak_dependency() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency)
+ return &weak_dependency_;
+}
+
+// repeated .google.protobuf.DescriptorProto message_type = 4;
+ int FileDescriptorProto::message_type_size() const {
+ return message_type_.size();
+}
+ void FileDescriptorProto::clear_message_type() {
+ message_type_.Clear();
+}
+ const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_.Get(index);
+}
+ ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+FileDescriptorProto::mutable_message_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
+ return &message_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
+ int FileDescriptorProto::enum_type_size() const {
+ return enum_type_.size();
+}
+ void FileDescriptorProto::clear_enum_type() {
+ enum_type_.Clear();
+}
+ const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_.Get(index);
+}
+ ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_.Mutable(index);
+}
+ ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+FileDescriptorProto::mutable_enum_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
+ return &enum_type_;
+}
+
+// repeated .google.protobuf.ServiceDescriptorProto service = 6;
+ int FileDescriptorProto::service_size() const {
+ return service_.size();
+}
+ void FileDescriptorProto::clear_service() {
+ service_.Clear();
+}
+ const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service)
+ return service_.Get(index);
+}
+ ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service)
+ return service_.Mutable(index);
+}
+ ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
+ return service_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+ return service_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+FileDescriptorProto::mutable_service() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
+ return &service_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 7;
+ int FileDescriptorProto::extension_size() const {
+ return extension_.size();
+}
+ void FileDescriptorProto::clear_extension() {
+ extension_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension)
+ return extension_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension)
+ return extension_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
+ return extension_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+ return extension_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+FileDescriptorProto::mutable_extension() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
+ return &extension_;
+}
+
+// optional .google.protobuf.FileOptions options = 8;
+ bool FileDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000200u) != 0;
+}
+ void FileDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000200u;
+}
+ void FileDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000200u;
+}
+ void FileDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::FileOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::FileOptions* FileDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::FileOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
+}
+
+// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
+ bool FileDescriptorProto::has_source_code_info() const {
+ return (_has_bits_[0] & 0x00000400u) != 0;
+}
+ void FileDescriptorProto::set_has_source_code_info() {
+ _has_bits_[0] |= 0x00000400u;
+}
+ void FileDescriptorProto::clear_has_source_code_info() {
+ _has_bits_[0] &= ~0x00000400u;
+}
+ void FileDescriptorProto::clear_source_code_info() {
+ if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
+ clear_has_source_code_info();
+}
+ const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
+ return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_;
+}
+ ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
+ set_has_source_code_info();
+ if (source_code_info_ == NULL) {
+ source_code_info_ = new ::google::protobuf::SourceCodeInfo;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
+ return source_code_info_;
+}
+ ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
+ clear_has_source_code_info();
+ ::google::protobuf::SourceCodeInfo* temp = source_code_info_;
+ source_code_info_ = NULL;
+ return temp;
+}
+ void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) {
+ delete source_code_info_;
+ source_code_info_ = source_code_info;
+ if (source_code_info) {
+ set_has_source_code_info();
+ } else {
+ clear_has_source_code_info();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
+}
+
+// optional string syntax = 12;
+ bool FileDescriptorProto::has_syntax() const {
+ return (_has_bits_[0] & 0x00000800u) != 0;
+}
+ void FileDescriptorProto::set_has_syntax() {
+ _has_bits_[0] |= 0x00000800u;
+}
+ void FileDescriptorProto::clear_has_syntax() {
+ _has_bits_[0] &= ~0x00000800u;
+}
+ void FileDescriptorProto::clear_syntax() {
+ syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_syntax();
+}
+ const ::std::string& FileDescriptorProto::syntax() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
+ return syntax_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_syntax(const ::std::string& value) {
+ set_has_syntax();
+ syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value) {
+ set_has_syntax();
+ syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
+}
+ void FileDescriptorProto::set_syntax(const char* value, size_t size) {
+ set_has_syntax();
+ syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
+}
+ ::std::string* FileDescriptorProto::mutable_syntax() {
+ set_has_syntax();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax)
+ return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileDescriptorProto::release_syntax() {
+ clear_has_syntax();
+ return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) {
+ if (syntax != NULL) {
+ set_has_syntax();
+ } else {
+ clear_has_syntax();
+ }
+ syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -1839,19 +2360,17 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::pr
}
void DescriptorProto_ExtensionRange::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
ZR_(start_, end_);
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -2594,6 +3113,338 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// DescriptorProto_ExtensionRange
+
+// optional int32 start = 1;
+ bool DescriptorProto_ExtensionRange::has_start() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void DescriptorProto_ExtensionRange::set_has_start() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void DescriptorProto_ExtensionRange::clear_has_start() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void DescriptorProto_ExtensionRange::clear_start() {
+ start_ = 0;
+ clear_has_start();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start)
+ return start_;
+}
+ void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) {
+ set_has_start();
+ start_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start)
+}
+
+// optional int32 end = 2;
+ bool DescriptorProto_ExtensionRange::has_end() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void DescriptorProto_ExtensionRange::set_has_end() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void DescriptorProto_ExtensionRange::clear_has_end() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void DescriptorProto_ExtensionRange::clear_end() {
+ end_ = 0;
+ clear_has_end();
+}
+ ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end)
+ return end_;
+}
+ void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) {
+ set_has_end();
+ end_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
+}
+
+// -------------------------------------------------------------------
+
+// DescriptorProto
+
+// optional string name = 1;
+ bool DescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void DescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void DescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void DescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& DescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
+}
+ void DescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
+}
+ ::std::string* DescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* DescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void DescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name)
+}
+
+// repeated .google.protobuf.FieldDescriptorProto field = 2;
+ int DescriptorProto::field_size() const {
+ return field_.size();
+}
+ void DescriptorProto::clear_field() {
+ field_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field)
+ return field_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field)
+ return field_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
+ return field_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+ return field_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_field() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
+ return &field_;
+}
+
+// repeated .google.protobuf.FieldDescriptorProto extension = 6;
+ int DescriptorProto::extension_size() const {
+ return extension_.size();
+}
+ void DescriptorProto::clear_extension() {
+ extension_.Clear();
+}
+ const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension)
+ return extension_.Get(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension)
+ return extension_.Mutable(index);
+}
+ ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
+ return extension_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+ return extension_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+DescriptorProto::mutable_extension() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
+ return &extension_;
+}
+
+// repeated .google.protobuf.DescriptorProto nested_type = 3;
+ int DescriptorProto::nested_type_size() const {
+ return nested_type_.size();
+}
+ void DescriptorProto::clear_nested_type() {
+ nested_type_.Clear();
+}
+ const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_.Get(index);
+}
+ ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+DescriptorProto::mutable_nested_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
+ return &nested_type_;
+}
+
+// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
+ int DescriptorProto::enum_type_size() const {
+ return enum_type_.size();
+}
+ void DescriptorProto::clear_enum_type() {
+ enum_type_.Clear();
+}
+ const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_.Get(index);
+}
+ ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_.Mutable(index);
+}
+ ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+DescriptorProto::mutable_enum_type() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
+ return &enum_type_;
+}
+
+// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
+ int DescriptorProto::extension_range_size() const {
+ return extension_range_.size();
+}
+ void DescriptorProto::clear_extension_range() {
+ extension_range_.Clear();
+}
+ const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_.Get(index);
+}
+ ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_.Mutable(index);
+}
+ ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+DescriptorProto::mutable_extension_range() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
+ return &extension_range_;
+}
+
+// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
+ int DescriptorProto::oneof_decl_size() const {
+ return oneof_decl_.size();
+}
+ void DescriptorProto::clear_oneof_decl() {
+ oneof_decl_.Clear();
+}
+ const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_.Get(index);
+}
+ ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_.Mutable(index);
+}
+ ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() {
+ // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+DescriptorProto::mutable_oneof_decl() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
+ return &oneof_decl_;
+}
+
+// optional .google.protobuf.MessageOptions options = 7;
+ bool DescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000080u) != 0;
+}
+ void DescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000080u;
+}
+ void DescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000080u;
+}
+ void DescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::MessageOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::MessageOptions* DescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::MessageOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -3308,6 +4159,363 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldDescriptorProto
+
+// optional string name = 1;
+ bool FieldDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FieldDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void FieldDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void FieldDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& FieldDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
+}
+ void FieldDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
+}
+ ::std::string* FieldDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name)
+}
+
+// optional int32 number = 3;
+ bool FieldDescriptorProto::has_number() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FieldDescriptorProto::set_has_number() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void FieldDescriptorProto::clear_has_number() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void FieldDescriptorProto::clear_number() {
+ number_ = 0;
+ clear_has_number();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number)
+ return number_;
+}
+ void FieldDescriptorProto::set_number(::google::protobuf::int32 value) {
+ set_has_number();
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
+ bool FieldDescriptorProto::has_label() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void FieldDescriptorProto::set_has_label() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void FieldDescriptorProto::clear_has_label() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void FieldDescriptorProto::clear_label() {
+ label_ = 1;
+ clear_has_label();
+}
+ ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label)
+ return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_);
+}
+ void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) {
+ assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value));
+ set_has_label();
+ label_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label)
+}
+
+// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
+ bool FieldDescriptorProto::has_type() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void FieldDescriptorProto::set_has_type() {
+ _has_bits_[0] |= 0x00000008u;
+}
+ void FieldDescriptorProto::clear_has_type() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+ void FieldDescriptorProto::clear_type() {
+ type_ = 1;
+ clear_has_type();
+}
+ ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type)
+ return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_);
+}
+ void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) {
+ assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value));
+ set_has_type();
+ type_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type)
+}
+
+// optional string type_name = 6;
+ bool FieldDescriptorProto::has_type_name() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void FieldDescriptorProto::set_has_type_name() {
+ _has_bits_[0] |= 0x00000010u;
+}
+ void FieldDescriptorProto::clear_has_type_name() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+ void FieldDescriptorProto::clear_type_name() {
+ type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_type_name();
+}
+ const ::std::string& FieldDescriptorProto::type_name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name)
+ return type_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_type_name(const ::std::string& value) {
+ set_has_type_name();
+ type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value) {
+ set_has_type_name();
+ type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
+}
+ void FieldDescriptorProto::set_type_name(const char* value, size_t size) {
+ set_has_type_name();
+ type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
+}
+ ::std::string* FieldDescriptorProto::mutable_type_name() {
+ set_has_type_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name)
+ return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_type_name() {
+ clear_has_type_name();
+ return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) {
+ if (type_name != NULL) {
+ set_has_type_name();
+ } else {
+ clear_has_type_name();
+ }
+ type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name)
+}
+
+// optional string extendee = 2;
+ bool FieldDescriptorProto::has_extendee() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void FieldDescriptorProto::set_has_extendee() {
+ _has_bits_[0] |= 0x00000020u;
+}
+ void FieldDescriptorProto::clear_has_extendee() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+ void FieldDescriptorProto::clear_extendee() {
+ extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_extendee();
+}
+ const ::std::string& FieldDescriptorProto::extendee() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
+ return extendee_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_extendee(const ::std::string& value) {
+ set_has_extendee();
+ extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value) {
+ set_has_extendee();
+ extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
+}
+ void FieldDescriptorProto::set_extendee(const char* value, size_t size) {
+ set_has_extendee();
+ extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
+}
+ ::std::string* FieldDescriptorProto::mutable_extendee() {
+ set_has_extendee();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee)
+ return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_extendee() {
+ clear_has_extendee();
+ return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) {
+ if (extendee != NULL) {
+ set_has_extendee();
+ } else {
+ clear_has_extendee();
+ }
+ extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee)
+}
+
+// optional string default_value = 7;
+ bool FieldDescriptorProto::has_default_value() const {
+ return (_has_bits_[0] & 0x00000040u) != 0;
+}
+ void FieldDescriptorProto::set_has_default_value() {
+ _has_bits_[0] |= 0x00000040u;
+}
+ void FieldDescriptorProto::clear_has_default_value() {
+ _has_bits_[0] &= ~0x00000040u;
+}
+ void FieldDescriptorProto::clear_default_value() {
+ default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_default_value();
+}
+ const ::std::string& FieldDescriptorProto::default_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value)
+ return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_default_value(const ::std::string& value) {
+ set_has_default_value();
+ default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value) {
+ set_has_default_value();
+ default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
+}
+ void FieldDescriptorProto::set_default_value(const char* value, size_t size) {
+ set_has_default_value();
+ default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
+}
+ ::std::string* FieldDescriptorProto::mutable_default_value() {
+ set_has_default_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value)
+ return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FieldDescriptorProto::release_default_value() {
+ clear_has_default_value();
+ return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) {
+ if (default_value != NULL) {
+ set_has_default_value();
+ } else {
+ clear_has_default_value();
+ }
+ default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value)
+}
+
+// optional int32 oneof_index = 9;
+ bool FieldDescriptorProto::has_oneof_index() const {
+ return (_has_bits_[0] & 0x00000080u) != 0;
+}
+ void FieldDescriptorProto::set_has_oneof_index() {
+ _has_bits_[0] |= 0x00000080u;
+}
+ void FieldDescriptorProto::clear_has_oneof_index() {
+ _has_bits_[0] &= ~0x00000080u;
+}
+ void FieldDescriptorProto::clear_oneof_index() {
+ oneof_index_ = 0;
+ clear_has_oneof_index();
+}
+ ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index)
+ return oneof_index_;
+}
+ void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) {
+ set_has_oneof_index();
+ oneof_index_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
+}
+
+// optional .google.protobuf.FieldOptions options = 8;
+ bool FieldDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000100u) != 0;
+}
+ void FieldDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000100u;
+}
+ void FieldDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000100u;
+}
+ void FieldDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::FieldOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::FieldOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -3557,6 +4765,63 @@ void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// OneofDescriptorProto
+
+// optional string name = 1;
+ bool OneofDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void OneofDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void OneofDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void OneofDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& OneofDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
+}
+ void OneofDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name)
+}
+ ::std::string* OneofDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* OneofDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void OneofDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -3897,6 +5162,136 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumDescriptorProto
+
+// optional string name = 1;
+ bool EnumDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void EnumDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& EnumDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
+}
+ void EnumDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
+}
+ ::std::string* EnumDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name)
+}
+
+// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
+ int EnumDescriptorProto::value_size() const {
+ return value_.size();
+}
+ void EnumDescriptorProto::clear_value() {
+ value_.Clear();
+}
+ const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value)
+ return value_.Get(index);
+}
+ ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value)
+ return value_.Mutable(index);
+}
+ ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
+ return value_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+ return value_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+EnumDescriptorProto::mutable_value() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
+ return &value_;
+}
+
+// optional .google.protobuf.EnumOptions options = 3;
+ bool EnumDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void EnumDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void EnumDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void EnumDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::EnumOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::EnumOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -4236,6 +5631,130 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueDescriptorProto
+
+// optional string name = 1;
+ bool EnumValueDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumValueDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void EnumValueDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumValueDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& EnumValueDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
+}
+ void EnumValueDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
+}
+ ::std::string* EnumValueDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* EnumValueDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void EnumValueDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name)
+}
+
+// optional int32 number = 2;
+ bool EnumValueDescriptorProto::has_number() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void EnumValueDescriptorProto::set_has_number() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void EnumValueDescriptorProto::clear_has_number() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void EnumValueDescriptorProto::clear_number() {
+ number_ = 0;
+ clear_has_number();
+}
+ ::google::protobuf::int32 EnumValueDescriptorProto::number() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number)
+ return number_;
+}
+ void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) {
+ set_has_number();
+ number_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number)
+}
+
+// optional .google.protobuf.EnumValueOptions options = 3;
+ bool EnumValueDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void EnumValueDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void EnumValueDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void EnumValueDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::EnumValueOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::EnumValueOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -4576,6 +6095,136 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceDescriptorProto
+
+// optional string name = 1;
+ bool ServiceDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void ServiceDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void ServiceDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void ServiceDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& ServiceDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
+}
+ void ServiceDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
+}
+ ::std::string* ServiceDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* ServiceDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void ServiceDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name)
+}
+
+// repeated .google.protobuf.MethodDescriptorProto method = 2;
+ int ServiceDescriptorProto::method_size() const {
+ return method_.size();
+}
+ void ServiceDescriptorProto::clear_method() {
+ method_.Clear();
+}
+ const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method)
+ return method_.Get(index);
+}
+ ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method)
+ return method_.Mutable(index);
+}
+ ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() {
+ // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
+ return method_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+ return method_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ServiceDescriptorProto::mutable_method() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
+ return &method_;
+}
+
+// optional .google.protobuf.ServiceOptions options = 3;
+ bool ServiceDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void ServiceDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void ServiceDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void ServiceDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::ServiceOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::ServiceOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -4658,15 +6307,13 @@ MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* are
}
void MethodDescriptorProto::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<MethodDescriptorProto*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<MethodDescriptorProto*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
if (_has_bits_[0 / 32] & 63) {
ZR_(client_streaming_, server_streaming_);
@@ -4684,7 +6331,7 @@ void MethodDescriptorProto::Clear() {
}
}
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
::memset(_has_bits_, 0, sizeof(_has_bits_));
@@ -5075,6 +6722,260 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodDescriptorProto
+
+// optional string name = 1;
+ bool MethodDescriptorProto::has_name() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void MethodDescriptorProto::set_has_name() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void MethodDescriptorProto::clear_has_name() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void MethodDescriptorProto::clear_name() {
+ name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name();
+}
+ const ::std::string& MethodDescriptorProto::name() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
+ return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_name(const ::std::string& value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
+}
+ void MethodDescriptorProto::set_name(const char* value, size_t size) {
+ set_has_name();
+ name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
+}
+ ::std::string* MethodDescriptorProto::mutable_name() {
+ set_has_name();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name)
+ return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_name() {
+ clear_has_name();
+ return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_name(::std::string* name) {
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
+ }
+ name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name)
+}
+
+// optional string input_type = 2;
+ bool MethodDescriptorProto::has_input_type() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void MethodDescriptorProto::set_has_input_type() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void MethodDescriptorProto::clear_has_input_type() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void MethodDescriptorProto::clear_input_type() {
+ input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_input_type();
+}
+ const ::std::string& MethodDescriptorProto::input_type() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type)
+ return input_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_input_type(const ::std::string& value) {
+ set_has_input_type();
+ input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value) {
+ set_has_input_type();
+ input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
+}
+ void MethodDescriptorProto::set_input_type(const char* value, size_t size) {
+ set_has_input_type();
+ input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_input_type() {
+ set_has_input_type();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type)
+ return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_input_type() {
+ clear_has_input_type();
+ return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) {
+ if (input_type != NULL) {
+ set_has_input_type();
+ } else {
+ clear_has_input_type();
+ }
+ input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type)
+}
+
+// optional string output_type = 3;
+ bool MethodDescriptorProto::has_output_type() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void MethodDescriptorProto::set_has_output_type() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void MethodDescriptorProto::clear_has_output_type() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void MethodDescriptorProto::clear_output_type() {
+ output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_output_type();
+}
+ const ::std::string& MethodDescriptorProto::output_type() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type)
+ return output_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_output_type(const ::std::string& value) {
+ set_has_output_type();
+ output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value) {
+ set_has_output_type();
+ output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
+}
+ void MethodDescriptorProto::set_output_type(const char* value, size_t size) {
+ set_has_output_type();
+ output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
+}
+ ::std::string* MethodDescriptorProto::mutable_output_type() {
+ set_has_output_type();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type)
+ return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* MethodDescriptorProto::release_output_type() {
+ clear_has_output_type();
+ return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) {
+ if (output_type != NULL) {
+ set_has_output_type();
+ } else {
+ clear_has_output_type();
+ }
+ output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type)
+}
+
+// optional .google.protobuf.MethodOptions options = 4;
+ bool MethodDescriptorProto::has_options() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void MethodDescriptorProto::set_has_options() {
+ _has_bits_[0] |= 0x00000008u;
+}
+ void MethodDescriptorProto::clear_has_options() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+ void MethodDescriptorProto::clear_options() {
+ if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
+ clear_has_options();
+}
+ const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
+ return options_ != NULL ? *options_ : *default_instance_->options_;
+}
+ ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
+ set_has_options();
+ if (options_ == NULL) {
+ options_ = new ::google::protobuf::MethodOptions;
+ }
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
+ return options_;
+}
+ ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() {
+ clear_has_options();
+ ::google::protobuf::MethodOptions* temp = options_;
+ options_ = NULL;
+ return temp;
+}
+ void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
+ delete options_;
+ options_ = options;
+ if (options) {
+ set_has_options();
+ } else {
+ clear_has_options();
+ }
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options)
+}
+
+// optional bool client_streaming = 5 [default = false];
+ bool MethodDescriptorProto::has_client_streaming() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void MethodDescriptorProto::set_has_client_streaming() {
+ _has_bits_[0] |= 0x00000010u;
+}
+ void MethodDescriptorProto::clear_has_client_streaming() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+ void MethodDescriptorProto::clear_client_streaming() {
+ client_streaming_ = false;
+ clear_has_client_streaming();
+}
+ bool MethodDescriptorProto::client_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming)
+ return client_streaming_;
+}
+ void MethodDescriptorProto::set_client_streaming(bool value) {
+ set_has_client_streaming();
+ client_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming)
+}
+
+// optional bool server_streaming = 6 [default = false];
+ bool MethodDescriptorProto::has_server_streaming() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void MethodDescriptorProto::set_has_server_streaming() {
+ _has_bits_[0] |= 0x00000020u;
+}
+ void MethodDescriptorProto::clear_has_server_streaming() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+ void MethodDescriptorProto::clear_server_streaming() {
+ server_streaming_ = false;
+ clear_has_server_streaming();
+}
+ bool MethodDescriptorProto::server_streaming() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming)
+ return server_streaming_;
+}
+ void MethodDescriptorProto::set_server_streaming(bool value) {
+ set_has_server_streaming();
+ server_streaming_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -5114,6 +7015,7 @@ const int FileOptions::kJavaGenericServicesFieldNumber;
const int FileOptions::kPyGenericServicesFieldNumber;
const int FileOptions::kDeprecatedFieldNumber;
const int FileOptions::kCcEnableArenasFieldNumber;
+const int FileOptions::kObjcClassPrefixFieldNumber;
const int FileOptions::kUninterpretedOptionFieldNumber;
#endif // !_MSC_VER
@@ -5149,6 +7051,7 @@ void FileOptions::SharedCtor() {
py_generic_services_ = false;
deprecated_ = false;
cc_enable_arenas_ = false;
+ objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -5161,6 +7064,7 @@ void FileOptions::SharedDtor() {
java_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
if (this != default_instance_) {
}
}
@@ -5192,15 +7096,13 @@ FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const {
void FileOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<FileOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<FileOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
if (_has_bits_[0 / 32] & 255) {
ZR_(java_multiple_files_, cc_generic_services_);
@@ -5215,9 +7117,14 @@ void FileOptions::Clear() {
go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
}
- ZR_(java_generic_services_, cc_enable_arenas_);
+ if (_has_bits_[8 / 32] & 7936) {
+ ZR_(java_generic_services_, cc_enable_arenas_);
+ if (has_objc_class_prefix()) {
+ objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ }
+ }
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -5423,6 +7330,23 @@ bool FileOptions::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(290)) goto parse_objc_class_prefix;
+ break;
+ }
+
+ // optional string objc_class_prefix = 36;
+ case 36: {
+ if (tag == 290) {
+ parse_objc_class_prefix:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->mutable_objc_class_prefix()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.FileOptions.objc_class_prefix");
+ } else {
+ goto handle_unusual;
+ }
if (input->ExpectTag(7994)) goto parse_uninterpreted_option;
break;
}
@@ -5547,6 +7471,16 @@ void FileOptions::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output);
}
+ // optional string objc_class_prefix = 36;
+ if (has_objc_class_prefix()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileOptions.objc_class_prefix");
+ ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+ 36, this->objc_class_prefix(), output);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
@@ -5646,6 +7580,17 @@ void FileOptions::SerializeWithCachedSizes(
target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target);
}
+ // optional string objc_class_prefix = 36;
+ if (has_objc_class_prefix()) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.FileOptions.objc_class_prefix");
+ target =
+ ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+ 36, this->objc_class_prefix(), target);
+ }
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
target = ::google::protobuf::internal::WireFormatLite::
@@ -5717,7 +7662,7 @@ int FileOptions::ByteSize() const {
}
}
- if (_has_bits_[8 / 32] & 3840) {
+ if (_has_bits_[8 / 32] & 7936) {
// optional bool java_generic_services = 17 [default = false];
if (has_java_generic_services()) {
total_size += 2 + 1;
@@ -5738,6 +7683,13 @@ int FileOptions::ByteSize() const {
total_size += 2 + 1;
}
+ // optional string objc_class_prefix = 36;
+ if (has_objc_class_prefix()) {
+ total_size += 2 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->objc_class_prefix());
+ }
+
}
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
total_size += 2 * this->uninterpreted_option_size();
@@ -5817,6 +7769,10 @@ void FileOptions::MergeFrom(const FileOptions& from) {
if (from.has_cc_enable_arenas()) {
set_cc_enable_arenas(from.cc_enable_arenas());
}
+ if (from.has_objc_class_prefix()) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_);
+ }
}
_extensions_.MergeFrom(from._extensions_);
if (from._internal_metadata_.have_unknown_fields()) {
@@ -5860,6 +7816,7 @@ void FileOptions::InternalSwap(FileOptions* other) {
std::swap(py_generic_services_, other->py_generic_services_);
std::swap(deprecated_, other->deprecated_);
std::swap(cc_enable_arenas_, other->cc_enable_arenas_);
+ objc_class_prefix_.Swap(&other->objc_class_prefix_);
uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
@@ -5875,6 +7832,469 @@ void FileOptions::InternalSwap(FileOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FileOptions
+
+// optional string java_package = 1;
+ bool FileOptions::has_java_package() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FileOptions::set_has_java_package() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void FileOptions::clear_has_java_package() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void FileOptions::clear_java_package() {
+ java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_java_package();
+}
+ const ::std::string& FileOptions::java_package() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package)
+ return java_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_package(const ::std::string& value) {
+ set_has_java_package();
+ java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value) {
+ set_has_java_package();
+ java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
+}
+ void FileOptions::set_java_package(const char* value, size_t size) {
+ set_has_java_package();
+ java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
+}
+ ::std::string* FileOptions::mutable_java_package() {
+ set_has_java_package();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package)
+ return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_package() {
+ clear_has_java_package();
+ return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_package(::std::string* java_package) {
+ if (java_package != NULL) {
+ set_has_java_package();
+ } else {
+ clear_has_java_package();
+ }
+ java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package)
+}
+
+// optional string java_outer_classname = 8;
+ bool FileOptions::has_java_outer_classname() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FileOptions::set_has_java_outer_classname() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void FileOptions::clear_has_java_outer_classname() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void FileOptions::clear_java_outer_classname() {
+ java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_java_outer_classname();
+}
+ const ::std::string& FileOptions::java_outer_classname() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname)
+ return java_outer_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_java_outer_classname(const ::std::string& value) {
+ set_has_java_outer_classname();
+ java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value) {
+ set_has_java_outer_classname();
+ java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname)
+}
+ void FileOptions::set_java_outer_classname(const char* value, size_t size) {
+ set_has_java_outer_classname();
+ java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
+}
+ ::std::string* FileOptions::mutable_java_outer_classname() {
+ set_has_java_outer_classname();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname)
+ return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_java_outer_classname() {
+ clear_has_java_outer_classname();
+ return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) {
+ if (java_outer_classname != NULL) {
+ set_has_java_outer_classname();
+ } else {
+ clear_has_java_outer_classname();
+ }
+ java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname)
+}
+
+// optional bool java_multiple_files = 10 [default = false];
+ bool FileOptions::has_java_multiple_files() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void FileOptions::set_has_java_multiple_files() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void FileOptions::clear_has_java_multiple_files() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void FileOptions::clear_java_multiple_files() {
+ java_multiple_files_ = false;
+ clear_has_java_multiple_files();
+}
+ bool FileOptions::java_multiple_files() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files)
+ return java_multiple_files_;
+}
+ void FileOptions::set_java_multiple_files(bool value) {
+ set_has_java_multiple_files();
+ java_multiple_files_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files)
+}
+
+// optional bool java_generate_equals_and_hash = 20 [default = false];
+ bool FileOptions::has_java_generate_equals_and_hash() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void FileOptions::set_has_java_generate_equals_and_hash() {
+ _has_bits_[0] |= 0x00000008u;
+}
+ void FileOptions::clear_has_java_generate_equals_and_hash() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+ void FileOptions::clear_java_generate_equals_and_hash() {
+ java_generate_equals_and_hash_ = false;
+ clear_has_java_generate_equals_and_hash();
+}
+ bool FileOptions::java_generate_equals_and_hash() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash)
+ return java_generate_equals_and_hash_;
+}
+ void FileOptions::set_java_generate_equals_and_hash(bool value) {
+ set_has_java_generate_equals_and_hash();
+ java_generate_equals_and_hash_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash)
+}
+
+// optional bool java_string_check_utf8 = 27 [default = false];
+ bool FileOptions::has_java_string_check_utf8() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void FileOptions::set_has_java_string_check_utf8() {
+ _has_bits_[0] |= 0x00000010u;
+}
+ void FileOptions::clear_has_java_string_check_utf8() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+ void FileOptions::clear_java_string_check_utf8() {
+ java_string_check_utf8_ = false;
+ clear_has_java_string_check_utf8();
+}
+ bool FileOptions::java_string_check_utf8() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8)
+ return java_string_check_utf8_;
+}
+ void FileOptions::set_java_string_check_utf8(bool value) {
+ set_has_java_string_check_utf8();
+ java_string_check_utf8_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8)
+}
+
+// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
+ bool FileOptions::has_optimize_for() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void FileOptions::set_has_optimize_for() {
+ _has_bits_[0] |= 0x00000020u;
+}
+ void FileOptions::clear_has_optimize_for() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+ void FileOptions::clear_optimize_for() {
+ optimize_for_ = 1;
+ clear_has_optimize_for();
+}
+ ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for)
+ return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_);
+}
+ void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) {
+ assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value));
+ set_has_optimize_for();
+ optimize_for_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for)
+}
+
+// optional string go_package = 11;
+ bool FileOptions::has_go_package() const {
+ return (_has_bits_[0] & 0x00000040u) != 0;
+}
+ void FileOptions::set_has_go_package() {
+ _has_bits_[0] |= 0x00000040u;
+}
+ void FileOptions::clear_has_go_package() {
+ _has_bits_[0] &= ~0x00000040u;
+}
+ void FileOptions::clear_go_package() {
+ go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_go_package();
+}
+ const ::std::string& FileOptions::go_package() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package)
+ return go_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_go_package(const ::std::string& value) {
+ set_has_go_package();
+ go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value) {
+ set_has_go_package();
+ go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
+}
+ void FileOptions::set_go_package(const char* value, size_t size) {
+ set_has_go_package();
+ go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
+}
+ ::std::string* FileOptions::mutable_go_package() {
+ set_has_go_package();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package)
+ return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_go_package() {
+ clear_has_go_package();
+ return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_go_package(::std::string* go_package) {
+ if (go_package != NULL) {
+ set_has_go_package();
+ } else {
+ clear_has_go_package();
+ }
+ go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package)
+}
+
+// optional bool cc_generic_services = 16 [default = false];
+ bool FileOptions::has_cc_generic_services() const {
+ return (_has_bits_[0] & 0x00000080u) != 0;
+}
+ void FileOptions::set_has_cc_generic_services() {
+ _has_bits_[0] |= 0x00000080u;
+}
+ void FileOptions::clear_has_cc_generic_services() {
+ _has_bits_[0] &= ~0x00000080u;
+}
+ void FileOptions::clear_cc_generic_services() {
+ cc_generic_services_ = false;
+ clear_has_cc_generic_services();
+}
+ bool FileOptions::cc_generic_services() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services)
+ return cc_generic_services_;
+}
+ void FileOptions::set_cc_generic_services(bool value) {
+ set_has_cc_generic_services();
+ cc_generic_services_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services)
+}
+
+// optional bool java_generic_services = 17 [default = false];
+ bool FileOptions::has_java_generic_services() const {
+ return (_has_bits_[0] & 0x00000100u) != 0;
+}
+ void FileOptions::set_has_java_generic_services() {
+ _has_bits_[0] |= 0x00000100u;
+}
+ void FileOptions::clear_has_java_generic_services() {
+ _has_bits_[0] &= ~0x00000100u;
+}
+ void FileOptions::clear_java_generic_services() {
+ java_generic_services_ = false;
+ clear_has_java_generic_services();
+}
+ bool FileOptions::java_generic_services() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services)
+ return java_generic_services_;
+}
+ void FileOptions::set_java_generic_services(bool value) {
+ set_has_java_generic_services();
+ java_generic_services_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services)
+}
+
+// optional bool py_generic_services = 18 [default = false];
+ bool FileOptions::has_py_generic_services() const {
+ return (_has_bits_[0] & 0x00000200u) != 0;
+}
+ void FileOptions::set_has_py_generic_services() {
+ _has_bits_[0] |= 0x00000200u;
+}
+ void FileOptions::clear_has_py_generic_services() {
+ _has_bits_[0] &= ~0x00000200u;
+}
+ void FileOptions::clear_py_generic_services() {
+ py_generic_services_ = false;
+ clear_has_py_generic_services();
+}
+ bool FileOptions::py_generic_services() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services)
+ return py_generic_services_;
+}
+ void FileOptions::set_py_generic_services(bool value) {
+ set_has_py_generic_services();
+ py_generic_services_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services)
+}
+
+// optional bool deprecated = 23 [default = false];
+ bool FileOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000400u) != 0;
+}
+ void FileOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000400u;
+}
+ void FileOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000400u;
+}
+ void FileOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool FileOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated)
+ return deprecated_;
+}
+ void FileOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated)
+}
+
+// optional bool cc_enable_arenas = 31 [default = false];
+ bool FileOptions::has_cc_enable_arenas() const {
+ return (_has_bits_[0] & 0x00000800u) != 0;
+}
+ void FileOptions::set_has_cc_enable_arenas() {
+ _has_bits_[0] |= 0x00000800u;
+}
+ void FileOptions::clear_has_cc_enable_arenas() {
+ _has_bits_[0] &= ~0x00000800u;
+}
+ void FileOptions::clear_cc_enable_arenas() {
+ cc_enable_arenas_ = false;
+ clear_has_cc_enable_arenas();
+}
+ bool FileOptions::cc_enable_arenas() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas)
+ return cc_enable_arenas_;
+}
+ void FileOptions::set_cc_enable_arenas(bool value) {
+ set_has_cc_enable_arenas();
+ cc_enable_arenas_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
+}
+
+// optional string objc_class_prefix = 36;
+ bool FileOptions::has_objc_class_prefix() const {
+ return (_has_bits_[0] & 0x00001000u) != 0;
+}
+ void FileOptions::set_has_objc_class_prefix() {
+ _has_bits_[0] |= 0x00001000u;
+}
+ void FileOptions::clear_has_objc_class_prefix() {
+ _has_bits_[0] &= ~0x00001000u;
+}
+ void FileOptions::clear_objc_class_prefix() {
+ objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_objc_class_prefix();
+}
+ const ::std::string& FileOptions::objc_class_prefix() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+ void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+ ::std::string* FileOptions::mutable_objc_class_prefix() {
+ set_has_objc_class_prefix();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* FileOptions::release_objc_class_prefix() {
+ clear_has_objc_class_prefix();
+ return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+ if (objc_class_prefix != NULL) {
+ set_has_objc_class_prefix();
+ } else {
+ clear_has_objc_class_prefix();
+ }
+ objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int FileOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+ void FileOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FileOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -5949,19 +8369,17 @@ MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const {
void MessageOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<MessageOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<MessageOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
ZR_(message_set_wire_format_, map_entry_);
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -6287,6 +8705,136 @@ void MessageOptions::InternalSwap(MessageOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MessageOptions
+
+// optional bool message_set_wire_format = 1 [default = false];
+ bool MessageOptions::has_message_set_wire_format() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void MessageOptions::set_has_message_set_wire_format() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void MessageOptions::clear_has_message_set_wire_format() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void MessageOptions::clear_message_set_wire_format() {
+ message_set_wire_format_ = false;
+ clear_has_message_set_wire_format();
+}
+ bool MessageOptions::message_set_wire_format() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format)
+ return message_set_wire_format_;
+}
+ void MessageOptions::set_message_set_wire_format(bool value) {
+ set_has_message_set_wire_format();
+ message_set_wire_format_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format)
+}
+
+// optional bool no_standard_descriptor_accessor = 2 [default = false];
+ bool MessageOptions::has_no_standard_descriptor_accessor() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void MessageOptions::set_has_no_standard_descriptor_accessor() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void MessageOptions::clear_has_no_standard_descriptor_accessor() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void MessageOptions::clear_no_standard_descriptor_accessor() {
+ no_standard_descriptor_accessor_ = false;
+ clear_has_no_standard_descriptor_accessor();
+}
+ bool MessageOptions::no_standard_descriptor_accessor() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+ return no_standard_descriptor_accessor_;
+}
+ void MessageOptions::set_no_standard_descriptor_accessor(bool value) {
+ set_has_no_standard_descriptor_accessor();
+ no_standard_descriptor_accessor_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor)
+}
+
+// optional bool deprecated = 3 [default = false];
+ bool MessageOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void MessageOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void MessageOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void MessageOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool MessageOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated)
+ return deprecated_;
+}
+ void MessageOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated)
+}
+
+// optional bool map_entry = 7;
+ bool MessageOptions::has_map_entry() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void MessageOptions::set_has_map_entry() {
+ _has_bits_[0] |= 0x00000008u;
+}
+ void MessageOptions::clear_has_map_entry() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+ void MessageOptions::clear_map_entry() {
+ map_entry_ = false;
+ clear_has_map_entry();
+}
+ bool MessageOptions::map_entry() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry)
+ return map_entry_;
+}
+ void MessageOptions::set_map_entry(bool value) {
+ set_has_map_entry();
+ map_entry_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int MessageOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+ void MessageOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MessageOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -6386,21 +8934,19 @@ FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const {
void FieldOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<FieldOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<FieldOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
if (_has_bits_[0 / 32] & 31) {
ZR_(ctype_, weak_);
}
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -6768,6 +9314,161 @@ void FieldOptions::InternalSwap(FieldOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// FieldOptions
+
+// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
+ bool FieldOptions::has_ctype() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void FieldOptions::set_has_ctype() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void FieldOptions::clear_has_ctype() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void FieldOptions::clear_ctype() {
+ ctype_ = 0;
+ clear_has_ctype();
+}
+ ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype)
+ return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_);
+}
+ void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) {
+ assert(::google::protobuf::FieldOptions_CType_IsValid(value));
+ set_has_ctype();
+ ctype_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype)
+}
+
+// optional bool packed = 2;
+ bool FieldOptions::has_packed() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void FieldOptions::set_has_packed() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void FieldOptions::clear_has_packed() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void FieldOptions::clear_packed() {
+ packed_ = false;
+ clear_has_packed();
+}
+ bool FieldOptions::packed() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed)
+ return packed_;
+}
+ void FieldOptions::set_packed(bool value) {
+ set_has_packed();
+ packed_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed)
+}
+
+// optional bool lazy = 5 [default = false];
+ bool FieldOptions::has_lazy() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void FieldOptions::set_has_lazy() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void FieldOptions::clear_has_lazy() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void FieldOptions::clear_lazy() {
+ lazy_ = false;
+ clear_has_lazy();
+}
+ bool FieldOptions::lazy() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy)
+ return lazy_;
+}
+ void FieldOptions::set_lazy(bool value) {
+ set_has_lazy();
+ lazy_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy)
+}
+
+// optional bool deprecated = 3 [default = false];
+ bool FieldOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void FieldOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000008u;
+}
+ void FieldOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+ void FieldOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool FieldOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated)
+ return deprecated_;
+}
+ void FieldOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated)
+}
+
+// optional bool weak = 10 [default = false];
+ bool FieldOptions::has_weak() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void FieldOptions::set_has_weak() {
+ _has_bits_[0] |= 0x00000010u;
+}
+ void FieldOptions::clear_has_weak() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+ void FieldOptions::clear_weak() {
+ weak_ = false;
+ clear_has_weak();
+}
+ bool FieldOptions::weak() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak)
+ return weak_;
+}
+ void FieldOptions::set_weak(bool value) {
+ set_has_weak();
+ weak_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int FieldOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+ void FieldOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+FieldOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -6838,19 +9539,17 @@ EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const {
void EnumOptions::Clear() {
_extensions_.Clear();
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<EnumOptions*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<EnumOptions*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
ZR_(allow_alias_, deprecated_);
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
uninterpreted_option_.Clear();
@@ -7108,6 +9807,88 @@ void EnumOptions::InternalSwap(EnumOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumOptions
+
+// optional bool allow_alias = 2;
+ bool EnumOptions::has_allow_alias() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumOptions::set_has_allow_alias() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void EnumOptions::clear_has_allow_alias() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumOptions::clear_allow_alias() {
+ allow_alias_ = false;
+ clear_has_allow_alias();
+}
+ bool EnumOptions::allow_alias() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias)
+ return allow_alias_;
+}
+ void EnumOptions::set_allow_alias(bool value) {
+ set_has_allow_alias();
+ allow_alias_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias)
+}
+
+// optional bool deprecated = 3 [default = false];
+ bool EnumOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void EnumOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void EnumOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void EnumOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool EnumOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated)
+ return deprecated_;
+}
+ void EnumOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int EnumOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+ void EnumOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -7396,6 +10177,64 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// EnumValueOptions
+
+// optional bool deprecated = 1 [default = false];
+ bool EnumValueOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void EnumValueOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void EnumValueOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void EnumValueOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool EnumValueOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated)
+ return deprecated_;
+}
+ void EnumValueOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int EnumValueOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+ void EnumValueOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+EnumValueOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -7684,6 +10523,64 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ServiceOptions
+
+// optional bool deprecated = 33 [default = false];
+ bool ServiceOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void ServiceOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void ServiceOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void ServiceOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool ServiceOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated)
+ return deprecated_;
+}
+ void ServiceOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int ServiceOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+ void ServiceOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ServiceOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -7972,6 +10869,64 @@ void MethodOptions::InternalSwap(MethodOptions* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// MethodOptions
+
+// optional bool deprecated = 33 [default = false];
+ bool MethodOptions::has_deprecated() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void MethodOptions::set_has_deprecated() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void MethodOptions::clear_has_deprecated() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void MethodOptions::clear_deprecated() {
+ deprecated_ = false;
+ clear_has_deprecated();
+}
+ bool MethodOptions::deprecated() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated)
+ return deprecated_;
+}
+ void MethodOptions::set_deprecated(bool value) {
+ set_has_deprecated();
+ deprecated_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated)
+}
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+ int MethodOptions::uninterpreted_option_size() const {
+ return uninterpreted_option_.size();
+}
+ void MethodOptions::clear_uninterpreted_option() {
+ uninterpreted_option_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() {
+ // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+MethodOptions::mutable_uninterpreted_option() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return &uninterpreted_option_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -8359,15 +11314,13 @@ UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena)
}
void UninterpretedOption::Clear() {
-#define OFFSET_OF_FIELD_(f) (reinterpret_cast<char*>( \
- &reinterpret_cast<UninterpretedOption*>(16)->f) - \
- reinterpret_cast<char*>(16))
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+ &reinterpret_cast<UninterpretedOption*>(16)->f)
-#define ZR_(first, last) do { \
- size_t f = OFFSET_OF_FIELD_(first); \
- size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \
- ::memset(&first, 0, n); \
- } while (0)
+#define ZR_(first, last) do {\
+ ::memset(&first, 0,\
+ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\
+} while (0)
if (_has_bits_[0 / 32] & 126) {
ZR_(positive_int_value_, double_value_);
@@ -8382,7 +11335,7 @@ void UninterpretedOption::Clear() {
}
}
-#undef OFFSET_OF_FIELD_
+#undef ZR_HELPER_
#undef ZR_
name_.Clear();
@@ -8799,6 +11752,352 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// UninterpretedOption_NamePart
+
+// required string name_part = 1;
+ bool UninterpretedOption_NamePart::has_name_part() const {
+ return (_has_bits_[0] & 0x00000001u) != 0;
+}
+ void UninterpretedOption_NamePart::set_has_name_part() {
+ _has_bits_[0] |= 0x00000001u;
+}
+ void UninterpretedOption_NamePart::clear_has_name_part() {
+ _has_bits_[0] &= ~0x00000001u;
+}
+ void UninterpretedOption_NamePart::clear_name_part() {
+ name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_name_part();
+}
+ const ::std::string& UninterpretedOption_NamePart::name_part() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part)
+ return name_part_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) {
+ set_has_name_part();
+ name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value) {
+ set_has_name_part();
+ name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) {
+ set_has_name_part();
+ name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+ ::std::string* UninterpretedOption_NamePart::mutable_name_part() {
+ set_has_name_part();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part)
+ return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption_NamePart::release_name_part() {
+ clear_has_name_part();
+ return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) {
+ if (name_part != NULL) {
+ set_has_name_part();
+ } else {
+ clear_has_name_part();
+ }
+ name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part)
+}
+
+// required bool is_extension = 2;
+ bool UninterpretedOption_NamePart::has_is_extension() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void UninterpretedOption_NamePart::set_has_is_extension() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void UninterpretedOption_NamePart::clear_has_is_extension() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void UninterpretedOption_NamePart::clear_is_extension() {
+ is_extension_ = false;
+ clear_has_is_extension();
+}
+ bool UninterpretedOption_NamePart::is_extension() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension)
+ return is_extension_;
+}
+ void UninterpretedOption_NamePart::set_is_extension(bool value) {
+ set_has_is_extension();
+ is_extension_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension)
+}
+
+// -------------------------------------------------------------------
+
+// UninterpretedOption
+
+// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
+ int UninterpretedOption::name_size() const {
+ return name_.size();
+}
+ void UninterpretedOption::clear_name() {
+ name_.Clear();
+}
+ const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name)
+ return name_.Get(index);
+}
+ ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name)
+ return name_.Mutable(index);
+}
+ ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() {
+ // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
+ return name_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+ return name_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+UninterpretedOption::mutable_name() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
+ return &name_;
+}
+
+// optional string identifier_value = 3;
+ bool UninterpretedOption::has_identifier_value() const {
+ return (_has_bits_[0] & 0x00000002u) != 0;
+}
+ void UninterpretedOption::set_has_identifier_value() {
+ _has_bits_[0] |= 0x00000002u;
+}
+ void UninterpretedOption::clear_has_identifier_value() {
+ _has_bits_[0] &= ~0x00000002u;
+}
+ void UninterpretedOption::clear_identifier_value() {
+ identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_identifier_value();
+}
+ const ::std::string& UninterpretedOption::identifier_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value)
+ return identifier_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_identifier_value(const ::std::string& value) {
+ set_has_identifier_value();
+ identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value) {
+ set_has_identifier_value();
+ identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
+}
+ void UninterpretedOption::set_identifier_value(const char* value, size_t size) {
+ set_has_identifier_value();
+ identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
+}
+ ::std::string* UninterpretedOption::mutable_identifier_value() {
+ set_has_identifier_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value)
+ return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_identifier_value() {
+ clear_has_identifier_value();
+ return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) {
+ if (identifier_value != NULL) {
+ set_has_identifier_value();
+ } else {
+ clear_has_identifier_value();
+ }
+ identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value)
+}
+
+// optional uint64 positive_int_value = 4;
+ bool UninterpretedOption::has_positive_int_value() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void UninterpretedOption::set_has_positive_int_value() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void UninterpretedOption::clear_has_positive_int_value() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void UninterpretedOption::clear_positive_int_value() {
+ positive_int_value_ = GOOGLE_ULONGLONG(0);
+ clear_has_positive_int_value();
+}
+ ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value)
+ return positive_int_value_;
+}
+ void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) {
+ set_has_positive_int_value();
+ positive_int_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value)
+}
+
+// optional int64 negative_int_value = 5;
+ bool UninterpretedOption::has_negative_int_value() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void UninterpretedOption::set_has_negative_int_value() {
+ _has_bits_[0] |= 0x00000008u;
+}
+ void UninterpretedOption::clear_has_negative_int_value() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+ void UninterpretedOption::clear_negative_int_value() {
+ negative_int_value_ = GOOGLE_LONGLONG(0);
+ clear_has_negative_int_value();
+}
+ ::google::protobuf::int64 UninterpretedOption::negative_int_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value)
+ return negative_int_value_;
+}
+ void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) {
+ set_has_negative_int_value();
+ negative_int_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value)
+}
+
+// optional double double_value = 6;
+ bool UninterpretedOption::has_double_value() const {
+ return (_has_bits_[0] & 0x00000010u) != 0;
+}
+ void UninterpretedOption::set_has_double_value() {
+ _has_bits_[0] |= 0x00000010u;
+}
+ void UninterpretedOption::clear_has_double_value() {
+ _has_bits_[0] &= ~0x00000010u;
+}
+ void UninterpretedOption::clear_double_value() {
+ double_value_ = 0;
+ clear_has_double_value();
+}
+ double UninterpretedOption::double_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value)
+ return double_value_;
+}
+ void UninterpretedOption::set_double_value(double value) {
+ set_has_double_value();
+ double_value_ = value;
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value)
+}
+
+// optional bytes string_value = 7;
+ bool UninterpretedOption::has_string_value() const {
+ return (_has_bits_[0] & 0x00000020u) != 0;
+}
+ void UninterpretedOption::set_has_string_value() {
+ _has_bits_[0] |= 0x00000020u;
+}
+ void UninterpretedOption::clear_has_string_value() {
+ _has_bits_[0] &= ~0x00000020u;
+}
+ void UninterpretedOption::clear_string_value() {
+ string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_string_value();
+}
+ const ::std::string& UninterpretedOption::string_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value)
+ return string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_string_value(const ::std::string& value) {
+ set_has_string_value();
+ string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const char* value) {
+ set_has_string_value();
+ string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
+}
+ void UninterpretedOption::set_string_value(const void* value, size_t size) {
+ set_has_string_value();
+ string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
+}
+ ::std::string* UninterpretedOption::mutable_string_value() {
+ set_has_string_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value)
+ return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_string_value() {
+ clear_has_string_value();
+ return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_string_value(::std::string* string_value) {
+ if (string_value != NULL) {
+ set_has_string_value();
+ } else {
+ clear_has_string_value();
+ }
+ string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value)
+}
+
+// optional string aggregate_value = 8;
+ bool UninterpretedOption::has_aggregate_value() const {
+ return (_has_bits_[0] & 0x00000040u) != 0;
+}
+ void UninterpretedOption::set_has_aggregate_value() {
+ _has_bits_[0] |= 0x00000040u;
+}
+ void UninterpretedOption::clear_has_aggregate_value() {
+ _has_bits_[0] &= ~0x00000040u;
+}
+ void UninterpretedOption::clear_aggregate_value() {
+ aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_aggregate_value();
+}
+ const ::std::string& UninterpretedOption::aggregate_value() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value)
+ return aggregate_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_aggregate_value(const ::std::string& value) {
+ set_has_aggregate_value();
+ aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value) {
+ set_has_aggregate_value();
+ aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ void UninterpretedOption::set_aggregate_value(const char* value, size_t size) {
+ set_has_aggregate_value();
+ aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
+}
+ ::std::string* UninterpretedOption::mutable_aggregate_value() {
+ set_has_aggregate_value();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value)
+ return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* UninterpretedOption::release_aggregate_value() {
+ clear_has_aggregate_value();
+ return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) {
+ if (aggregate_value != NULL) {
+ set_has_aggregate_value();
+ } else {
+ clear_has_aggregate_value();
+ }
+ aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value)
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// ===================================================================
@@ -8807,6 +12106,7 @@ const int SourceCodeInfo_Location::kPathFieldNumber;
const int SourceCodeInfo_Location::kSpanFieldNumber;
const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber;
const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber;
+const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber;
#endif // !_MSC_VER
SourceCodeInfo_Location::SourceCodeInfo_Location()
@@ -8882,6 +12182,7 @@ void SourceCodeInfo_Location::Clear() {
}
path_.Clear();
span_.Clear();
+ leading_detached_comments_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
if (_internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->Clear();
@@ -8963,6 +12264,25 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
+ if (input->ExpectTag(50)) goto parse_leading_detached_comments;
+ break;
+ }
+
+ // repeated string leading_detached_comments = 6;
+ case 6: {
+ if (tag == 50) {
+ parse_leading_detached_comments:
+ DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+ input, this->add_leading_detached_comments()));
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(),
+ this->leading_detached_comments(this->leading_detached_comments_size() - 1).length(),
+ ::google::protobuf::internal::WireFormat::PARSE,
+ "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+ } else {
+ goto handle_unusual;
+ }
+ if (input->ExpectTag(50)) goto parse_leading_detached_comments;
if (input->ExpectAtEnd()) goto success;
break;
}
@@ -9032,6 +12352,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
4, this->trailing_comments(), output);
}
+ // repeated string leading_detached_comments = 6;
+ for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+ ::google::protobuf::internal::WireFormatLite::WriteString(
+ 6, this->leading_detached_comments(i), output);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
@@ -9092,6 +12422,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes(
4, this->trailing_comments(), target);
}
+ // repeated string leading_detached_comments = 6;
+ for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+ ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+ this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+ ::google::protobuf::internal::WireFormat::SERIALIZE,
+ "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
+ target = ::google::protobuf::internal::WireFormatLite::
+ WriteStringToArray(6, this->leading_detached_comments(i), target);
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
@@ -9153,6 +12493,13 @@ int SourceCodeInfo_Location::ByteSize() const {
total_size += data_size;
}
+ // repeated string leading_detached_comments = 6;
+ total_size += 1 * this->leading_detached_comments_size();
+ for (int i = 0; i < this->leading_detached_comments_size(); i++) {
+ total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->leading_detached_comments(i));
+ }
+
if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
@@ -9180,6 +12527,7 @@ void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
path_.MergeFrom(from.path_);
span_.MergeFrom(from.span_);
+ leading_detached_comments_.MergeFrom(from.leading_detached_comments_);
if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) {
if (from.has_leading_comments()) {
set_has_leading_comments();
@@ -9221,6 +12569,7 @@ void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) {
span_.UnsafeArenaSwap(&other->span_);
leading_comments_.Swap(&other->leading_comments_);
trailing_comments_.Swap(&other->trailing_comments_);
+ leading_detached_comments_.UnsafeArenaSwap(&other->leading_detached_comments_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_internal_metadata_.Swap(&other->_internal_metadata_);
std::swap(_cached_size_, other->_cached_size_);
@@ -9464,6 +12813,264 @@ void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
return metadata;
}
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// SourceCodeInfo_Location
+
+// repeated int32 path = 1 [packed = true];
+ int SourceCodeInfo_Location::path_size() const {
+ return path_.size();
+}
+ void SourceCodeInfo_Location::clear_path() {
+ path_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path)
+ return path_.Get(index);
+}
+ void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) {
+ path_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path)
+}
+ void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) {
+ path_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::path() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path)
+ return path_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_path() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path)
+ return &path_;
+}
+
+// repeated int32 span = 2 [packed = true];
+ int SourceCodeInfo_Location::span_size() const {
+ return span_.size();
+}
+ void SourceCodeInfo_Location::clear_span() {
+ span_.Clear();
+}
+ ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span)
+ return span_.Get(index);
+}
+ void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) {
+ span_.Set(index, value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span)
+}
+ void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) {
+ span_.Add(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span)
+}
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+SourceCodeInfo_Location::span() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span)
+ return span_;
+}
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+SourceCodeInfo_Location::mutable_span() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span)
+ return &span_;
+}
+
+// optional string leading_comments = 3;
+ bool SourceCodeInfo_Location::has_leading_comments() const {
+ return (_has_bits_[0] & 0x00000004u) != 0;
+}
+ void SourceCodeInfo_Location::set_has_leading_comments() {
+ _has_bits_[0] |= 0x00000004u;
+}
+ void SourceCodeInfo_Location::clear_has_leading_comments() {
+ _has_bits_[0] &= ~0x00000004u;
+}
+ void SourceCodeInfo_Location::clear_leading_comments() {
+ leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_leading_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_comments() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments)
+ return leading_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) {
+ set_has_leading_comments();
+ leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value) {
+ set_has_leading_comments();
+ leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) {
+ set_has_leading_comments();
+ leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_comments() {
+ set_has_leading_comments();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments)
+ return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_leading_comments() {
+ clear_has_leading_comments();
+ return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) {
+ if (leading_comments != NULL) {
+ set_has_leading_comments();
+ } else {
+ clear_has_leading_comments();
+ }
+ leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments)
+}
+
+// optional string trailing_comments = 4;
+ bool SourceCodeInfo_Location::has_trailing_comments() const {
+ return (_has_bits_[0] & 0x00000008u) != 0;
+}
+ void SourceCodeInfo_Location::set_has_trailing_comments() {
+ _has_bits_[0] |= 0x00000008u;
+}
+ void SourceCodeInfo_Location::clear_has_trailing_comments() {
+ _has_bits_[0] &= ~0x00000008u;
+}
+ void SourceCodeInfo_Location::clear_trailing_comments() {
+ trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_trailing_comments();
+}
+ const ::std::string& SourceCodeInfo_Location::trailing_comments() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+ return trailing_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) {
+ set_has_trailing_comments();
+ trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
+ set_has_trailing_comments();
+ trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) {
+ set_has_trailing_comments();
+ trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+ ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
+ set_has_trailing_comments();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+ return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ ::std::string* SourceCodeInfo_Location::release_trailing_comments() {
+ clear_has_trailing_comments();
+ return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+ void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) {
+ if (trailing_comments != NULL) {
+ set_has_trailing_comments();
+ } else {
+ clear_has_trailing_comments();
+ }
+ trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
+}
+
+// repeated string leading_detached_comments = 6;
+ int SourceCodeInfo_Location::leading_detached_comments_size() const {
+ return leading_detached_comments_.size();
+}
+ void SourceCodeInfo_Location::clear_leading_detached_comments() {
+ leading_detached_comments_.Clear();
+}
+ const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Get(index);
+}
+ ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Mutable(index);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ leading_detached_comments_.Mutable(index)->assign(value);
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+ leading_detached_comments_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+ leading_detached_comments_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+ return leading_detached_comments_.Add();
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+ leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+ const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_;
+}
+ ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return &leading_detached_comments_;
+}
+
+// -------------------------------------------------------------------
+
+// SourceCodeInfo
+
+// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
+ int SourceCodeInfo::location_size() const {
+ return location_.size();
+}
+ void SourceCodeInfo::clear_location() {
+ location_.Clear();
+}
+ const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location)
+ return location_.Get(index);
+}
+ ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location)
+ return location_.Mutable(index);
+}
+ ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() {
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
+ return location_.Add();
+}
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+ return location_;
+}
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+SourceCodeInfo::mutable_location() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
+ return &location_;
+}
+
+#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index cda25982..d8cba659 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -222,15 +222,15 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
// accessors -------------------------------------------------------
// repeated .google.protobuf.FileDescriptorProto file = 1;
- inline int file_size() const;
- inline void clear_file();
+ int file_size() const;
+ void clear_file();
static const int kFileFieldNumber = 1;
- inline const ::google::protobuf::FileDescriptorProto& file(int index) const;
- inline ::google::protobuf::FileDescriptorProto* mutable_file(int index);
- inline ::google::protobuf::FileDescriptorProto* add_file();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ const ::google::protobuf::FileDescriptorProto& file(int index) const;
+ ::google::protobuf::FileDescriptorProto* mutable_file(int index);
+ ::google::protobuf::FileDescriptorProto* add_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
file() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_file();
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
@@ -314,146 +314,146 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional string package = 2;
- inline bool has_package() const;
- inline void clear_package();
+ bool has_package() const;
+ void clear_package();
static const int kPackageFieldNumber = 2;
- inline const ::std::string& package() const;
- inline void set_package(const ::std::string& value);
- inline void set_package(const char* value);
- inline void set_package(const char* value, size_t size);
- inline ::std::string* mutable_package();
- inline ::std::string* release_package();
- inline void set_allocated_package(::std::string* package);
+ const ::std::string& package() const;
+ void set_package(const ::std::string& value);
+ void set_package(const char* value);
+ void set_package(const char* value, size_t size);
+ ::std::string* mutable_package();
+ ::std::string* release_package();
+ void set_allocated_package(::std::string* package);
// repeated string dependency = 3;
- inline int dependency_size() const;
- inline void clear_dependency();
+ int dependency_size() const;
+ void clear_dependency();
static const int kDependencyFieldNumber = 3;
- inline const ::std::string& dependency(int index) const;
- inline ::std::string* mutable_dependency(int index);
- inline void set_dependency(int index, const ::std::string& value);
- inline void set_dependency(int index, const char* value);
- inline void set_dependency(int index, const char* value, size_t size);
- inline ::std::string* add_dependency();
- inline void add_dependency(const ::std::string& value);
- inline void add_dependency(const char* value);
- inline void add_dependency(const char* value, size_t size);
- inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
- inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
+ const ::std::string& dependency(int index) const;
+ ::std::string* mutable_dependency(int index);
+ void set_dependency(int index, const ::std::string& value);
+ void set_dependency(int index, const char* value);
+ void set_dependency(int index, const char* value, size_t size);
+ ::std::string* add_dependency();
+ void add_dependency(const ::std::string& value);
+ void add_dependency(const char* value);
+ void add_dependency(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency();
// repeated int32 public_dependency = 10;
- inline int public_dependency_size() const;
- inline void clear_public_dependency();
+ int public_dependency_size() const;
+ void clear_public_dependency();
static const int kPublicDependencyFieldNumber = 10;
- inline ::google::protobuf::int32 public_dependency(int index) const;
- inline void set_public_dependency(int index, ::google::protobuf::int32 value);
- inline void add_public_dependency(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 public_dependency(int index) const;
+ void set_public_dependency(int index, ::google::protobuf::int32 value);
+ void add_public_dependency(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
public_dependency() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_public_dependency();
// repeated int32 weak_dependency = 11;
- inline int weak_dependency_size() const;
- inline void clear_weak_dependency();
+ int weak_dependency_size() const;
+ void clear_weak_dependency();
static const int kWeakDependencyFieldNumber = 11;
- inline ::google::protobuf::int32 weak_dependency(int index) const;
- inline void set_weak_dependency(int index, ::google::protobuf::int32 value);
- inline void add_weak_dependency(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 weak_dependency(int index) const;
+ void set_weak_dependency(int index, ::google::protobuf::int32 value);
+ void add_weak_dependency(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
weak_dependency() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_weak_dependency();
// repeated .google.protobuf.DescriptorProto message_type = 4;
- inline int message_type_size() const;
- inline void clear_message_type();
+ int message_type_size() const;
+ void clear_message_type();
static const int kMessageTypeFieldNumber = 4;
- inline const ::google::protobuf::DescriptorProto& message_type(int index) const;
- inline ::google::protobuf::DescriptorProto* mutable_message_type(int index);
- inline ::google::protobuf::DescriptorProto* add_message_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ const ::google::protobuf::DescriptorProto& message_type(int index) const;
+ ::google::protobuf::DescriptorProto* mutable_message_type(int index);
+ ::google::protobuf::DescriptorProto* add_message_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
message_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_message_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
- inline int enum_type_size() const;
- inline void clear_enum_type();
+ int enum_type_size() const;
+ void clear_enum_type();
static const int kEnumTypeFieldNumber = 5;
- inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
- inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
- inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+ ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+ ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
- inline int service_size() const;
- inline void clear_service();
+ int service_size() const;
+ void clear_service();
static const int kServiceFieldNumber = 6;
- inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
- inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
- inline ::google::protobuf::ServiceDescriptorProto* add_service();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+ const ::google::protobuf::ServiceDescriptorProto& service(int index) const;
+ ::google::protobuf::ServiceDescriptorProto* mutable_service(int index);
+ ::google::protobuf::ServiceDescriptorProto* add_service();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
service() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
mutable_service();
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
- inline int extension_size() const;
- inline void clear_extension();
+ int extension_size() const;
+ void clear_extension();
static const int kExtensionFieldNumber = 7;
- inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
- inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
- inline ::google::protobuf::FieldDescriptorProto* add_extension();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+ ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+ ::google::protobuf::FieldDescriptorProto* add_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
// optional .google.protobuf.FileOptions options = 8;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 8;
- inline const ::google::protobuf::FileOptions& options() const;
- inline ::google::protobuf::FileOptions* mutable_options();
- inline ::google::protobuf::FileOptions* release_options();
- inline void set_allocated_options(::google::protobuf::FileOptions* options);
+ const ::google::protobuf::FileOptions& options() const;
+ ::google::protobuf::FileOptions* mutable_options();
+ ::google::protobuf::FileOptions* release_options();
+ void set_allocated_options(::google::protobuf::FileOptions* options);
// optional .google.protobuf.SourceCodeInfo source_code_info = 9;
- inline bool has_source_code_info() const;
- inline void clear_source_code_info();
+ bool has_source_code_info() const;
+ void clear_source_code_info();
static const int kSourceCodeInfoFieldNumber = 9;
- inline const ::google::protobuf::SourceCodeInfo& source_code_info() const;
- inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
- inline ::google::protobuf::SourceCodeInfo* release_source_code_info();
- inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
+ const ::google::protobuf::SourceCodeInfo& source_code_info() const;
+ ::google::protobuf::SourceCodeInfo* mutable_source_code_info();
+ ::google::protobuf::SourceCodeInfo* release_source_code_info();
+ void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info);
// optional string syntax = 12;
- inline bool has_syntax() const;
- inline void clear_syntax();
+ bool has_syntax() const;
+ void clear_syntax();
static const int kSyntaxFieldNumber = 12;
- inline const ::std::string& syntax() const;
- inline void set_syntax(const ::std::string& value);
- inline void set_syntax(const char* value);
- inline void set_syntax(const char* value, size_t size);
- inline ::std::string* mutable_syntax();
- inline ::std::string* release_syntax();
- inline void set_allocated_syntax(::std::string* syntax);
+ const ::std::string& syntax() const;
+ void set_syntax(const ::std::string& value);
+ void set_syntax(const char* value);
+ void set_syntax(const char* value, size_t size);
+ ::std::string* mutable_syntax();
+ ::std::string* release_syntax();
+ void set_allocated_syntax(::std::string* syntax);
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto)
private:
@@ -557,18 +557,18 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto
// accessors -------------------------------------------------------
// optional int32 start = 1;
- inline bool has_start() const;
- inline void clear_start();
+ bool has_start() const;
+ void clear_start();
static const int kStartFieldNumber = 1;
- inline ::google::protobuf::int32 start() const;
- inline void set_start(::google::protobuf::int32 value);
+ ::google::protobuf::int32 start() const;
+ void set_start(::google::protobuf::int32 value);
// optional int32 end = 2;
- inline bool has_end() const;
- inline void clear_end();
+ bool has_end() const;
+ void clear_end();
static const int kEndFieldNumber = 2;
- inline ::google::protobuf::int32 end() const;
- inline void set_end(::google::protobuf::int32 value);
+ ::google::protobuf::int32 end() const;
+ void set_end(::google::protobuf::int32 value);
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
private:
@@ -658,97 +658,97 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// repeated .google.protobuf.FieldDescriptorProto field = 2;
- inline int field_size() const;
- inline void clear_field();
+ int field_size() const;
+ void clear_field();
static const int kFieldFieldNumber = 2;
- inline const ::google::protobuf::FieldDescriptorProto& field(int index) const;
- inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
- inline ::google::protobuf::FieldDescriptorProto* add_field();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ const ::google::protobuf::FieldDescriptorProto& field(int index) const;
+ ::google::protobuf::FieldDescriptorProto* mutable_field(int index);
+ ::google::protobuf::FieldDescriptorProto* add_field();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
field() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_field();
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
- inline int extension_size() const;
- inline void clear_extension();
+ int extension_size() const;
+ void clear_extension();
static const int kExtensionFieldNumber = 6;
- inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
- inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
- inline ::google::protobuf::FieldDescriptorProto* add_extension();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ const ::google::protobuf::FieldDescriptorProto& extension(int index) const;
+ ::google::protobuf::FieldDescriptorProto* mutable_extension(int index);
+ ::google::protobuf::FieldDescriptorProto* add_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
extension() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
// repeated .google.protobuf.DescriptorProto nested_type = 3;
- inline int nested_type_size() const;
- inline void clear_nested_type();
+ int nested_type_size() const;
+ void clear_nested_type();
static const int kNestedTypeFieldNumber = 3;
- inline const ::google::protobuf::DescriptorProto& nested_type(int index) const;
- inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
- inline ::google::protobuf::DescriptorProto* add_nested_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ const ::google::protobuf::DescriptorProto& nested_type(int index) const;
+ ::google::protobuf::DescriptorProto* mutable_nested_type(int index);
+ ::google::protobuf::DescriptorProto* add_nested_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
nested_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_nested_type();
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
- inline int enum_type_size() const;
- inline void clear_enum_type();
+ int enum_type_size() const;
+ void clear_enum_type();
static const int kEnumTypeFieldNumber = 4;
- inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
- inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
- inline ::google::protobuf::EnumDescriptorProto* add_enum_type();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const;
+ ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index);
+ ::google::protobuf::EnumDescriptorProto* add_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
enum_type() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
- inline int extension_range_size() const;
- inline void clear_extension_range();
+ int extension_range_size() const;
+ void clear_extension_range();
static const int kExtensionRangeFieldNumber = 5;
- inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
- inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
- inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+ const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const;
+ ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index);
+ ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
extension_range() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
mutable_extension_range();
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
- inline int oneof_decl_size() const;
- inline void clear_oneof_decl();
+ int oneof_decl_size() const;
+ void clear_oneof_decl();
static const int kOneofDeclFieldNumber = 8;
- inline const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
- inline ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
- inline ::google::protobuf::OneofDescriptorProto* add_oneof_decl();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+ const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const;
+ ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index);
+ ::google::protobuf::OneofDescriptorProto* add_oneof_decl();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
oneof_decl() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
mutable_oneof_decl();
// optional .google.protobuf.MessageOptions options = 7;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 7;
- inline const ::google::protobuf::MessageOptions& options() const;
- inline ::google::protobuf::MessageOptions* mutable_options();
- inline ::google::protobuf::MessageOptions* release_options();
- inline void set_allocated_options(::google::protobuf::MessageOptions* options);
+ const ::google::protobuf::MessageOptions& options() const;
+ ::google::protobuf::MessageOptions* mutable_options();
+ ::google::protobuf::MessageOptions* release_options();
+ void set_allocated_options(::google::protobuf::MessageOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto)
private:
@@ -907,89 +907,89 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional int32 number = 3;
- inline bool has_number() const;
- inline void clear_number();
+ bool has_number() const;
+ void clear_number();
static const int kNumberFieldNumber = 3;
- inline ::google::protobuf::int32 number() const;
- inline void set_number(::google::protobuf::int32 value);
+ ::google::protobuf::int32 number() const;
+ void set_number(::google::protobuf::int32 value);
// optional .google.protobuf.FieldDescriptorProto.Label label = 4;
- inline bool has_label() const;
- inline void clear_label();
+ bool has_label() const;
+ void clear_label();
static const int kLabelFieldNumber = 4;
- inline ::google::protobuf::FieldDescriptorProto_Label label() const;
- inline void set_label(::google::protobuf::FieldDescriptorProto_Label value);
+ ::google::protobuf::FieldDescriptorProto_Label label() const;
+ void set_label(::google::protobuf::FieldDescriptorProto_Label value);
// optional .google.protobuf.FieldDescriptorProto.Type type = 5;
- inline bool has_type() const;
- inline void clear_type();
+ bool has_type() const;
+ void clear_type();
static const int kTypeFieldNumber = 5;
- inline ::google::protobuf::FieldDescriptorProto_Type type() const;
- inline void set_type(::google::protobuf::FieldDescriptorProto_Type value);
+ ::google::protobuf::FieldDescriptorProto_Type type() const;
+ void set_type(::google::protobuf::FieldDescriptorProto_Type value);
// optional string type_name = 6;
- inline bool has_type_name() const;
- inline void clear_type_name();
+ bool has_type_name() const;
+ void clear_type_name();
static const int kTypeNameFieldNumber = 6;
- inline const ::std::string& type_name() const;
- inline void set_type_name(const ::std::string& value);
- inline void set_type_name(const char* value);
- inline void set_type_name(const char* value, size_t size);
- inline ::std::string* mutable_type_name();
- inline ::std::string* release_type_name();
- inline void set_allocated_type_name(::std::string* type_name);
+ const ::std::string& type_name() const;
+ void set_type_name(const ::std::string& value);
+ void set_type_name(const char* value);
+ void set_type_name(const char* value, size_t size);
+ ::std::string* mutable_type_name();
+ ::std::string* release_type_name();
+ void set_allocated_type_name(::std::string* type_name);
// optional string extendee = 2;
- inline bool has_extendee() const;
- inline void clear_extendee();
+ bool has_extendee() const;
+ void clear_extendee();
static const int kExtendeeFieldNumber = 2;
- inline const ::std::string& extendee() const;
- inline void set_extendee(const ::std::string& value);
- inline void set_extendee(const char* value);
- inline void set_extendee(const char* value, size_t size);
- inline ::std::string* mutable_extendee();
- inline ::std::string* release_extendee();
- inline void set_allocated_extendee(::std::string* extendee);
+ const ::std::string& extendee() const;
+ void set_extendee(const ::std::string& value);
+ void set_extendee(const char* value);
+ void set_extendee(const char* value, size_t size);
+ ::std::string* mutable_extendee();
+ ::std::string* release_extendee();
+ void set_allocated_extendee(::std::string* extendee);
// optional string default_value = 7;
- inline bool has_default_value() const;
- inline void clear_default_value();
+ bool has_default_value() const;
+ void clear_default_value();
static const int kDefaultValueFieldNumber = 7;
- inline const ::std::string& default_value() const;
- inline void set_default_value(const ::std::string& value);
- inline void set_default_value(const char* value);
- inline void set_default_value(const char* value, size_t size);
- inline ::std::string* mutable_default_value();
- inline ::std::string* release_default_value();
- inline void set_allocated_default_value(::std::string* default_value);
+ const ::std::string& default_value() const;
+ void set_default_value(const ::std::string& value);
+ void set_default_value(const char* value);
+ void set_default_value(const char* value, size_t size);
+ ::std::string* mutable_default_value();
+ ::std::string* release_default_value();
+ void set_allocated_default_value(::std::string* default_value);
// optional int32 oneof_index = 9;
- inline bool has_oneof_index() const;
- inline void clear_oneof_index();
+ bool has_oneof_index() const;
+ void clear_oneof_index();
static const int kOneofIndexFieldNumber = 9;
- inline ::google::protobuf::int32 oneof_index() const;
- inline void set_oneof_index(::google::protobuf::int32 value);
+ ::google::protobuf::int32 oneof_index() const;
+ void set_oneof_index(::google::protobuf::int32 value);
// optional .google.protobuf.FieldOptions options = 8;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 8;
- inline const ::google::protobuf::FieldOptions& options() const;
- inline ::google::protobuf::FieldOptions* mutable_options();
- inline ::google::protobuf::FieldOptions* release_options();
- inline void set_allocated_options(::google::protobuf::FieldOptions* options);
+ const ::google::protobuf::FieldOptions& options() const;
+ ::google::protobuf::FieldOptions* mutable_options();
+ ::google::protobuf::FieldOptions* release_options();
+ void set_allocated_options(::google::protobuf::FieldOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto)
private:
@@ -1098,16 +1098,16 @@ class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Messa
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto)
private:
@@ -1192,37 +1192,37 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// repeated .google.protobuf.EnumValueDescriptorProto value = 2;
- inline int value_size() const;
- inline void clear_value();
+ int value_size() const;
+ void clear_value();
static const int kValueFieldNumber = 2;
- inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
- inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
- inline ::google::protobuf::EnumValueDescriptorProto* add_value();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+ const ::google::protobuf::EnumValueDescriptorProto& value(int index) const;
+ ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index);
+ ::google::protobuf::EnumValueDescriptorProto* add_value();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
value() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
mutable_value();
// optional .google.protobuf.EnumOptions options = 3;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 3;
- inline const ::google::protobuf::EnumOptions& options() const;
- inline ::google::protobuf::EnumOptions* mutable_options();
- inline ::google::protobuf::EnumOptions* release_options();
- inline void set_allocated_options(::google::protobuf::EnumOptions* options);
+ const ::google::protobuf::EnumOptions& options() const;
+ ::google::protobuf::EnumOptions* mutable_options();
+ ::google::protobuf::EnumOptions* release_options();
+ void set_allocated_options(::google::protobuf::EnumOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto)
private:
@@ -1311,32 +1311,32 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional int32 number = 2;
- inline bool has_number() const;
- inline void clear_number();
+ bool has_number() const;
+ void clear_number();
static const int kNumberFieldNumber = 2;
- inline ::google::protobuf::int32 number() const;
- inline void set_number(::google::protobuf::int32 value);
+ ::google::protobuf::int32 number() const;
+ void set_number(::google::protobuf::int32 value);
// optional .google.protobuf.EnumValueOptions options = 3;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 3;
- inline const ::google::protobuf::EnumValueOptions& options() const;
- inline ::google::protobuf::EnumValueOptions* mutable_options();
- inline ::google::protobuf::EnumValueOptions* release_options();
- inline void set_allocated_options(::google::protobuf::EnumValueOptions* options);
+ const ::google::protobuf::EnumValueOptions& options() const;
+ ::google::protobuf::EnumValueOptions* mutable_options();
+ ::google::protobuf::EnumValueOptions* release_options();
+ void set_allocated_options(::google::protobuf::EnumValueOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
private:
@@ -1427,37 +1427,37 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// repeated .google.protobuf.MethodDescriptorProto method = 2;
- inline int method_size() const;
- inline void clear_method();
+ int method_size() const;
+ void clear_method();
static const int kMethodFieldNumber = 2;
- inline const ::google::protobuf::MethodDescriptorProto& method(int index) const;
- inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
- inline ::google::protobuf::MethodDescriptorProto* add_method();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ const ::google::protobuf::MethodDescriptorProto& method(int index) const;
+ ::google::protobuf::MethodDescriptorProto* mutable_method(int index);
+ ::google::protobuf::MethodDescriptorProto* add_method();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
method() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
mutable_method();
// optional .google.protobuf.ServiceOptions options = 3;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 3;
- inline const ::google::protobuf::ServiceOptions& options() const;
- inline ::google::protobuf::ServiceOptions* mutable_options();
- inline ::google::protobuf::ServiceOptions* release_options();
- inline void set_allocated_options(::google::protobuf::ServiceOptions* options);
+ const ::google::protobuf::ServiceOptions& options() const;
+ ::google::protobuf::ServiceOptions* mutable_options();
+ ::google::protobuf::ServiceOptions* release_options();
+ void set_allocated_options(::google::protobuf::ServiceOptions* options);
// @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto)
private:
@@ -1546,63 +1546,63 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess
// accessors -------------------------------------------------------
// optional string name = 1;
- inline bool has_name() const;
- inline void clear_name();
+ bool has_name() const;
+ void clear_name();
static const int kNameFieldNumber = 1;
- inline const ::std::string& name() const;
- inline void set_name(const ::std::string& value);
- inline void set_name(const char* value);
- inline void set_name(const char* value, size_t size);
- inline ::std::string* mutable_name();
- inline ::std::string* release_name();
- inline void set_allocated_name(::std::string* name);
+ const ::std::string& name() const;
+ void set_name(const ::std::string& value);
+ void set_name(const char* value);
+ void set_name(const char* value, size_t size);
+ ::std::string* mutable_name();
+ ::std::string* release_name();
+ void set_allocated_name(::std::string* name);
// optional string input_type = 2;
- inline bool has_input_type() const;
- inline void clear_input_type();
+ bool has_input_type() const;
+ void clear_input_type();
static const int kInputTypeFieldNumber = 2;
- inline const ::std::string& input_type() const;
- inline void set_input_type(const ::std::string& value);
- inline void set_input_type(const char* value);
- inline void set_input_type(const char* value, size_t size);
- inline ::std::string* mutable_input_type();
- inline ::std::string* release_input_type();
- inline void set_allocated_input_type(::std::string* input_type);
+ const ::std::string& input_type() const;
+ void set_input_type(const ::std::string& value);
+ void set_input_type(const char* value);
+ void set_input_type(const char* value, size_t size);
+ ::std::string* mutable_input_type();
+ ::std::string* release_input_type();
+ void set_allocated_input_type(::std::string* input_type);
// optional string output_type = 3;
- inline bool has_output_type() const;
- inline void clear_output_type();
+ bool has_output_type() const;
+ void clear_output_type();
static const int kOutputTypeFieldNumber = 3;
- inline const ::std::string& output_type() const;
- inline void set_output_type(const ::std::string& value);
- inline void set_output_type(const char* value);
- inline void set_output_type(const char* value, size_t size);
- inline ::std::string* mutable_output_type();
- inline ::std::string* release_output_type();
- inline void set_allocated_output_type(::std::string* output_type);
+ const ::std::string& output_type() const;
+ void set_output_type(const ::std::string& value);
+ void set_output_type(const char* value);
+ void set_output_type(const char* value, size_t size);
+ ::std::string* mutable_output_type();
+ ::std::string* release_output_type();
+ void set_allocated_output_type(::std::string* output_type);
// optional .google.protobuf.MethodOptions options = 4;
- inline bool has_options() const;
- inline void clear_options();
+ bool has_options() const;
+ void clear_options();
static const int kOptionsFieldNumber = 4;
- inline const ::google::protobuf::MethodOptions& options() const;
- inline ::google::protobuf::MethodOptions* mutable_options();
- inline ::google::protobuf::MethodOptions* release_options();
- inline void set_allocated_options(::google::protobuf::MethodOptions* options);
+ const ::google::protobuf::MethodOptions& options() const;
+ ::google::protobuf::MethodOptions* mutable_options();
+ ::google::protobuf::MethodOptions* release_options();
+ void set_allocated_options(::google::protobuf::MethodOptions* options);
// optional bool client_streaming = 5 [default = false];
- inline bool has_client_streaming() const;
- inline void clear_client_streaming();
+ bool has_client_streaming() const;
+ void clear_client_streaming();
static const int kClientStreamingFieldNumber = 5;
- inline bool client_streaming() const;
- inline void set_client_streaming(bool value);
+ bool client_streaming() const;
+ void set_client_streaming(bool value);
// optional bool server_streaming = 6 [default = false];
- inline bool has_server_streaming() const;
- inline void clear_server_streaming();
+ bool has_server_streaming() const;
+ void clear_server_streaming();
static const int kServerStreamingFieldNumber = 6;
- inline bool server_streaming() const;
- inline void set_server_streaming(bool value);
+ bool server_streaming() const;
+ void set_server_streaming(bool value);
// @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto)
private:
@@ -1727,114 +1727,126 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional string java_package = 1;
- inline bool has_java_package() const;
- inline void clear_java_package();
+ bool has_java_package() const;
+ void clear_java_package();
static const int kJavaPackageFieldNumber = 1;
- inline const ::std::string& java_package() const;
- inline void set_java_package(const ::std::string& value);
- inline void set_java_package(const char* value);
- inline void set_java_package(const char* value, size_t size);
- inline ::std::string* mutable_java_package();
- inline ::std::string* release_java_package();
- inline void set_allocated_java_package(::std::string* java_package);
+ const ::std::string& java_package() const;
+ void set_java_package(const ::std::string& value);
+ void set_java_package(const char* value);
+ void set_java_package(const char* value, size_t size);
+ ::std::string* mutable_java_package();
+ ::std::string* release_java_package();
+ void set_allocated_java_package(::std::string* java_package);
// optional string java_outer_classname = 8;
- inline bool has_java_outer_classname() const;
- inline void clear_java_outer_classname();
+ bool has_java_outer_classname() const;
+ void clear_java_outer_classname();
static const int kJavaOuterClassnameFieldNumber = 8;
- inline const ::std::string& java_outer_classname() const;
- inline void set_java_outer_classname(const ::std::string& value);
- inline void set_java_outer_classname(const char* value);
- inline void set_java_outer_classname(const char* value, size_t size);
- inline ::std::string* mutable_java_outer_classname();
- inline ::std::string* release_java_outer_classname();
- inline void set_allocated_java_outer_classname(::std::string* java_outer_classname);
+ const ::std::string& java_outer_classname() const;
+ void set_java_outer_classname(const ::std::string& value);
+ void set_java_outer_classname(const char* value);
+ void set_java_outer_classname(const char* value, size_t size);
+ ::std::string* mutable_java_outer_classname();
+ ::std::string* release_java_outer_classname();
+ void set_allocated_java_outer_classname(::std::string* java_outer_classname);
// optional bool java_multiple_files = 10 [default = false];
- inline bool has_java_multiple_files() const;
- inline void clear_java_multiple_files();
+ bool has_java_multiple_files() const;
+ void clear_java_multiple_files();
static const int kJavaMultipleFilesFieldNumber = 10;
- inline bool java_multiple_files() const;
- inline void set_java_multiple_files(bool value);
+ bool java_multiple_files() const;
+ void set_java_multiple_files(bool value);
// optional bool java_generate_equals_and_hash = 20 [default = false];
- inline bool has_java_generate_equals_and_hash() const;
- inline void clear_java_generate_equals_and_hash();
+ bool has_java_generate_equals_and_hash() const;
+ void clear_java_generate_equals_and_hash();
static const int kJavaGenerateEqualsAndHashFieldNumber = 20;
- inline bool java_generate_equals_and_hash() const;
- inline void set_java_generate_equals_and_hash(bool value);
+ bool java_generate_equals_and_hash() const;
+ void set_java_generate_equals_and_hash(bool value);
// optional bool java_string_check_utf8 = 27 [default = false];
- inline bool has_java_string_check_utf8() const;
- inline void clear_java_string_check_utf8();
+ bool has_java_string_check_utf8() const;
+ void clear_java_string_check_utf8();
static const int kJavaStringCheckUtf8FieldNumber = 27;
- inline bool java_string_check_utf8() const;
- inline void set_java_string_check_utf8(bool value);
+ bool java_string_check_utf8() const;
+ void set_java_string_check_utf8(bool value);
// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
- inline bool has_optimize_for() const;
- inline void clear_optimize_for();
+ bool has_optimize_for() const;
+ void clear_optimize_for();
static const int kOptimizeForFieldNumber = 9;
- inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
- inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
+ ::google::protobuf::FileOptions_OptimizeMode optimize_for() const;
+ void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value);
// optional string go_package = 11;
- inline bool has_go_package() const;
- inline void clear_go_package();
+ bool has_go_package() const;
+ void clear_go_package();
static const int kGoPackageFieldNumber = 11;
- inline const ::std::string& go_package() const;
- inline void set_go_package(const ::std::string& value);
- inline void set_go_package(const char* value);
- inline void set_go_package(const char* value, size_t size);
- inline ::std::string* mutable_go_package();
- inline ::std::string* release_go_package();
- inline void set_allocated_go_package(::std::string* go_package);
+ const ::std::string& go_package() const;
+ void set_go_package(const ::std::string& value);
+ void set_go_package(const char* value);
+ void set_go_package(const char* value, size_t size);
+ ::std::string* mutable_go_package();
+ ::std::string* release_go_package();
+ void set_allocated_go_package(::std::string* go_package);
// optional bool cc_generic_services = 16 [default = false];
- inline bool has_cc_generic_services() const;
- inline void clear_cc_generic_services();
+ bool has_cc_generic_services() const;
+ void clear_cc_generic_services();
static const int kCcGenericServicesFieldNumber = 16;
- inline bool cc_generic_services() const;
- inline void set_cc_generic_services(bool value);
+ bool cc_generic_services() const;
+ void set_cc_generic_services(bool value);
// optional bool java_generic_services = 17 [default = false];
- inline bool has_java_generic_services() const;
- inline void clear_java_generic_services();
+ bool has_java_generic_services() const;
+ void clear_java_generic_services();
static const int kJavaGenericServicesFieldNumber = 17;
- inline bool java_generic_services() const;
- inline void set_java_generic_services(bool value);
+ bool java_generic_services() const;
+ void set_java_generic_services(bool value);
// optional bool py_generic_services = 18 [default = false];
- inline bool has_py_generic_services() const;
- inline void clear_py_generic_services();
+ bool has_py_generic_services() const;
+ void clear_py_generic_services();
static const int kPyGenericServicesFieldNumber = 18;
- inline bool py_generic_services() const;
- inline void set_py_generic_services(bool value);
+ bool py_generic_services() const;
+ void set_py_generic_services(bool value);
// optional bool deprecated = 23 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 23;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// optional bool cc_enable_arenas = 31 [default = false];
- inline bool has_cc_enable_arenas() const;
- inline void clear_cc_enable_arenas();
+ bool has_cc_enable_arenas() const;
+ void clear_cc_enable_arenas();
static const int kCcEnableArenasFieldNumber = 31;
- inline bool cc_enable_arenas() const;
- inline void set_cc_enable_arenas(bool value);
+ bool cc_enable_arenas() const;
+ void set_cc_enable_arenas(bool value);
+
+ // optional string objc_class_prefix = 36;
+ bool has_objc_class_prefix() const;
+ void clear_objc_class_prefix();
+ static const int kObjcClassPrefixFieldNumber = 36;
+ const ::std::string& objc_class_prefix() const;
+ void set_objc_class_prefix(const ::std::string& value);
+ void set_objc_class_prefix(const char* value);
+ void set_objc_class_prefix(const char* value, size_t size);
+ ::std::string* mutable_objc_class_prefix();
+ ::std::string* release_objc_class_prefix();
+ void set_allocated_objc_class_prefix(::std::string* objc_class_prefix);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
@@ -1864,6 +1876,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
inline void clear_has_deprecated();
inline void set_has_cc_enable_arenas();
inline void clear_has_cc_enable_arenas();
+ inline void set_has_objc_class_prefix();
+ inline void clear_has_objc_class_prefix();
::google::protobuf::internal::ExtensionSet _extensions_;
@@ -1878,6 +1892,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
bool cc_generic_services_;
int optimize_for_;
::google::protobuf::internal::ArenaStringPtr go_package_;
+ ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
bool java_generic_services_;
bool py_generic_services_;
@@ -1957,43 +1972,43 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool message_set_wire_format = 1 [default = false];
- inline bool has_message_set_wire_format() const;
- inline void clear_message_set_wire_format();
+ bool has_message_set_wire_format() const;
+ void clear_message_set_wire_format();
static const int kMessageSetWireFormatFieldNumber = 1;
- inline bool message_set_wire_format() const;
- inline void set_message_set_wire_format(bool value);
+ bool message_set_wire_format() const;
+ void set_message_set_wire_format(bool value);
// optional bool no_standard_descriptor_accessor = 2 [default = false];
- inline bool has_no_standard_descriptor_accessor() const;
- inline void clear_no_standard_descriptor_accessor();
+ bool has_no_standard_descriptor_accessor() const;
+ void clear_no_standard_descriptor_accessor();
static const int kNoStandardDescriptorAccessorFieldNumber = 2;
- inline bool no_standard_descriptor_accessor() const;
- inline void set_no_standard_descriptor_accessor(bool value);
+ bool no_standard_descriptor_accessor() const;
+ void set_no_standard_descriptor_accessor(bool value);
// optional bool deprecated = 3 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 3;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// optional bool map_entry = 7;
- inline bool has_map_entry() const;
- inline void clear_map_entry();
+ bool has_map_entry() const;
+ void clear_map_entry();
static const int kMapEntryFieldNumber = 7;
- inline bool map_entry() const;
- inline void set_map_entry(bool value);
+ bool map_entry() const;
+ void set_map_entry(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
@@ -2117,50 +2132,50 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
- inline bool has_ctype() const;
- inline void clear_ctype();
+ bool has_ctype() const;
+ void clear_ctype();
static const int kCtypeFieldNumber = 1;
- inline ::google::protobuf::FieldOptions_CType ctype() const;
- inline void set_ctype(::google::protobuf::FieldOptions_CType value);
+ ::google::protobuf::FieldOptions_CType ctype() const;
+ void set_ctype(::google::protobuf::FieldOptions_CType value);
// optional bool packed = 2;
- inline bool has_packed() const;
- inline void clear_packed();
+ bool has_packed() const;
+ void clear_packed();
static const int kPackedFieldNumber = 2;
- inline bool packed() const;
- inline void set_packed(bool value);
+ bool packed() const;
+ void set_packed(bool value);
// optional bool lazy = 5 [default = false];
- inline bool has_lazy() const;
- inline void clear_lazy();
+ bool has_lazy() const;
+ void clear_lazy();
static const int kLazyFieldNumber = 5;
- inline bool lazy() const;
- inline void set_lazy(bool value);
+ bool lazy() const;
+ void set_lazy(bool value);
// optional bool deprecated = 3 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 3;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// optional bool weak = 10 [default = false];
- inline bool has_weak() const;
- inline void clear_weak();
+ bool has_weak() const;
+ void clear_weak();
static const int kWeakFieldNumber = 10;
- inline bool weak() const;
- inline void set_weak(bool value);
+ bool weak() const;
+ void set_weak(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
@@ -2262,29 +2277,29 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool allow_alias = 2;
- inline bool has_allow_alias() const;
- inline void clear_allow_alias();
+ bool has_allow_alias() const;
+ void clear_allow_alias();
static const int kAllowAliasFieldNumber = 2;
- inline bool allow_alias() const;
- inline void set_allow_alias(bool value);
+ bool allow_alias() const;
+ void set_allow_alias(bool value);
// optional bool deprecated = 3 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 3;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
@@ -2377,22 +2392,22 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool deprecated = 1 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 1;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
@@ -2482,22 +2497,22 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool deprecated = 33 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 33;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
@@ -2587,22 +2602,22 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// optional bool deprecated = 33 [default = false];
- inline bool has_deprecated() const;
- inline void clear_deprecated();
+ bool has_deprecated() const;
+ void clear_deprecated();
static const int kDeprecatedFieldNumber = 33;
- inline bool deprecated() const;
- inline void set_deprecated(bool value);
+ bool deprecated() const;
+ void set_deprecated(bool value);
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
- inline int uninterpreted_option_size() const;
- inline void clear_uninterpreted_option();
+ int uninterpreted_option_size() const;
+ void clear_uninterpreted_option();
static const int kUninterpretedOptionFieldNumber = 999;
- inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
- inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
- inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+ ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+ ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
uninterpreted_option() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
@@ -2692,23 +2707,23 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu
// accessors -------------------------------------------------------
// required string name_part = 1;
- inline bool has_name_part() const;
- inline void clear_name_part();
+ bool has_name_part() const;
+ void clear_name_part();
static const int kNamePartFieldNumber = 1;
- inline const ::std::string& name_part() const;
- inline void set_name_part(const ::std::string& value);
- inline void set_name_part(const char* value);
- inline void set_name_part(const char* value, size_t size);
- inline ::std::string* mutable_name_part();
- inline ::std::string* release_name_part();
- inline void set_allocated_name_part(::std::string* name_part);
+ const ::std::string& name_part() const;
+ void set_name_part(const ::std::string& value);
+ void set_name_part(const char* value);
+ void set_name_part(const char* value, size_t size);
+ ::std::string* mutable_name_part();
+ ::std::string* release_name_part();
+ void set_allocated_name_part(::std::string* name_part);
// required bool is_extension = 2;
- inline bool has_is_extension() const;
- inline void clear_is_extension();
+ bool has_is_extension() const;
+ void clear_is_extension();
static const int kIsExtensionFieldNumber = 2;
- inline bool is_extension() const;
- inline void set_is_extension(bool value);
+ bool is_extension() const;
+ void set_is_extension(bool value);
// @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart)
private:
@@ -2801,73 +2816,73 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
// accessors -------------------------------------------------------
// repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
- inline int name_size() const;
- inline void clear_name();
+ int name_size() const;
+ void clear_name();
static const int kNameFieldNumber = 2;
- inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
- inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
- inline ::google::protobuf::UninterpretedOption_NamePart* add_name();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+ const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const;
+ ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index);
+ ::google::protobuf::UninterpretedOption_NamePart* add_name();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
name() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
mutable_name();
// optional string identifier_value = 3;
- inline bool has_identifier_value() const;
- inline void clear_identifier_value();
+ bool has_identifier_value() const;
+ void clear_identifier_value();
static const int kIdentifierValueFieldNumber = 3;
- inline const ::std::string& identifier_value() const;
- inline void set_identifier_value(const ::std::string& value);
- inline void set_identifier_value(const char* value);
- inline void set_identifier_value(const char* value, size_t size);
- inline ::std::string* mutable_identifier_value();
- inline ::std::string* release_identifier_value();
- inline void set_allocated_identifier_value(::std::string* identifier_value);
+ const ::std::string& identifier_value() const;
+ void set_identifier_value(const ::std::string& value);
+ void set_identifier_value(const char* value);
+ void set_identifier_value(const char* value, size_t size);
+ ::std::string* mutable_identifier_value();
+ ::std::string* release_identifier_value();
+ void set_allocated_identifier_value(::std::string* identifier_value);
// optional uint64 positive_int_value = 4;
- inline bool has_positive_int_value() const;
- inline void clear_positive_int_value();
+ bool has_positive_int_value() const;
+ void clear_positive_int_value();
static const int kPositiveIntValueFieldNumber = 4;
- inline ::google::protobuf::uint64 positive_int_value() const;
- inline void set_positive_int_value(::google::protobuf::uint64 value);
+ ::google::protobuf::uint64 positive_int_value() const;
+ void set_positive_int_value(::google::protobuf::uint64 value);
// optional int64 negative_int_value = 5;
- inline bool has_negative_int_value() const;
- inline void clear_negative_int_value();
+ bool has_negative_int_value() const;
+ void clear_negative_int_value();
static const int kNegativeIntValueFieldNumber = 5;
- inline ::google::protobuf::int64 negative_int_value() const;
- inline void set_negative_int_value(::google::protobuf::int64 value);
+ ::google::protobuf::int64 negative_int_value() const;
+ void set_negative_int_value(::google::protobuf::int64 value);
// optional double double_value = 6;
- inline bool has_double_value() const;
- inline void clear_double_value();
+ bool has_double_value() const;
+ void clear_double_value();
static const int kDoubleValueFieldNumber = 6;
- inline double double_value() const;
- inline void set_double_value(double value);
+ double double_value() const;
+ void set_double_value(double value);
// optional bytes string_value = 7;
- inline bool has_string_value() const;
- inline void clear_string_value();
+ bool has_string_value() const;
+ void clear_string_value();
static const int kStringValueFieldNumber = 7;
- inline const ::std::string& string_value() const;
- inline void set_string_value(const ::std::string& value);
- inline void set_string_value(const char* value);
- inline void set_string_value(const void* value, size_t size);
- inline ::std::string* mutable_string_value();
- inline ::std::string* release_string_value();
- inline void set_allocated_string_value(::std::string* string_value);
+ const ::std::string& string_value() const;
+ void set_string_value(const ::std::string& value);
+ void set_string_value(const char* value);
+ void set_string_value(const void* value, size_t size);
+ ::std::string* mutable_string_value();
+ ::std::string* release_string_value();
+ void set_allocated_string_value(::std::string* string_value);
// optional string aggregate_value = 8;
- inline bool has_aggregate_value() const;
- inline void clear_aggregate_value();
+ bool has_aggregate_value() const;
+ void clear_aggregate_value();
static const int kAggregateValueFieldNumber = 8;
- inline const ::std::string& aggregate_value() const;
- inline void set_aggregate_value(const ::std::string& value);
- inline void set_aggregate_value(const char* value);
- inline void set_aggregate_value(const char* value, size_t size);
- inline ::std::string* mutable_aggregate_value();
- inline ::std::string* release_aggregate_value();
- inline void set_allocated_aggregate_value(::std::string* aggregate_value);
+ const ::std::string& aggregate_value() const;
+ void set_aggregate_value(const ::std::string& value);
+ void set_aggregate_value(const char* value);
+ void set_aggregate_value(const char* value, size_t size);
+ ::std::string* mutable_aggregate_value();
+ ::std::string* release_aggregate_value();
+ void set_allocated_aggregate_value(::std::string* aggregate_value);
// @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption)
private:
@@ -2968,52 +2983,68 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
// accessors -------------------------------------------------------
// repeated int32 path = 1 [packed = true];
- inline int path_size() const;
- inline void clear_path();
+ int path_size() const;
+ void clear_path();
static const int kPathFieldNumber = 1;
- inline ::google::protobuf::int32 path(int index) const;
- inline void set_path(int index, ::google::protobuf::int32 value);
- inline void add_path(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 path(int index) const;
+ void set_path(int index, ::google::protobuf::int32 value);
+ void add_path(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
path() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_path();
// repeated int32 span = 2 [packed = true];
- inline int span_size() const;
- inline void clear_span();
+ int span_size() const;
+ void clear_span();
static const int kSpanFieldNumber = 2;
- inline ::google::protobuf::int32 span(int index) const;
- inline void set_span(int index, ::google::protobuf::int32 value);
- inline void add_span(::google::protobuf::int32 value);
- inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
+ ::google::protobuf::int32 span(int index) const;
+ void set_span(int index, ::google::protobuf::int32 value);
+ void add_span(::google::protobuf::int32 value);
+ const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >&
span() const;
- inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
+ ::google::protobuf::RepeatedField< ::google::protobuf::int32 >*
mutable_span();
// optional string leading_comments = 3;
- inline bool has_leading_comments() const;
- inline void clear_leading_comments();
+ bool has_leading_comments() const;
+ void clear_leading_comments();
static const int kLeadingCommentsFieldNumber = 3;
- inline const ::std::string& leading_comments() const;
- inline void set_leading_comments(const ::std::string& value);
- inline void set_leading_comments(const char* value);
- inline void set_leading_comments(const char* value, size_t size);
- inline ::std::string* mutable_leading_comments();
- inline ::std::string* release_leading_comments();
- inline void set_allocated_leading_comments(::std::string* leading_comments);
+ const ::std::string& leading_comments() const;
+ void set_leading_comments(const ::std::string& value);
+ void set_leading_comments(const char* value);
+ void set_leading_comments(const char* value, size_t size);
+ ::std::string* mutable_leading_comments();
+ ::std::string* release_leading_comments();
+ void set_allocated_leading_comments(::std::string* leading_comments);
// optional string trailing_comments = 4;
- inline bool has_trailing_comments() const;
- inline void clear_trailing_comments();
+ bool has_trailing_comments() const;
+ void clear_trailing_comments();
static const int kTrailingCommentsFieldNumber = 4;
- inline const ::std::string& trailing_comments() const;
- inline void set_trailing_comments(const ::std::string& value);
- inline void set_trailing_comments(const char* value);
- inline void set_trailing_comments(const char* value, size_t size);
- inline ::std::string* mutable_trailing_comments();
- inline ::std::string* release_trailing_comments();
- inline void set_allocated_trailing_comments(::std::string* trailing_comments);
+ const ::std::string& trailing_comments() const;
+ void set_trailing_comments(const ::std::string& value);
+ void set_trailing_comments(const char* value);
+ void set_trailing_comments(const char* value, size_t size);
+ ::std::string* mutable_trailing_comments();
+ ::std::string* release_trailing_comments();
+ void set_allocated_trailing_comments(::std::string* trailing_comments);
+
+ // repeated string leading_detached_comments = 6;
+ int leading_detached_comments_size() const;
+ void clear_leading_detached_comments();
+ static const int kLeadingDetachedCommentsFieldNumber = 6;
+ const ::std::string& leading_detached_comments(int index) const;
+ ::std::string* mutable_leading_detached_comments(int index);
+ void set_leading_detached_comments(int index, const ::std::string& value);
+ void set_leading_detached_comments(int index, const char* value);
+ void set_leading_detached_comments(int index, const char* value, size_t size);
+ ::std::string* add_leading_detached_comments();
+ void add_leading_detached_comments(const ::std::string& value);
+ void add_leading_detached_comments(const char* value);
+ void add_leading_detached_comments(const char* value, size_t size);
+ const ::google::protobuf::RepeatedPtrField< ::std::string>& leading_detached_comments() const;
+ ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_leading_detached_comments();
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location)
private:
@@ -3031,6 +3062,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me
mutable int _span_cached_byte_size_;
::google::protobuf::internal::ArenaStringPtr leading_comments_;
::google::protobuf::internal::ArenaStringPtr trailing_comments_;
+ ::google::protobuf::RepeatedPtrField< ::std::string> leading_detached_comments_;
friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
@@ -3107,15 +3139,15 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
// accessors -------------------------------------------------------
// repeated .google.protobuf.SourceCodeInfo.Location location = 1;
- inline int location_size() const;
- inline void clear_location();
+ int location_size() const;
+ void clear_location();
static const int kLocationFieldNumber = 1;
- inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
- inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
- inline ::google::protobuf::SourceCodeInfo_Location* add_location();
- inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+ const ::google::protobuf::SourceCodeInfo_Location& location(int index) const;
+ ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index);
+ ::google::protobuf::SourceCodeInfo_Location* add_location();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
location() const;
- inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
+ ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
mutable_location();
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
@@ -3137,6 +3169,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
// ===================================================================
+#if !PROTOBUF_INLINE_NOT_IN_HEADERS
// FileDescriptorSet
// repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -5416,6 +5449,59 @@ inline void FileOptions::set_cc_enable_arenas(bool value) {
// @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas)
}
+// optional string objc_class_prefix = 36;
+inline bool FileOptions::has_objc_class_prefix() const {
+ return (_has_bits_[0] & 0x00001000u) != 0;
+}
+inline void FileOptions::set_has_objc_class_prefix() {
+ _has_bits_[0] |= 0x00001000u;
+}
+inline void FileOptions::clear_has_objc_class_prefix() {
+ _has_bits_[0] &= ~0x00001000u;
+}
+inline void FileOptions::clear_objc_class_prefix() {
+ objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ clear_has_objc_class_prefix();
+}
+inline const ::std::string& FileOptions::objc_class_prefix() const {
+ // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_objc_class_prefix(const ::std::string& value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+ // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+ // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) {
+ set_has_objc_class_prefix();
+ objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ ::std::string(reinterpret_cast<const char*>(value), size));
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
+}
+inline ::std::string* FileOptions::mutable_objc_class_prefix() {
+ set_has_objc_class_prefix();
+ // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix)
+ return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_objc_class_prefix() {
+ clear_has_objc_class_prefix();
+ return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) {
+ if (objc_class_prefix != NULL) {
+ set_has_objc_class_prefix();
+ } else {
+ clear_has_objc_class_prefix();
+ }
+ objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix);
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix)
+}
+
// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
inline int FileOptions::uninterpreted_option_size() const {
return uninterpreted_option_.size();
@@ -6503,6 +6589,60 @@ inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::stri
// @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments)
}
+// repeated string leading_detached_comments = 6;
+inline int SourceCodeInfo_Location::leading_detached_comments_size() const {
+ return leading_detached_comments_.size();
+}
+inline void SourceCodeInfo_Location::clear_leading_detached_comments() {
+ leading_detached_comments_.Clear();
+}
+inline const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const {
+ // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Get(index);
+}
+inline ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) {
+ // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_.Mutable(index);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) {
+ // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ leading_detached_comments_.Mutable(index)->assign(value);
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) {
+ leading_detached_comments_.Mutable(index)->assign(value);
+ // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+ leading_detached_comments_.Mutable(index)->assign(
+ reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() {
+ return leading_detached_comments_.Add();
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
+ leading_detached_comments_.Add()->assign(value);
+ // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+ leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
+ // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+SourceCodeInfo_Location::leading_detached_comments() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return leading_detached_comments_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+SourceCodeInfo_Location::mutable_leading_detached_comments() {
+ // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
+ return &leading_detached_comments_;
+}
+
// -------------------------------------------------------------------
// SourceCodeInfo
@@ -6537,6 +6677,7 @@ SourceCodeInfo::mutable_location() {
return &location_;
}
+#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index e17c0cc8..367b16e5 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -172,9 +172,7 @@ message FieldDescriptorProto {
optional string default_value = 7;
// If set, gives the index of a oneof in the containing type's oneof_decl
- // list. This field is a member of that oneof. Extensions of a oneof should
- // not set this since the oneof to which they belong will be inferred based
- // on the extension range containing the extension's field number.
+ // list. This field is a member of that oneof.
optional int32 oneof_index = 9;
optional FieldOptions options = 8;
@@ -344,12 +342,15 @@ message FileOptions {
// least, this is a formalization for deprecating files.
optional bool deprecated = 23 [default=false];
-
// Enables the use of arenas for the proto messages in this file. This applies
// only to generated classes for C++.
optional bool cc_enable_arenas = 31 [default=false];
+ // Sets the objective c class prefix which is prepended to all objective c
+ // generated classes from this .proto. There is no default.
+ optional string objc_class_prefix = 36;
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
@@ -681,6 +682,11 @@ message SourceCodeInfo {
// A series of line comments appearing on consecutive lines, with no other
// tokens appearing on those lines, will be treated as a single comment.
//
+ // leading_detached_comments will keep paragraphs of comments that appear
+ // before (but not connected to) the current element. Each paragraph,
+ // separated by empty lines, will be one comment element in the repeated
+ // field.
+ //
// Only the comment content is provided; comment markers (e.g. //) are
// stripped out. For block comments, leading whitespace and an asterisk
// will be stripped from the beginning of each line other than the first.
@@ -701,6 +707,12 @@ message SourceCodeInfo {
// // Another line attached to qux.
// optional double qux = 4;
//
+ // // Detached comment for corge. This is not leading or trailing comments
+ // // to qux or corge because there are blank lines separating it from
+ // // both.
+ //
+ // // Detached comment for corge paragraph 2.
+ //
// optional string corge = 5;
// /* Block comment attached
// * to corge. Leading asterisks
@@ -708,7 +720,10 @@ message SourceCodeInfo {
// /* Block comment attached to
// * grault. */
// optional int32 grault = 6;
+ //
+ // // ignored detached comments.
optional string leading_comments = 3;
optional string trailing_comments = 4;
+ repeated string leading_detached_comments = 6;
}
}
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index d024eab1..2117c020 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -153,10 +153,10 @@ bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddExtension(
if (!field.extendee().empty() && field.extendee()[0] == '.') {
// The extension is fully-qualified. We can use it as a lookup key in
// the by_symbol_ table.
- if (!InsertIfNotPresent(&by_extension_,
- make_pair(field.extendee().substr(1),
- field.number()),
- value)) {
+ if (!InsertIfNotPresent(
+ &by_extension_,
+ std::make_pair(field.extendee().substr(1), field.number()),
+ value)) {
GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
"extend " << field.extendee() << " { "
<< field.name() << " = " << field.number() << " }";
@@ -189,17 +189,16 @@ template <typename Value>
Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
const string& containing_type,
int field_number) {
- return FindWithDefault(by_extension_,
- make_pair(containing_type, field_number),
- Value());
+ return FindWithDefault(
+ by_extension_, std::make_pair(containing_type, field_number), Value());
}
template <typename Value>
bool SimpleDescriptorDatabase::DescriptorIndex<Value>::FindAllExtensionNumbers(
const string& containing_type,
vector<int>* output) {
- typename map<pair<string, int>, Value >::const_iterator it =
- by_extension_.lower_bound(make_pair(containing_type, 0));
+ typename map<pair<string, int>, Value>::const_iterator it =
+ by_extension_.lower_bound(std::make_pair(containing_type, 0));
bool success = false;
for (; it != by_extension_.end() && it->first.first == containing_type;
@@ -310,7 +309,7 @@ bool EncodedDescriptorDatabase::Add(
const void* encoded_file_descriptor, int size) {
FileDescriptorProto file;
if (file.ParseFromArray(encoded_file_descriptor, size)) {
- return index_.AddFile(file, make_pair(encoded_file_descriptor, size));
+ return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size));
} else {
GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to "
"EncodedDescriptorDatabase::Add().";
@@ -525,15 +524,16 @@ bool MergedDescriptorDatabase::FindAllExtensionNumbers(
for (int i = 0; i < sources_.size(); i++) {
if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) {
- copy(results.begin(), results.end(),
- insert_iterator<set<int> >(merged_results, merged_results.begin()));
+ std::copy(
+ results.begin(), results.end(),
+ insert_iterator<set<int> >(merged_results, merged_results.begin()));
success = true;
}
results.clear();
}
- copy(merged_results.begin(), merged_results.end(),
- insert_iterator<vector<int> >(*output, output->end()));
+ std::copy(merged_results.begin(), merged_results.end(),
+ insert_iterator<vector<int> >(*output, output->end()));
return success;
}
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 6642d71b..1c03c443 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -408,7 +408,7 @@ TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) {
vector<int> numbers;
EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers));
ASSERT_EQ(2, numbers.size());
- sort(numbers.begin(), numbers.end());
+ std::sort(numbers.begin(), numbers.end());
EXPECT_EQ(5, numbers[0]);
EXPECT_EQ(32, numbers[1]);
}
@@ -722,7 +722,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
vector<int> numbers;
EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers));
ASSERT_EQ(2, numbers.size());
- sort(numbers.begin(), numbers.end());
+ std::sort(numbers.begin(), numbers.end());
EXPECT_EQ(12, numbers[0]);
EXPECT_EQ(13, numbers[1]);
}
@@ -731,7 +731,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) {
vector<int> numbers;
EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers));
ASSERT_EQ(2, numbers.size());
- sort(numbers.begin(), numbers.end());
+ std::sort(numbers.begin(), numbers.end());
EXPECT_EQ(12, numbers[0]);
EXPECT_EQ(13, numbers[1]);
}
diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py
deleted file mode 100644
index c5a8d8a2..00000000
--- a/src/google/protobuf/descriptor_pb2_test.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#! /usr/bin/python
-#
-# Protocol Buffers - Google's data interchange format
-# Copyright 2008 Google Inc. All rights reserved.
-# https://developers.google.com/protocol-buffers/
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date.
-
-from google3.pyglib import resources
-from google.apputils import basetest
-
-_DESC = 'google3/net/proto2/proto/descriptor_pb2.'
-_OLD = _DESC + 'py-prebuilt'
-_NEW = _DESC + 'compiled'
-
-
-class PregeneratedFileChanged(basetest.TestCase):
-
- def testSameText(self):
- generated = resources.GetResource(_NEW)
- checkedin = resources.GetResource(_OLD)
- self.assertMultiLineEqual(
- generated, checkedin, 'It seems that protoc _pb2 generator changed. '
- 'Please run google/protobuf/generate_descriptor_proto.sh to '
- 'regnerate a new version of %s and add it to your CL' % _OLD)
-
-if __name__ == '__main__':
- basetest.main()
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 2ceb41e5..fdce3d78 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -6104,9 +6104,9 @@ TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) {
file_desc->CopySourceCodeInfoTo(&file_desc_proto);
const SourceCodeInfo& info = file_desc_proto.source_code_info();
- ASSERT_EQ(3, info.location_size());
+ ASSERT_EQ(4, info.location_size());
// Get the Foo message location
- const SourceCodeInfo_Location& foo_location = info.location(1);
+ const SourceCodeInfo_Location& foo_location = info.location(2);
ASSERT_EQ(2, foo_location.path_size());
EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0));
EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
new file mode 100644
index 00000000..868c732f
--- /dev/null
+++ b/src/google/protobuf/duration.proto
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "DurationProto";
+option java_package = "com.google.protobuf";
+
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// Example 1: compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+message Duration {
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive.
+ int64 seconds = 1;
+
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // seconds field and a positive or negative nanos field. For durations
+ // of one second or more, a non-zero value for the nanos field must be
+ // of the same sign as the seconds field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ int32 nanos = 2;
+}
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index 49087131..03b38dd0 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -97,7 +97,7 @@ void Register(const MessageLite* containing_type,
int number, ExtensionInfo info) {
::google::protobuf::GoogleOnceInit(&registry_init_, &InitRegistry);
- if (!InsertIfNotPresent(registry_, make_pair(containing_type, number),
+ if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number),
info)) {
GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
<< containing_type->GetTypeName()
@@ -107,8 +107,9 @@ void Register(const MessageLite* containing_type,
const ExtensionInfo* FindRegisteredExtension(
const MessageLite* containing_type, int number) {
- return (registry_ == NULL) ? NULL :
- FindOrNull(*registry_, make_pair(containing_type, number));
+ return (registry_ == NULL)
+ ? NULL
+ : FindOrNull(*registry_, std::make_pair(containing_type, number));
}
} // namespace
@@ -1032,7 +1033,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other,
if (this_iter == extensions_.end()) {
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
- extensions_.insert(make_pair(number, other_iter->second));
+ extensions_.insert(std::make_pair(number, other_iter->second));
} else {
InternalExtensionMergeFrom(number, other_iter->second);
}
@@ -1042,7 +1043,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other,
if (other_iter == other->extensions_.end()) {
if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
- other->extensions_.insert(make_pair(number, this_iter->second));
+ other->extensions_.insert(std::make_pair(number, this_iter->second));
} else {
other->InternalExtensionMergeFrom(number, this_iter->second);
}
@@ -1175,6 +1176,9 @@ bool ExtensionSet::ParseFieldWithExtensionInfo(
extension.enum_validity_check.arg, value)) {
AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed,
value, extension.descriptor);
+ } else {
+ // Invalid value. Treat as unknown.
+ field_skipper->SkipUnknownEnum(number, value);
}
}
break;
@@ -1337,7 +1341,7 @@ bool ExtensionSet::MaybeNewExtension(int number,
const FieldDescriptor* descriptor,
Extension** result) {
pair<map<int, Extension>::iterator, bool> insert_result =
- extensions_.insert(make_pair(number, Extension()));
+ extensions_.insert(std::make_pair(number, Extension()));
*result = &insert_result.first->second;
(*result)->descriptor = descriptor;
return insert_result.second;
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 5f4ca1c3..796e7a5f 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -91,9 +91,10 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder {
const Descriptor* containing_type_;
};
-void ExtensionSet::AppendToList(const Descriptor* containing_type,
- const DescriptorPool* pool,
- vector<const FieldDescriptor*>* output) const {
+void ExtensionSet::AppendToList(
+ const Descriptor* containing_type,
+ const DescriptorPool* pool,
+ std::vector<const FieldDescriptor*>* output) const {
for (map<int, Extension>::const_iterator iter = extensions_.begin();
iter != extensions_.end(); ++iter) {
bool has = false;
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
new file mode 100644
index 00000000..492d4b06
--- /dev/null
+++ b/src/google/protobuf/field_mask.proto
@@ -0,0 +1,161 @@
+// 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 google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "FieldMaskProto";
+option java_package = "com.google.protobuf";
+
+
+// `FieldMask` represents a set of symbolic field paths, for example:
+//
+// paths: "f.a"
+// paths: "f.b.d"
+//
+// Here `f` represents a field in some root message, `a` and `b`
+// fields in the message found in `f`, and `d` a field found in the
+// message in `f.b`.
+//
+// Field masks are used to specify a subset of fields that should be
+// returned by a get operation or modified by an update operation.
+// Field masks also have a custom JSON encoding (see below).
+//
+// # Field Masks in Projections
+// When used in the context of a projection, a response message or
+// sub-message is filtered by the API to only contain those fields as
+// specified in the mask. For example, if the mask in the previous
+// example is applied to a response message as follows:
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// x : 2
+// }
+// y : 13
+// }
+// z: 8
+//
+// The result will not contain specific values for fields x,y and z
+// (there value will be set to the default, and omitted in proto text
+// output):
+//
+//
+// f {
+// a : 22
+// b {
+// d : 1
+// }
+// }
+//
+// A repeated field is not allowed except at the last position of a
+// field mask.
+//
+// If a FieldMask object is not present in a get operation, the
+// operation applies to all fields (as if a FieldMask of all fields
+// had been specified).
+//
+// Note that a field mask does not necessarily applies to the
+// top-level response message. In case of a REST get operation, the
+// field mask applies directly to the response, but in case of a REST
+// list operation, the mask instead applies to each individual message
+// in the returned resource list. In case of a REST custom method,
+// other definitions may be used. Where the mask applies will be
+// clearly documented together with its declaration in the API. In
+// any case, the effect on the returned resource/resources is required
+// behavior for APIs.
+//
+// # Field Masks in Update Operations
+// A field mask in update operations specifies which fields of the
+// targeted resource are going to be updated. The API is required
+// to only change the values of the fields as specified in the mask
+// and leave the others untouched. If a resource is passed in to
+// describe the updated values, the API ignores the values of all
+// fields not covered by the mask.
+//
+// In order to reset a field's value to the default, the field must
+// be in the mask and set to the default value in the provided resource.
+// Hence, in order to reset all fields of a resource, provide a default
+// instance of the resource and set all fields in the mask, or do
+// not provide a mask as described below.
+//
+// If a field mask is not present on update, the operation applies to
+// all fields (as if a field mask of all fields has been specified).
+// Note that in the presence of schema evolution, this may mean that
+// fields the client does not know and has therefore not filled into
+// the request will be reset to their default. If this is unwanted
+// behavior, a specific service may require a client to always specify
+// a field mask, producing an error if not.
+//
+// As with get operations, the location of the resource which
+// describes the updated values in the request message depends on the
+// operation kind. In any case, the effect of the field mask is
+// required to be honored by the API.
+//
+// ## Considerations for HTTP REST
+// The HTTP kind of an update operation which uses a field mask must
+// be set to PATCH instead of PUT in order to satisfy HTTP semantics
+// (PUT must only be used for full updates).
+//
+// # JSON Encoding of Field Masks
+// In JSON, a field mask is encoded as a single string where paths are
+// separated by a comma. Fields name in each path are converted
+// to/from lower-camel naming conventions.
+//
+// As an example, consider the following message declarations:
+//
+// message Profile {
+// User user = 1;
+// Photo photo = 2;
+// }
+// message User {
+// string display_name = 1;
+// string address = 2;
+// }
+//
+// In proto a field mask for `Profile` may look as such:
+//
+// mask {
+// paths: "user.display_name"
+// paths: "photo"
+// }
+//
+// In JSON, the same mask is represented as below:
+//
+// {
+// mask: "user.displayName,photo"
+// }
+//
+message FieldMask {
+ // The set of field mask paths.
+ repeated string paths = 1;
+}
diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h
index 3852cea5..fdcdc277 100644
--- a/src/google/protobuf/generated_enum_reflection.h
+++ b/src/google/protobuf/generated_enum_reflection.h
@@ -42,6 +42,7 @@
#include <string>
#include <google/protobuf/stubs/template_util.h>
+#include <google/protobuf/generated_enum_util.h>
namespace google {
namespace protobuf {
@@ -50,10 +51,6 @@ namespace protobuf {
namespace protobuf {
-// This type trait can be used to cause templates to only match proto2 enum
-// types.
-template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
-
// Returns the EnumDescriptor for enum type E, which must be a
// proto-declared enum type. Code generated by the protocol compiler
// will include specializations of this template for each enum type declared.
diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h
new file mode 100644
index 00000000..e4242055
--- /dev/null
+++ b/src/google/protobuf/generated_enum_util.h
@@ -0,0 +1,46 @@
+// 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_GENERATED_ENUM_UTIL_H__
+#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
+
+#include <google/protobuf/stubs/template_util.h>
+
+namespace google {
+namespace protobuf {
+
+// This type trait can be used to cause templates to only match proto2 enum
+// types.
+template <typename T> struct is_proto_enum : ::google::protobuf::internal::false_type {};
+
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index b500b9c5..412c48a1 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -247,8 +247,14 @@ namespace {
UnknownFieldSet* empty_unknown_field_set_ = NULL;
GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
+void DeleteEmptyUnknownFieldSet() {
+ delete empty_unknown_field_set_;
+ empty_unknown_field_set_ = NULL;
+}
+
void InitEmptyUnknownFieldSet() {
empty_unknown_field_set_ = new UnknownFieldSet;
+ internal::OnShutdown(&DeleteEmptyUnknownFieldSet);
}
const UnknownFieldSet& GetEmptyUnknownFieldSet() {
@@ -989,6 +995,7 @@ void GeneratedMessageReflection::ListFields(
// Optimization: The default instance never has any fields set.
if (&message == default_instance_) return;
+ output->reserve(descriptor_->field_count());
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
@@ -1012,7 +1019,7 @@ void GeneratedMessageReflection::ListFields(
}
// ListFields() must sort output by field number.
- sort(output->begin(), output->end(), FieldNumberSorter());
+ std::sort(output->begin(), output->end(), FieldNumberSorter());
}
// -------------------------------------------------------------------
@@ -1428,6 +1435,8 @@ const Message& GeneratedMessageReflection::GetMessage(
Message* GeneratedMessageReflection::MutableMessage(
Message* message, const FieldDescriptor* field,
MessageFactory* factory) const {
+ USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
+
if (factory == NULL) factory = message_factory_;
if (field->is_extension()) {
@@ -1966,26 +1975,28 @@ inline void GeneratedMessageReflection::ClearOneof(
uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
if (oneof_case > 0) {
const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_STRING: {
- switch (field->options().ctype()) {
- default: // TODO(kenton): Support other string reps.
- case FieldOptions::STRING: {
- const string* default_ptr =
- &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
- MutableField<ArenaStringPtr>(message, field)->
- Destroy(default_ptr, GetArena(message));
- break;
+ if (GetArena(message) == NULL) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_STRING: {
+ switch (field->options().ctype()) {
+ default: // TODO(kenton): Support other string reps.
+ case FieldOptions::STRING: {
+ const string* default_ptr =
+ &DefaultRaw<ArenaStringPtr>(field).Get(NULL);
+ MutableField<ArenaStringPtr>(message, field)->
+ Destroy(default_ptr, GetArena(message));
+ break;
+ }
}
+ break;
}
- break;
- }
- case FieldDescriptor::CPPTYPE_MESSAGE:
- delete *MutableRaw<Message*>(message, field);
- break;
- default:
- break;
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ delete *MutableRaw<Message*>(message, field);
+ break;
+ default:
+ break;
+ }
}
*MutableOneofCase(message, oneof_descriptor) = 0;
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index df88205c..93e1a22e 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -153,7 +153,7 @@ void CodedInputStream::PopLimit(Limit limit) {
std::pair<CodedInputStream::Limit, int>
CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
- return make_pair(PushLimit(byte_limit), --recursion_budget_);
+ return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
}
bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
@@ -613,8 +613,15 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
}
CodedOutputStream::~CodedOutputStream() {
+ Trim();
+}
+
+void CodedOutputStream::Trim() {
if (buffer_size_ > 0) {
output_->BackUp(buffer_size_);
+ total_bytes_ -= buffer_size_;
+ buffer_size_ = 0;
+ buffer_ = NULL;
}
}
@@ -662,12 +669,7 @@ void CodedOutputStream::WriteAliasedRaw(const void* data, int size) {
) {
WriteRaw(data, size);
} else {
- if (buffer_size_ > 0) {
- output_->BackUp(buffer_size_);
- total_bytes_ -= buffer_size_;
- buffer_ = NULL;
- buffer_size_ = 0;
- }
+ Trim();
total_bytes_ += size;
had_error_ |= !output_->WriteAliasedRaw(data, size);
@@ -704,61 +706,12 @@ void CodedOutputStream::WriteLittleEndian64(uint64 value) {
}
}
-inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline(
- uint32 value, uint8* target) {
- target[0] = static_cast<uint8>(value | 0x80);
- if (value >= (1 << 7)) {
- target[1] = static_cast<uint8>((value >> 7) | 0x80);
- if (value >= (1 << 14)) {
- target[2] = static_cast<uint8>((value >> 14) | 0x80);
- if (value >= (1 << 21)) {
- target[3] = static_cast<uint8>((value >> 21) | 0x80);
- if (value >= (1 << 28)) {
- target[4] = static_cast<uint8>(value >> 28);
- return target + 5;
- } else {
- target[3] &= 0x7F;
- return target + 4;
- }
- } else {
- target[2] &= 0x7F;
- return target + 3;
- }
- } else {
- target[1] &= 0x7F;
- return target + 2;
- }
- } else {
- target[0] &= 0x7F;
- return target + 1;
- }
-}
-
-void CodedOutputStream::WriteVarint32(uint32 value) {
- if (buffer_size_ >= kMaxVarint32Bytes) {
- // Fast path: We have enough bytes left in the buffer to guarantee that
- // this write won't cross the end, so we can skip the checks.
- uint8* target = buffer_;
- uint8* end = WriteVarint32FallbackToArrayInline(value, target);
- int size = end - target;
- Advance(size);
- } else {
- // Slow path: This write might cross the end of the buffer, so we
- // compose the bytes first then use WriteRaw().
- uint8 bytes[kMaxVarint32Bytes];
- int size = 0;
- while (value > 0x7F) {
- bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
- value >>= 7;
- }
- bytes[size++] = static_cast<uint8>(value) & 0x7F;
- WriteRaw(bytes, size);
- }
-}
-
-uint8* CodedOutputStream::WriteVarint32FallbackToArray(
- uint32 value, uint8* target) {
- return WriteVarint32FallbackToArrayInline(value, target);
+void CodedOutputStream::WriteVarint32SlowPath(uint32 value) {
+ uint8 bytes[kMaxVarint32Bytes];
+ uint8* target = &bytes[0];
+ uint8* end = WriteVarint32ToArray(value, target);
+ int size = end - target;
+ WriteRaw(bytes, size);
}
inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 978cc19d..dea4b650 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -647,6 +647,13 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// ZeroCopyOutputStream immediately after the last byte written.
~CodedOutputStream();
+ // Trims any unused space in the underlying buffer so that its size matches
+ // the number of bytes written by this stream. The underlying buffer will
+ // automatically be trimmed when this stream is destroyed; this call is only
+ // necessary if the underlying buffer is accessed *before* the stream is
+ // destroyed.
+ void Trim();
+
// Skips a number of bytes, leaving the bytes unmodified in the underlying
// buffer. Returns false if an underlying write error occurs. This is
// mainly useful with GetDirectBufferPointer().
@@ -789,7 +796,9 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// ZeroCopyOutputStream supports it.
void WriteAliasedRaw(const void* buffer, int size);
- static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target);
+ // If this write might cross the end of the buffer, we compose the bytes first
+ // then use WriteRaw().
+ void WriteVarint32SlowPath(uint32 value);
// Always-inlined versions of WriteVarint* functions so that code can be
// reused, while still controlling size. For instance, WriteVarint32ToArray()
@@ -798,8 +807,6 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// WriteVarint32FallbackToArray. Meanwhile, WriteVarint32() is already
// out-of-line, so it should just invoke this directly to avoid any extra
// function call overhead.
- static uint8* WriteVarint32FallbackToArrayInline(
- uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
static uint8* WriteVarint64ToArrayInline(
uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
@@ -919,7 +926,7 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
const uint32 kMax1ByteVarint = 0x7f;
uint32 tag = last_tag_ = buffer_[0];
Advance(1);
- return make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
+ return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
}
// Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available,
// and tag is two bytes. The latter is tested by bitwise-and-not of the
@@ -937,12 +944,12 @@ inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
// so we don't have to check for tag == 0. We may need to check whether
// it exceeds cutoff.
bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff;
- return make_pair(tag, at_or_below_cutoff);
+ return std::make_pair(tag, at_or_below_cutoff);
}
}
// Slow path
last_tag_ = ReadTagFallback();
- return make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
+ return std::make_pair(last_tag_, static_cast<uint32>(last_tag_ - 1) < cutoff);
}
inline bool CodedInputStream::LastTagWas(uint32 expected) {
@@ -1027,13 +1034,14 @@ inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) {
}
inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value,
- uint8* target) {
- if (value < 0x80) {
- *target = value;
- return target + 1;
- } else {
- return WriteVarint32FallbackToArray(value, target);
+ uint8* target) {
+ while (value >= 0x80) {
+ *target = static_cast<uint8>(value | 0x80);
+ value >>= 7;
+ ++target;
}
+ *target = static_cast<uint8>(value);
+ return target + 1;
}
inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) {
@@ -1086,22 +1094,26 @@ inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value,
return target + sizeof(value);
}
+inline void CodedOutputStream::WriteVarint32(uint32 value) {
+ if (buffer_size_ >= 5) {
+ // Fast path: We have enough bytes left in the buffer to guarantee that
+ // this write won't cross the end, so we can skip the checks.
+ uint8* target = buffer_;
+ uint8* end = WriteVarint32ToArray(value, target);
+ int size = end - target;
+ Advance(size);
+ } else {
+ WriteVarint32SlowPath(value);
+ }
+}
+
inline void CodedOutputStream::WriteTag(uint32 value) {
WriteVarint32(value);
}
inline uint8* CodedOutputStream::WriteTagToArray(
uint32 value, uint8* target) {
- if (value < (1 << 7)) {
- target[0] = value;
- return target + 1;
- } else if (value < (1 << 14)) {
- target[0] = static_cast<uint8>(value | 0x80);
- target[1] = static_cast<uint8>(value >> 7);
- return target + 2;
- } else {
- return WriteVarint32FallbackToArray(value, target);
- }
+ return WriteVarint32ToArray(value, target);
}
inline int CodedOutputStream::VarintSize32(uint32 value) {
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index bbe5e399..02d5bad3 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -502,11 +502,11 @@ struct Fixed64Case {
};
inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) {
- return os << "0x" << hex << c.value << dec;
+ return os << "0x" << std::hex << c.value << std::dec;
}
inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) {
- return os << "0x" << hex << c.value << dec;
+ return os << "0x" << std::hex << c.value << std::dec;
}
Fixed32Case kFixed32Cases[] = {
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index e6037863..c9f4ca7f 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -49,6 +49,7 @@ static const int kDefaultBufferSize = 65536;
GzipInputStream::GzipInputStream(
ZeroCopyInputStream* sub_stream, Format format, int buffer_size)
: format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) {
+ zcontext_.state = Z_NULL;
zcontext_.zalloc = Z_NULL;
zcontext_.zfree = Z_NULL;
zcontext_.opaque = Z_NULL;
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
index 3e25edfa..4360b18f 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -368,7 +368,7 @@ inline char* mutable_string_data(string* s) {
inline std::pair<char*, bool> as_string_data(string* s) {
char *p = mutable_string_data(s);
#ifdef LANG_CXX11
- return make_pair(p, true);
+ return std::make_pair(p, true);
#else
return make_pair(p, p != NULL);
#endif
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index a3705269..4ea21007 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -345,6 +345,6 @@ int main(int argc, char* argv[]) {
GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size());
}
- cout << "PASS" << endl;
+ std::cout << "PASS" << std::endl;
return 0;
}
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 6d8a9d03..e56af3fc 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -34,6 +34,8 @@
#include <iterator>
#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/generated_enum_util.h>
#include <google/protobuf/map_type_handler.h>
namespace google {
@@ -45,10 +47,12 @@ class Map;
template <typename Enum> struct is_proto_enum;
namespace internal {
-template <typename K, typename V, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-class MapField;
-} // namespace internal
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+class MapFieldLite;
+}
// This is the class for google::protobuf::Map's internal value_type. Instead of using
// std::pair as value_type, we use this class which provides us more control of
@@ -61,23 +65,24 @@ class MapPair {
MapPair(const Key& other_first, const T& other_second)
: first(other_first), second(other_second) {}
-
explicit MapPair(const Key& other_first) : first(other_first), second() {}
-
MapPair(const MapPair& other)
: first(other.first), second(other.second) {}
~MapPair() {}
- // Implicitly convertible to std::pair.
- operator std::pair<const Key, T>() const {
- return std::pair<const Key, T>(first, second);
+ // Implicitly convertible to std::pair of compatible types.
+ template <typename T1, typename T2>
+ operator std::pair<T1, T2>() const {
+ return std::pair<T1, T2>(first, second);
}
const Key first;
T second;
private:
+ typedef void DestructorSkippable_;
+ friend class ::google::protobuf::Arena;
friend class Map<Key, T>;
};
@@ -86,6 +91,7 @@ class MapPair {
// interface directly to visit or change map fields.
template <typename Key, typename T>
class Map {
+ typedef internal::MapCppTypeHandler<Key> KeyTypeHandler;
typedef internal::MapCppTypeHandler<T> ValueTypeHandler;
public:
@@ -100,20 +106,104 @@ class Map {
typedef size_t size_type;
typedef hash<Key> hasher;
-
- Map() : default_enum_value_(0) {}
-
- Map(const Map& other) {
+ typedef equal_to<Key> key_equal;
+
+ Map()
+ : arena_(NULL),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(0) {}
+ explicit Map(Arena* arena)
+ : arena_(arena),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(0) {}
+
+ Map(const Map& other)
+ : arena_(NULL),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(other.default_enum_value_) {
insert(other.begin(), other.end());
}
~Map() { clear(); }
+ private:
+ // re-implement std::allocator to use arena allocator for memory allocation.
+ // Used for google::protobuf::Map implementation. Users should not use this class
+ // directly.
+ template <typename U>
+ class MapAllocator {
+ public:
+ typedef U value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+
+ MapAllocator() : arena_(NULL) {}
+ explicit MapAllocator(Arena* arena) : arena_(arena) {}
+ template <typename X>
+ MapAllocator(const MapAllocator<X>& allocator)
+ : arena_(allocator.arena_) {}
+
+ pointer allocate(size_type n, const_pointer hint = 0) {
+ // If arena is not given, malloc needs to be called which doesn't
+ // construct element object.
+ if (arena_ == NULL) {
+ return reinterpret_cast<pointer>(malloc(n * sizeof(value_type)));
+ } else {
+ return reinterpret_cast<pointer>(
+ Arena::CreateArray<uint8>(arena_, n * sizeof(value_type)));
+ }
+ }
+
+ void deallocate(pointer p, size_type n) {
+ if (arena_ == NULL) {
+ free(p);
+ }
+ }
+
+ void construct(pointer p, const_reference t) { new (p) value_type(t); }
+
+ void destroy(pointer p) {
+ if (arena_ == NULL) p->~value_type();
+ }
+
+ template <typename X>
+ struct rebind {
+ typedef MapAllocator<X> other;
+ };
+
+ template <typename X>
+ bool operator==(const MapAllocator<X>& other) const {
+ return arena_ == other.arena_;
+ }
+
+ template <typename X>
+ bool operator!=(const MapAllocator<X>& other) const {
+ return arena_ != other.arena_;
+ }
+
+ private:
+ Arena* arena_;
+
+ template <typename X>
+ friend class MapAllocator;
+ };
+
+ public:
+ typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator;
+
// Iterators
- class const_iterator
+ class LIBPROTOBUF_EXPORT const_iterator
: public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
const value_type*, const value_type&> {
- typedef typename hash_map<Key, value_type*>::const_iterator InnerIt;
+ typedef typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+ Allocator>::const_iterator InnerIt;
public:
const_iterator() {}
@@ -139,8 +229,9 @@ class Map {
InnerIt it_;
};
- class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
- typedef typename hash_map<Key, value_type*>::iterator InnerIt;
+ class LIBPROTOBUF_EXPORT iterator : public std::iterator<std::forward_iterator_tag, value_type> {
+ typedef typename hash_map<Key, value_type*, hasher, equal_to<Key>,
+ Allocator>::iterator InnerIt;
public:
iterator() {}
@@ -185,7 +276,7 @@ class Map {
T& operator[](const key_type& key) {
value_type** value = &elements_[key];
if (*value == NULL) {
- *value = new value_type(key);
+ *value = CreateValueTypeInternal(key);
internal::MapValueInitializer<google::protobuf::is_proto_enum<T>::value,
T>::Initialize((*value)->second,
default_enum_value_);
@@ -241,7 +332,7 @@ class Map {
} else {
return std::pair<iterator, bool>(
iterator(elements_.insert(std::pair<Key, value_type*>(
- value.first, new value_type(value))).first), true);
+ value.first, CreateValueTypeInternal(value))).first), true);
}
}
template <class InputIt>
@@ -256,28 +347,29 @@ class Map {
// Erase
size_type erase(const key_type& key) {
- typename hash_map<Key, value_type*>::iterator it = elements_.find(key);
+ typename hash_map<Key, value_type*, hash<Key>, equal_to<Key>,
+ Allocator>::iterator it = elements_.find(key);
if (it == elements_.end()) {
return 0;
} else {
- delete it->second;
+ if (arena_ == NULL) delete it->second;
elements_.erase(it);
return 1;
}
}
void erase(iterator pos) {
- delete pos.it_->second;
+ if (arena_ == NULL) delete pos.it_->second;
elements_.erase(pos.it_);
}
void erase(iterator first, iterator last) {
for (iterator it = first; it != last;) {
- delete it.it_->second;
+ if (arena_ == NULL) delete it.it_->second;
elements_.erase((it++).it_);
}
}
void clear() {
for (iterator it = begin(); it != end(); ++it) {
- delete it.it_->second;
+ if (arena_ == NULL) delete it.it_->second;
}
elements_.clear();
}
@@ -297,12 +389,45 @@ class Map {
default_enum_value_ = default_enum_value;
}
- hash_map<Key, value_type*> elements_;
+ value_type* CreateValueTypeInternal(const Key& key) {
+ if (arena_ == NULL) {
+ return new value_type(key);
+ } else {
+ value_type* value = reinterpret_cast<value_type*>(
+ Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+ Arena::CreateInArenaStorage(const_cast<Key*>(&value->first), arena_);
+ Arena::CreateInArenaStorage(&value->second, arena_);
+ const_cast<Key&>(value->first) = key;
+ return value;
+ }
+ }
+
+ value_type* CreateValueTypeInternal(const value_type& value) {
+ if (arena_ == NULL) {
+ return new value_type(value);
+ } else {
+ value_type* p = reinterpret_cast<value_type*>(
+ Arena::CreateArray<uint8>(arena_, sizeof(value_type)));
+ Arena::CreateInArenaStorage(const_cast<Key*>(&p->first), arena_);
+ Arena::CreateInArenaStorage(&p->second, arena_);
+ const_cast<Key&>(p->first) = value.first;
+ p->second = value.second;
+ return p;
+ }
+ }
+
+ Arena* arena_;
+ Allocator allocator_;
+ hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator> elements_;
int default_enum_value_;
- template <typename K, typename V, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum>
- friend class internal::MapField;
+ friend class ::google::protobuf::Arena;
+ typedef void DestructorSkippable_;
+ template <typename K, typename V,
+ internal::WireFormatLite::FieldType key_wire_type,
+ internal::WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+ friend class LIBPROTOBUF_EXPORT internal::MapFieldLite;
};
} // namespace protobuf
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index 217b15f6..f78a4f40 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -31,13 +31,23 @@
#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
#define GOOGLE_PROTOBUF_MAP_ENTRY_H__
-#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/map_entry_lite.h>
#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
namespace protobuf {
class Arena;
+namespace internal {
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class MapField;
+}
}
namespace protobuf {
@@ -45,7 +55,8 @@ namespace internal {
// Register all MapEntry default instances so we can delete them in
// ShutdownProtobufLibrary().
-void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(MessageLite* default_instance);
+void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(
+ MessageLite* default_instance);
// This is the common base class for MapEntry. It is used by MapFieldBase in
// reflection api, in which the static type of key and value is unknown.
@@ -82,179 +93,103 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
// while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to
// get internal layout.
// Moreover, default_enum_value is used to initialize enum field in proto2.
-template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
- FieldDescriptor::Type ValueProtoType, int default_enum_value>
-class MapEntry : public MapEntryBase {
- // Handlers for key/value's proto field type. Used to infer internal layout
- // and provide parsing/serialization support.
- typedef MapProtoTypeHandler<KeyProtoType> KeyProtoHandler;
- typedef MapProtoTypeHandler<ValueProtoType> ValueProtoHandler;
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
+ // Handlers for key/value wire type. Provide utilities to parse/serialize
+ // key/value.
+ typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+ typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
// Define key/value's internal stored type. Message is the only one whose
// internal stored type cannot be inferred from its proto type.
- typedef typename KeyProtoHandler::CppType KeyProtoHandlerCppType;
- typedef typename ValueProtoHandler::CppType ValueProtoHandlerCppType;
- static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
- static const bool kIsValueMessage = ValueProtoHandler::kIsMessage;
- typedef typename MapIf<kIsKeyMessage, Key, KeyProtoHandlerCppType>::type
+ static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+ static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
+ typedef typename KeyWireHandler::CppType KeyInternalType;
+ typedef typename ValueWireHandler::CppType ValueInternalType;
+ typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
KeyCppType;
- typedef typename MapIf<kIsValueMessage, Value, ValueProtoHandlerCppType>::type
+ typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
ValCppType;
- // Handlers for key/value's internal stored type. Provide utilities to
- // manipulate internal stored type. We need it because some types are stored
- // as values and others are stored as pointers (Message and string), but we
- // need to keep the code in MapEntry unified instead of providing different
- // codes for each type.
- typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
- typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
-
- // Define internal memory layout. Strings and messages are stored as
- // pointers, while other types are stored as values.
- static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
- static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
- typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
- KeyBase;
- typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
- ValueBase;
-
// Abbreviation for MapEntry
typedef typename google::protobuf::internal::MapEntry<
- Key, Value, KeyProtoType, ValueProtoType, default_enum_value> EntryType;
-
- // Constants for field number.
- static const int kKeyFieldNumber = 1;
- static const int kValueFieldNumber = 2;
+ Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType;
- // Constants for field tag.
- static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kKeyFieldNumber, KeyProtoHandler::kWireType);
- static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kValueFieldNumber, ValueProtoHandler::kWireType);
- static const int kTagSize = 1;
+ // Abbreviation for MapEntryLite
+ typedef typename google::protobuf::internal::MapEntryLite<
+ Key, Value, kKeyFieldType, kValueFieldType, default_enum_value>
+ EntryLiteType;
public:
~MapEntry() {
if (this == default_instance_) {
delete reflection_;
- } else {
- KeyCppHandler::Delete(key_);
- ValueCppHandler::Delete(value_);
}
}
// accessors ======================================================
- inline void set_key(const KeyCppType& key) {
- KeyCppHandler::EnsureMutable(&key_);
- KeyCppHandler::Merge(key, &key_);
- set_has_key();
- }
virtual inline const KeyCppType& key() const {
- return KeyCppHandler::Reference(key_);
+ return entry_lite_.key();
}
inline KeyCppType* mutable_key() {
- set_has_key();
- KeyCppHandler::EnsureMutable(&key_);
- return KeyCppHandler::Pointer(key_);
- }
- inline void set_value(const ValCppType& value) {
- ValueCppHandler::EnsureMutable(&value_);
- ValueCppHandler::Merge(value, &value_);
- set_has_value();
+ return entry_lite_.mutable_key();
}
virtual inline const ValCppType& value() const {
- GOOGLE_CHECK(default_instance_ != NULL);
- return ValueCppHandler::DefaultIfNotInitialized(value_,
- default_instance_->value_);
+ return entry_lite_.value();
}
inline ValCppType* mutable_value() {
- set_has_value();
- ValueCppHandler::EnsureMutable(&value_);
- return ValueCppHandler::Pointer(value_);
+ return entry_lite_.mutable_value();
}
// implements Message =============================================
bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
- uint32 tag;
-
- for (;;) {
- // 1) corrupted data: return false;
- // 2) unknown field: skip without putting into unknown field set;
- // 3) unknown enum value: keep it in parsing. In proto2, caller should
- // check the value and put this entry into containing message's unknown
- // field set if the value is an unknown enum. In proto3, caller doesn't
- // need to care whether the value is unknown enum;
- // 4) missing key/value: missed key/value will have default value. caller
- // should take this entry as if key/value is set to default value.
- tag = input->ReadTag();
- switch (tag) {
- case kKeyTag:
- if (!KeyProtoHandler::Read(input, mutable_key())) return false;
- set_has_key();
- if (!input->ExpectTag(kValueTag)) break;
- GOOGLE_FALLTHROUGH_INTENDED;
-
- case kValueTag:
- if (!ValueProtoHandler::Read(input, mutable_value())) return false;
- set_has_value();
- if (input->ExpectAtEnd()) return true;
- break;
-
- default:
- if (tag == 0 ||
- WireFormatLite::GetTagWireType(tag) ==
- WireFormatLite::WIRETYPE_END_GROUP) {
- return true;
- }
- if (!WireFormatLite::SkipField(input, tag)) return false;
- break;
- }
- }
+ return entry_lite_.MergePartialFromCodedStream(input);
}
int ByteSize() const {
- int size = 0;
- size += has_key() ? kTagSize + KeyProtoHandler::ByteSize(key()) : 0;
- size += has_value() ? kTagSize + ValueProtoHandler::ByteSize(value()) : 0;
- return size;
+ return entry_lite_.ByteSize();
}
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
- KeyProtoHandler::Write(kKeyFieldNumber, key(), output);
- ValueProtoHandler::Write(kValueFieldNumber, value(), output);
+ entry_lite_.SerializeWithCachedSizes(output);
}
::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
- output = KeyProtoHandler::WriteToArray(kKeyFieldNumber, key(), output);
- output =
- ValueProtoHandler::WriteToArray(kValueFieldNumber, value(), output);
- return output;
+ return entry_lite_.SerializeWithCachedSizesToArray(output);
}
int GetCachedSize() const {
- int size = 0;
- size += has_key() ? kTagSize + KeyProtoHandler::GetCachedSize(key()) : 0;
- size +=
- has_value() ? kTagSize + ValueProtoHandler::GetCachedSize(value()) : 0;
- return size;
+ return entry_lite_.GetCachedSize();
}
- bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+ bool IsInitialized() const {
+ return entry_lite_.IsInitialized();
+ }
Message* New() const {
MapEntry* entry = new MapEntry;
entry->descriptor_ = descriptor_;
entry->reflection_ = reflection_;
- entry->default_instance_ = default_instance_;
+ entry->set_default_instance(default_instance_);
+ return entry;
+ }
+
+ Message* New(Arena* arena) const {
+ MapEntry* entry = Arena::CreateMessage<MapEntry>(arena);
+ entry->descriptor_ = descriptor_;
+ entry->reflection_ = reflection_;
+ entry->set_default_instance(default_instance_);
return entry;
}
int SpaceUsed() const {
int size = sizeof(MapEntry);
- size += KeyCppHandler::SpaceUsedInMapEntry(key_);
- size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+ size += entry_lite_.SpaceUsed();
return size;
}
@@ -279,30 +214,19 @@ class MapEntry : public MapEntryBase {
}
void MergeFrom(const MapEntry& from) {
- if (from._has_bits_[0]) {
- if (from.has_key()) {
- KeyCppHandler::EnsureMutable(&key_);
- KeyCppHandler::Merge(from.key(), &key_);
- set_has_key();
- }
- if (from.has_value()) {
- ValueCppHandler::EnsureMutable(&value_);
- ValueCppHandler::Merge(from.value(), &value_);
- set_has_value();
- }
- }
+ entry_lite_.MergeFrom(from.entry_lite_);
}
void Clear() {
- KeyCppHandler::Clear(&key_);
- ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
- clear_has_key();
- clear_has_value();
+ entry_lite_.Clear();
}
void InitAsDefaultInstance() {
- KeyCppHandler::AssignDefaultValue(&key_);
- ValueCppHandler::AssignDefaultValue(&value_);
+ entry_lite_.InitAsDefaultInstance();
+ }
+
+ Arena* GetArena() const {
+ return entry_lite_.GetArena();
}
// Create default MapEntry instance for given descriptor. Descriptor has to be
@@ -310,141 +234,58 @@ class MapEntry : public MapEntryBase {
// may have the same type and MapEntry class. The given descriptor is needed
// to distinguish instances of the same MapEntry class.
static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) {
- MapEntry* entry = new MapEntry();
+ MapEntry* entry = new MapEntry;
const Reflection* reflection = new GeneratedMessageReflection(
descriptor, entry, offsets_,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_),
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1,
DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1);
entry->descriptor_ = descriptor;
entry->reflection_ = reflection;
- entry->default_instance_ = entry;
+ entry->set_default_instance(entry);
entry->InitAsDefaultInstance();
RegisterMapEntryDefaultInstance(entry);
return entry;
}
- // Create a MapEntry for given key and value from google::protobuf::Map in
- // serialization. This function is only called when value is enum. Enum is
- // treated differently because its type in MapEntry is int and its type in
- // google::protobuf::Map is enum. We cannot create a reference to int from an enum.
- static MapEntry* EnumWrap(const Key& key, const Value value) {
- return new MapEnumEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
- default_enum_value>(key, value);
- }
+ private:
+ MapEntry() : default_instance_(NULL), entry_lite_() {}
- // Like above, but for all the other types. This avoids value copy to create
- // MapEntry from google::protobuf::Map in serialization.
- static MapEntry* Wrap(const Key& key, const Value& value) {
- return new MapEntryWrapper<Key, Value, KeyProtoType, ValueProtoType,
- default_enum_value>(key, value);
- }
+ explicit MapEntry(Arena* arena)
+ : default_instance_(NULL), entry_lite_(arena) {}
- protected:
- void set_has_key() { _has_bits_[0] |= 0x00000001u; }
- bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
- void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
- void set_has_value() { _has_bits_[0] |= 0x00000002u; }
- bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
- void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
+ inline Arena* GetArenaNoVirtual() const {
+ return entry_lite_.GetArenaNoVirtual();
+ }
- private:
- // Serializing a generated message containing map field involves serializing
- // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
- // after serialization should be the same as that of a MapEntry message
- // containing the same key and value inside it. However, google::protobuf::Map doesn't
- // store key and value as MapEntry message, which disables us to use existing
- // code to serialize message. In order to use existing code to serialize
- // message, we need to construct a MapEntry from key-value pair. But it
- // involves copy of key and value to construct a MapEntry. In order to avoid
- // this copy in constructing a MapEntry, we need the following class which
- // only takes references of given key and value.
- template <typename KeyNested, typename ValueNested,
- FieldDescriptor::Type KeyProtoNested,
- FieldDescriptor::Type ValueProtoNested, int default_enum>
- class MapEntryWrapper
- : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
- ValueProtoNested, default_enum> {
- typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
- default_enum_value> Base;
- typedef typename Base::KeyCppType KeyCppType;
- typedef typename Base::ValCppType ValCppType;
-
- public:
- MapEntryWrapper(const KeyNested& key, const ValueNested& value)
- : key_(key), value_(value) {
- Base::set_has_key();
- Base::set_has_value();
- }
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
-
- private:
- const Key& key_;
- const Value& value_;
- };
-
- // Like above, but for enum value only, which stores value instead of
- // reference of value field inside. This is needed because the type of value
- // field in constructor is an enum, while we need to store it as an int. If we
- // initialize a reference to int with a reference to enum, compiler will
- // generate a temporary int from enum and initialize the reference to int with
- // the temporary.
- template <typename KeyNested, typename ValueNested,
- FieldDescriptor::Type KeyProtoNested,
- FieldDescriptor::Type ValueProtoNested, int default_enum>
- class MapEnumEntryWrapper
- : public MapEntry<KeyNested, ValueNested, KeyProtoNested,
- ValueProtoNested, default_enum> {
- typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
- default_enum> Base;
- typedef typename Base::KeyCppType KeyCppType;
- typedef typename Base::ValCppType ValCppType;
-
- public:
- MapEnumEntryWrapper(const KeyNested& key, const ValueNested& value)
- : key_(key), value_(value) {
- Base::set_has_key();
- Base::set_has_value();
- }
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
-
- private:
- const KeyCppType& key_;
- const ValCppType value_;
- };
-
- MapEntry() : default_instance_(NULL) {
- KeyCppHandler::Initialize(&key_);
- ValueCppHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value);
- _has_bits_[0] = 0;
+ void set_default_instance(MapEntry* default_instance) {
+ default_instance_ = default_instance;
+ entry_lite_.set_default_instance(&default_instance->entry_lite_);
}
- KeyBase key_;
- ValueBase value_;
static int offsets_[2];
UnknownFieldSet _unknown_fields_;
- uint32 _has_bits_[1];
MapEntry* default_instance_;
+ EntryLiteType entry_lite_;
friend class ::google::protobuf::Arena;
- template <typename K, typename V,
- FieldDescriptor::Type KType,
- FieldDescriptor::Type VType, int default_enum>
- friend class internal::MapField;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+ WireFormatLite::FieldType, int default_enum>
+ friend class LIBPROTOBUF_EXPORT internal::MapField;
friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
};
-template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
- FieldDescriptor::Type ValueProtoType, int default_enum_value>
-int MapEntry<Key, Value, KeyProtoType, ValueProtoType,
+template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+int MapEntry<Key, Value, kKeyFieldType, kValueFieldType,
default_enum_value>::offsets_[2] = {
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_),
};
} // namespace internal
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
new file mode 100644
index 00000000..304fba88
--- /dev/null
+++ b/src/google/protobuf/map_entry_lite.h
@@ -0,0 +1,409 @@
+// 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_MAP_ENTRY_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
+
+#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+class Arena;
+namespace internal {
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class MapEntry;
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class MapFieldLite;
+} // namespace internal
+} // namespace protobuf
+
+namespace protobuf {
+namespace internal {
+
+// MapEntryLite is used to implement parsing and serialization of map for lite
+// runtime.
+template <typename Key, typename Value,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite {
+ // Handlers for key/value wire type. Provide utilities to parse/serialize
+ // key/value.
+ typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+ typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
+
+ // Define key/value's internal stored type. Message is the only one whose
+ // internal stored type cannot be inferred from its proto type
+ static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+ static const bool kIsValueMessage = ValueWireHandler::kIsMessage;
+ typedef typename KeyWireHandler::CppType KeyInternalType;
+ typedef typename ValueWireHandler::CppType ValueInternalType;
+ typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type
+ KeyCppType;
+ typedef typename MapIf<kIsValueMessage, Value, ValueInternalType>::type
+ ValCppType;
+
+ // Handlers for key/value's internal stored type. Provide utilities to
+ // manipulate internal stored type. We need it because some types are stored
+ // as values and others are stored as pointers (Message and string), but we
+ // need to keep the code in MapEntry unified instead of providing different
+ // codes for each type.
+ typedef MapCppTypeHandler<KeyCppType> KeyCppHandler;
+ typedef MapCppTypeHandler<ValCppType> ValueCppHandler;
+
+ // Define internal memory layout. Strings and messages are stored as
+ // pointers, while other types are stored as values.
+ static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage;
+ static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage;
+ typedef typename MapIf<kKeyIsStringOrMessage, KeyCppType*, KeyCppType>::type
+ KeyBase;
+ typedef typename MapIf<kValIsStringOrMessage, ValCppType*, ValCppType>::type
+ ValueBase;
+
+ // Constants for field number.
+ static const int kKeyFieldNumber = 1;
+ static const int kValueFieldNumber = 2;
+
+ // Constants for field tag.
+ static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+ kKeyFieldNumber, KeyWireHandler::kWireType);
+ static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
+ kValueFieldNumber, ValueWireHandler::kWireType);
+ static const int kTagSize = 1;
+
+ public:
+ ~MapEntryLite() {
+ if (this != default_instance_) {
+ KeyCppHandler::Delete(key_);
+ ValueCppHandler::Delete(value_);
+ }
+ }
+
+ // accessors ======================================================
+
+ virtual inline const KeyCppType& key() const {
+ return KeyCppHandler::Reference(key_);
+ }
+ inline KeyCppType* mutable_key() {
+ set_has_key();
+ KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ return KeyCppHandler::Pointer(key_);
+ }
+ virtual inline const ValCppType& value() const {
+ GOOGLE_CHECK(default_instance_ != NULL);
+ return ValueCppHandler::DefaultIfNotInitialized(value_,
+ default_instance_->value_);
+ }
+ inline ValCppType* mutable_value() {
+ set_has_value();
+ ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+ return ValueCppHandler::Pointer(value_);
+ }
+
+ // implements MessageLite =========================================
+
+ // MapEntryLite is for implementation only and this function isn't called
+ // anywhere. Just provide a fake implementation here for MessageLite.
+ string GetTypeName() const { return ""; }
+
+ void CheckTypeAndMergeFrom(const MessageLite& other) {
+ MergeFrom(*::google::protobuf::down_cast<const MapEntryLite*>(&other));
+ }
+
+ bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) {
+ uint32 tag;
+
+ for (;;) {
+ // 1) corrupted data: return false;
+ // 2) unknown field: skip without putting into unknown field set;
+ // 3) unknown enum value: keep it in parsing. In proto2, caller should
+ // check the value and put this entry into containing message's unknown
+ // field set if the value is an unknown enum. In proto3, caller doesn't
+ // need to care whether the value is unknown enum;
+ // 4) missing key/value: missed key/value will have default value. caller
+ // should take this entry as if key/value is set to default value.
+ tag = input->ReadTag();
+ switch (tag) {
+ case kKeyTag:
+ if (!KeyWireHandler::Read(input, mutable_key())) return false;
+ set_has_key();
+ if (!input->ExpectTag(kValueTag)) break;
+ GOOGLE_FALLTHROUGH_INTENDED;
+
+ case kValueTag:
+ if (!ValueWireHandler::Read(input, mutable_value())) return false;
+ set_has_value();
+ if (input->ExpectAtEnd()) return true;
+ break;
+
+ default:
+ if (tag == 0 ||
+ WireFormatLite::GetTagWireType(tag) ==
+ WireFormatLite::WIRETYPE_END_GROUP) {
+ return true;
+ }
+ if (!WireFormatLite::SkipField(input, tag)) return false;
+ break;
+ }
+ }
+ }
+
+ int ByteSize() const {
+ int size = 0;
+ size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0;
+ size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0;
+ return size;
+ }
+
+ void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
+ KeyWireHandler::Write(kKeyFieldNumber, key(), output);
+ ValueWireHandler::Write(kValueFieldNumber, value(), output);
+ }
+
+ ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {
+ output = KeyWireHandler::WriteToArray(kKeyFieldNumber, key(), output);
+ output =
+ ValueWireHandler::WriteToArray(kValueFieldNumber, value(), output);
+ return output;
+ }
+
+ int GetCachedSize() const {
+ int size = 0;
+ size += has_key() ? kTagSize + KeyWireHandler::GetCachedSize(key()) : 0;
+ size +=
+ has_value() ? kTagSize + ValueWireHandler::GetCachedSize(value()) : 0;
+ return size;
+ }
+
+ bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+
+ MessageLite* New() const {
+ MapEntryLite* entry = new MapEntryLite;
+ entry->default_instance_ = default_instance_;
+ return entry;
+ }
+
+ MessageLite* New(Arena* arena) const {
+ MapEntryLite* entry = Arena::CreateMessage<MapEntryLite>(arena);
+ entry->default_instance_ = default_instance_;
+ return entry;
+ }
+
+ int SpaceUsed() const {
+ int size = sizeof(MapEntryLite);
+ size += KeyCppHandler::SpaceUsedInMapEntry(key_);
+ size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+ return size;
+ }
+
+ void MergeFrom(const MapEntryLite& from) {
+ if (from._has_bits_[0]) {
+ if (from.has_key()) {
+ KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ KeyCppHandler::Merge(from.key(), &key_);
+ set_has_key();
+ }
+ if (from.has_value()) {
+ ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+ ValueCppHandler::Merge(from.value(), &value_);
+ set_has_value();
+ }
+ }
+ }
+
+ void Clear() {
+ KeyCppHandler::Clear(&key_);
+ ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
+ clear_has_key();
+ clear_has_value();
+ }
+
+ void InitAsDefaultInstance() {
+ KeyCppHandler::AssignDefaultValue(&key_);
+ ValueCppHandler::AssignDefaultValue(&value_);
+ }
+
+ Arena* GetArena() const {
+ return GetArenaNoVirtual();
+ }
+
+ // Create a MapEntryLite for given key and value from google::protobuf::Map in
+ // serialization. This function is only called when value is enum. Enum is
+ // treated differently because its type in MapEntry is int and its type in
+ // 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<
+ Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> >(
+ arena, key, value, arena);
+ }
+
+ // 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);
+ }
+
+ protected:
+ void set_has_key() { _has_bits_[0] |= 0x00000001u; }
+ bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; }
+ void clear_has_key() { _has_bits_[0] &= ~0x00000001u; }
+ void set_has_value() { _has_bits_[0] |= 0x00000002u; }
+ bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; }
+ void clear_has_value() { _has_bits_[0] &= ~0x00000002u; }
+
+ private:
+ // Serializing a generated message containing map field involves serializing
+ // key-value pairs from google::protobuf::Map. The wire format of each key-value pair
+ // after serialization should be the same as that of a MapEntry message
+ // containing the same key and value inside it. However, google::protobuf::Map doesn't
+ // store key and value as MapEntry message, which disables us to use existing
+ // code to serialize message. In order to use existing code to serialize
+ // message, we need to construct a MapEntry from key-value pair. But it
+ // involves copy of key and value to construct a MapEntry. In order to avoid
+ // this copy in constructing a MapEntry, we need the following class which
+ // only takes references of given key and value.
+ template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+ WireFormatLite::FieldType v_wire_type, int default_enum>
+ class LIBPROTOBUF_EXPORT MapEntryWrapper
+ : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+ typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+ typedef typename Base::KeyCppType KeyCppType;
+ typedef typename Base::ValCppType ValCppType;
+
+ public:
+ MapEntryWrapper(const K& key, const V& value, Arena* arena)
+ : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+ key_(key),
+ value_(value) {
+ Base::set_has_key();
+ Base::set_has_value();
+ }
+ inline const KeyCppType& key() const { return key_; }
+ inline const ValCppType& value() const { return value_; }
+
+ private:
+ const Key& key_;
+ const Value& value_;
+
+ friend class ::google::protobuf::Arena;
+ typedef void DestructorSkippable_;
+ };
+
+ // Like above, but for enum value only, which stores value instead of
+ // reference of value field inside. This is needed because the type of value
+ // field in constructor is an enum, while we need to store it as an int. If we
+ // initialize a reference to int with a reference to enum, compiler will
+ // generate a temporary int from enum and initialize the reference to int with
+ // the temporary.
+ template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
+ WireFormatLite::FieldType v_wire_type, int default_enum>
+ class LIBPROTOBUF_EXPORT MapEnumEntryWrapper
+ : public MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> {
+ typedef MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum> Base;
+ typedef typename Base::KeyCppType KeyCppType;
+ typedef typename Base::ValCppType ValCppType;
+
+ public:
+ MapEnumEntryWrapper(const K& key, const V& value, Arena* arena)
+ : MapEntryLite<K, V, k_wire_type, v_wire_type, default_enum>(arena),
+ key_(key),
+ value_(value) {
+ Base::set_has_key();
+ Base::set_has_value();
+ }
+ inline const KeyCppType& key() const { return key_; }
+ inline const ValCppType& value() const { return value_; }
+
+ private:
+ const KeyCppType& key_;
+ const ValCppType value_;
+
+ friend class ::google::protobuf::Arena;
+ typedef void DestructorSkippable_;
+ };
+
+ MapEntryLite() : default_instance_(NULL), arena_(NULL) {
+ KeyCppHandler::Initialize(&key_, NULL);
+ ValueCppHandler::InitializeMaybeByDefaultEnum(
+ &value_, default_enum_value, NULL);
+ _has_bits_[0] = 0;
+ }
+
+ explicit MapEntryLite(Arena* arena)
+ : default_instance_(NULL), arena_(arena) {
+ KeyCppHandler::Initialize(&key_, arena);
+ ValueCppHandler::InitializeMaybeByDefaultEnum(
+ &value_, default_enum_value, arena);
+ _has_bits_[0] = 0;
+ }
+
+ inline Arena* GetArenaNoVirtual() const {
+ return arena_;
+ }
+
+ void set_default_instance(MapEntryLite* default_instance) {
+ default_instance_ = default_instance;
+ }
+
+ MapEntryLite* default_instance_;
+
+ KeyBase key_;
+ ValueBase value_;
+ Arena* arena_;
+ uint32 _has_bits_[1];
+
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
+ template <typename K, typename V, WireFormatLite::FieldType,
+ WireFormatLite::FieldType, int>
+ friend class LIBPROTOBUF_EXPORT internal::MapEntry;
+ template <typename K, typename V, WireFormatLite::FieldType,
+ WireFormatLite::FieldType, int>
+ friend class LIBPROTOBUF_EXPORT internal::MapFieldLite;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
+};
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index b535ec28..fd40c0d8 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -55,14 +55,14 @@ void InitMapEntryDefaultInstances() {
}
void RegisterMapEntryDefaultInstance(MessageLite* default_instance) {
- GoogleOnceInit(&map_entry_default_instances_once_,
+ ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_,
&InitMapEntryDefaultInstances);
MutexLock lock(map_entry_default_instances_mutex_);
map_entry_default_instances_->push_back(default_instance);
}
MapFieldBase::~MapFieldBase() {
- if (repeated_field_ != NULL) delete repeated_field_;
+ if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_;
}
const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
@@ -118,7 +118,9 @@ void MapFieldBase::SyncRepeatedFieldWithMap() const {
}
void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
- if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField<Message>;
+ if (repeated_field_ == NULL) {
+ repeated_field_ = Arena::Create<RepeatedPtrField<Message> >(arena_, arena_);
+ }
}
void MapFieldBase::SyncMapWithRepeatedField() const {
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 8516d74e..6d8b6ec8 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -34,8 +34,10 @@
#include <google/protobuf/stubs/atomicops.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/map.h>
+#include <google/protobuf/arena.h>
#include <google/protobuf/map_entry.h>
+#include <google/protobuf/map_field_lite.h>
+#include <google/protobuf/map_type_handler.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/unknown_field_set.h>
@@ -56,7 +58,13 @@ class MapFieldAccessor;
class LIBPROTOBUF_EXPORT MapFieldBase {
public:
MapFieldBase()
- : base_map_(NULL),
+ : arena_(NULL),
+ repeated_field_(NULL),
+ entry_descriptor_(NULL),
+ assign_descriptor_callback_(NULL),
+ state_(STATE_MODIFIED_MAP) {}
+ explicit MapFieldBase(Arena* arena)
+ : arena_(arena),
repeated_field_(NULL),
entry_descriptor_(NULL),
assign_descriptor_callback_(NULL),
@@ -109,7 +117,7 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
CLEAN = 2, // data in map and repeated field are same
};
- mutable void* base_map_;
+ Arena* arena_;
mutable RepeatedPtrField<Message>* repeated_field_;
// MapEntry can only be created from MapField. To create MapEntry, MapField
// needs to know its descriptor, because MapEntry is not generated class which
@@ -134,41 +142,55 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
// This class provides accesss to map field using generated api. It is used for
// internal generated message implentation only. Users should never use this
// directly.
-template<typename Key, typename T,
- FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value = 0>
-class MapField : public MapFieldBase {
- // Handlers for key/value's proto field type.
- typedef MapProtoTypeHandler<KeyProto> KeyProtoHandler;
- typedef MapProtoTypeHandler<ValueProto> ValueProtoHandler;
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value = 0>
+class LIBPROTOBUF_EXPORT MapField : public MapFieldBase,
+ public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value> {
+ // Handlers for key/value wire type. Provide utilities to parse/serialize
+ // key/value.
+ typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
+ typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
// Define key/value's internal stored type.
- typedef typename KeyProtoHandler::CppType KeyHandlerCpp;
- typedef typename ValueProtoHandler::CppType ValHandlerCpp;
- static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage;
- static const bool kIsValMessage = ValueProtoHandler::kIsMessage;
- typedef typename MapIf<kIsKeyMessage, Key, KeyHandlerCpp>::type KeyCpp;
- typedef typename MapIf<kIsValMessage, T , ValHandlerCpp>::type ValCpp;
+ static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
+ static const bool kIsValMessage = ValueWireHandler::kIsMessage;
+ typedef typename KeyWireHandler::CppType KeyInternalType;
+ typedef typename ValueWireHandler::CppType ValueInternalType;
+ typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCpp;
+ typedef typename MapIf<kIsValMessage, T , ValueInternalType>::type ValCpp;
// Handlers for key/value's internal stored type.
typedef MapCppTypeHandler<KeyCpp> KeyHandler;
typedef MapCppTypeHandler<ValCpp> ValHandler;
// Define message type for internal repeated field.
- typedef MapEntry<Key, T, KeyProto, ValueProto, default_enum_value> EntryType;
+ typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
+ EntryType;
+ typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value> EntryLiteType;
+
+ // Define abbreviation for parent MapFieldLite
+ typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value> MapFieldLiteType;
// Enum needs to be handled differently from other types because it has
// different exposed type in google::protobuf::Map's api and repeated field's api. For
// details see the comment in the implementation of
// SyncMapWithRepeatedFieldNoLocki.
- static const bool kIsValueEnum = ValueProtoHandler::kIsEnum;
+ static const bool kIsValueEnum = ValueWireHandler::kIsEnum;
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
public:
MapField();
+ explicit MapField(Arena* arena);
// MapField doesn't own the default_entry, which means default_entry must
// outlive the lifetime of MapField.
MapField(const Message* default_entry);
+ // For tests only.
+ MapField(Arena* arena, const Message* default_entry);
~MapField();
// Accessors
@@ -178,29 +200,22 @@ class MapField : public MapFieldBase {
// Convenient methods for generated message implementation.
int size() const;
void Clear();
- void MergeFrom(const MapField& other);
- void Swap(MapField* other);
+ void MergeFrom(const MapFieldLiteType& other);
+ void Swap(MapFieldLiteType* other);
// Allocates metadata only if this MapField is part of a generated message.
void SetEntryDescriptor(const Descriptor** descriptor);
void SetAssignDescriptorCallback(void (*callback)());
- // Set default enum value only for proto2 map field whose value is enum type.
- void SetDefaultEnumValue();
-
- // Used in the implementation of parsing. Caller should take the ownership.
- EntryType* NewEntry() const;
- // Used in the implementation of serializing enum value type. Caller should
- // take the ownership.
- EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
- // Used in the implementation of serializing other value types. Caller should
- // take the ownership.
- EntryType* NewEntryWrapper(const Key& key, const T& t) const;
-
private:
+ typedef void DestructorSkippable_;
+
// MapField needs MapEntry's default instance to create new MapEntry.
void InitDefaultEntryOnce() const;
+ // Manually set default entry instance. For test only.
+ void SetDefaultEntryOnce(const EntryType* default_entry) const;
+
// Convenient methods to get internal google::protobuf::Map
const Map<Key, T>& GetInternalMap() const;
Map<Key, T>* MutableInternalMap();
@@ -211,14 +226,9 @@ class MapField : public MapFieldBase {
int SpaceUsedExcludingSelfNoLock() const;
mutable const EntryType* default_entry_;
-};
-// True if IsInitialized() is true for value field in all elements of t. T is
-// expected to be message. It's useful to have this helper here to keep the
-// protobuf compiler from ever having to emit loops in IsInitialized() methods.
-// We want the C++ compiler to inline this or not as it sees fit.
-template <typename Key, typename T>
-bool AllAreInitialized(const Map<Key, T>& t);
+ friend class ::google::protobuf::Arena;
+};
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 79302e48..ae63c721 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -43,160 +43,183 @@ namespace google {
namespace protobuf {
namespace internal {
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField()
- : default_entry_(NULL) {
- MapFieldBase::base_map_ = new Map<Key, T>;
- SetDefaultEnumValue();
-}
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField()
+ : default_entry_(NULL) {}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+ Arena* arena)
+ : MapFieldBase(arena),
+ MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+ arena),
+ default_entry_(NULL) {}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MapField(
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
const Message* default_entry)
- : default_entry_(down_cast<const EntryType*>(default_entry)) {
- MapFieldBase::base_map_ = new Map<Key, T>;
- SetDefaultEnumValue();
-}
+ : default_entry_(down_cast<const EntryType*>(default_entry)) {}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::~MapField() {
- delete reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
-}
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
+ Arena* arena, const Message* default_entry)
+ : MapFieldBase(arena),
+ MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
+ arena),
+ default_entry_(down_cast<const EntryType*>(default_entry)) {}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-int MapField<Key, T, KeyProto, ValueProto, default_enum_value>::size() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::~MapField() {}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::size() const {
SyncMapWithRepeatedField();
- return GetInternalMap().size();
+ return MapFieldLiteType::GetInternalMap().size();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Clear() {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::Clear() {
SyncMapWithRepeatedField();
- MutableInternalMap()->clear();
+ MapFieldLiteType::MutableInternalMap()->clear();
SetMapDirty();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
const Map<Key, T>&
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::GetMap() const {
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::GetMap() const {
SyncMapWithRepeatedField();
- return GetInternalMap();
+ return MapFieldLiteType::GetInternalMap();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
Map<Key, T>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MutableMap() {
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::MutableMap() {
SyncMapWithRepeatedField();
- Map<Key, T>* result = MutableInternalMap();
+ Map<Key, T>* result = MapFieldLiteType::MutableInternalMap();
SetMapDirty();
return result;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::MergeFrom(
- const MapField& other) {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::MergeFrom(
+ const MapFieldLiteType& other) {
+ const MapField& down_other = down_cast<const MapField&>(other);
SyncMapWithRepeatedField();
- other.SyncMapWithRepeatedField();
-
- Map<Key, T>* map = MutableInternalMap();
- const Map<Key, T>& other_map = other.GetInternalMap();
- for (typename Map<Key, T>::const_iterator it = other_map.begin();
- it != other_map.end(); ++it) {
- (*map)[it->first] = it->second;
- }
+ down_other.SyncMapWithRepeatedField();
+ MapFieldLiteType::MergeFrom(other);
SetMapDirty();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto, default_enum_value>::Swap(
- MapField* other) {
- std::swap(repeated_field_, other->repeated_field_);
- std::swap(base_map_, other->base_map_);
- std::swap(state_, other->state_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::Swap(
+ MapFieldLiteType* other) {
+ MapField* down_other = down_cast<MapField*>(other);
+ std::swap(repeated_field_, down_other->repeated_field_);
+ MapFieldLiteType::Swap(other);
+ std::swap(state_, down_other->state_);
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
void
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::SetEntryDescriptor(
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SetEntryDescriptor(
const Descriptor** descriptor) {
entry_descriptor_ = descriptor;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
void
-MapField<Key, T, KeyProto, ValueProto,
+MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
assign_descriptor_callback_ = callback;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SetDefaultEnumValue() {
- MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntry() const {
- // The MapEntry instance created here is only used in generated code for
- // parsing. It doesn't have default instance, descriptor or reflection,
- // because these are not needed in parsing and will prevent us from using it
- // for parsing MessageLite.
- return new EntryType();
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEntryWrapper(
- const Key& key, const T& t) const {
- return EntryType::Wrap(key, t);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-MapEntry<Key, T, KeyProto, ValueProto, default_enum_value>*
-MapField<Key, T, KeyProto, ValueProto, default_enum_value>::NewEnumEntryWrapper(
- const Key& key, const T t) const {
- return EntryType::EnumWrap(key, t);
-}
-
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-const Map<Key, T>& MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::GetInternalMap() const {
- return *reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+const Map<Key, T>&
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::GetInternalMap() const {
+ return MapFieldLiteType::GetInternalMap();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-Map<Key, T>* MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::MutableInternalMap() {
- return reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+Map<Key, T>*
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::MutableInternalMap() {
+ return MapFieldLiteType::MutableInternalMap();
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
if (repeated_field_ == NULL) {
- repeated_field_ = new RepeatedPtrField<Message>();
+ if (arena_ == NULL) {
+ repeated_field_ = new RepeatedPtrField<Message>();
+ } else {
+ repeated_field_ =
+ Arena::Create<RepeatedPtrField<Message> >(arena_, arena_);
+ }
}
- const Map<Key, T>& map =
- *static_cast<const Map<Key, T>*>(MapFieldBase::base_map_);
+ const Map<Key, T>& map = GetInternalMap();
RepeatedPtrField<EntryType>* repeated_field =
reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
@@ -206,18 +229,21 @@ void MapField<Key, T, KeyProto, ValueProto,
it != map.end(); ++it) {
InitDefaultEntryOnce();
GOOGLE_CHECK(default_entry_ != NULL);
- EntryType* new_entry = down_cast<EntryType*>(default_entry_->New());
+ EntryType* new_entry = down_cast<EntryType*>(default_entry_->New(arena_));
repeated_field->AddAllocated(new_entry);
- new_entry->set_key(it->first);
- new_entry->set_value(it->second);
+ (*new_entry->mutable_key()) = it->first;
+ (*new_entry->mutable_value()) = it->second;
}
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
- Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SyncMapWithRepeatedFieldNoLock() const {
+ Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
RepeatedPtrField<EntryType>* repeated_field =
reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
map->clear();
@@ -232,15 +258,18 @@ void MapField<Key, T, KeyProto, ValueProto,
}
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-int MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+int
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
int size = 0;
if (repeated_field_ != NULL) {
size += repeated_field_->SpaceUsedExcludingSelf();
}
- Map<Key, T>* map = reinterpret_cast<Map<Key, T>*>(MapFieldBase::base_map_);
+ Map<Key, T>* map = const_cast<MapField*>(this)->MutableInternalMap();
size += sizeof(*map);
for (typename Map<Key, T>::iterator it = map->begin();
it != map->end(); ++it) {
@@ -250,10 +279,14 @@ int MapField<Key, T, KeyProto, ValueProto,
return size;
}
-template <typename Key, typename T, FieldDescriptor::Type KeyProto,
- FieldDescriptor::Type ValueProto, int default_enum_value>
-void MapField<Key, T, KeyProto, ValueProto,
- default_enum_value>::InitDefaultEntryOnce() const {
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void
+MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::InitDefaultEntryOnce()
+ const {
if (default_entry_ == NULL) {
InitMetadataOnce();
GOOGLE_CHECK(*entry_descriptor_ != NULL);
@@ -262,15 +295,6 @@ void MapField<Key, T, KeyProto, ValueProto,
}
}
-template <typename Key, typename T>
-bool AllAreInitialized(const Map<Key, T>& t) {
- for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
- ++it) {
- if (!it->second.IsInitialized()) return false;
- }
- return true;
-}
-
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
new file mode 100644
index 00000000..549ecc08
--- /dev/null
+++ b/src/google/protobuf/map_field_lite.h
@@ -0,0 +1,278 @@
+// 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_MAP_FIELD_LITE_H__
+#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
+
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_entry_lite.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// This class provides accesss to map field using generated api. It is used for
+// internal generated message implentation only. Users should never use this
+// directly.
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value = 0>
+class LIBPROTOBUF_EXPORT MapFieldLite {
+ // Define message type for internal repeated field.
+ typedef MapEntryLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value> EntryType;
+
+ public:
+ MapFieldLite();
+ explicit MapFieldLite(Arena* arena);
+ virtual ~MapFieldLite();
+
+ // Accessors
+ virtual const Map<Key, T>& GetMap() const;
+ virtual Map<Key, T>* MutableMap();
+
+ // Convenient methods for generated message implementation.
+ virtual int size() const;
+ virtual void Clear();
+ virtual void MergeFrom(const MapFieldLite& other);
+ virtual void Swap(MapFieldLite* other);
+
+ // Set default enum value only for proto2 map field whose value is enum type.
+ void SetDefaultEnumValue();
+
+ // Used in the implementation of parsing. Caller should take the ownership.
+ EntryType* NewEntry() const;
+ // Used in the implementation of serializing enum value type. Caller should
+ // take the ownership.
+ EntryType* NewEnumEntryWrapper(const Key& key, const T t) const;
+ // Used in the implementation of serializing other value types. Caller should
+ // take the ownership.
+ EntryType* NewEntryWrapper(const Key& key, const T& t) const;
+
+ protected:
+ // Convenient methods to get internal google::protobuf::Map
+ virtual const Map<Key, T>& GetInternalMap() const;
+ virtual Map<Key, T>* MutableInternalMap();
+
+ private:
+ typedef void DestructorSkippable_;
+
+ Arena* arena_;
+ Map<Key, T>* map_;
+
+ friend class ::google::protobuf::Arena;
+};
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MapFieldLite()
+ : arena_(NULL) {
+ map_ = new Map<Key, T>;
+ SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+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);
+ SetDefaultEnumValue();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::~MapFieldLite() {
+ delete map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::GetMap() const {
+ return *map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MutableMap() {
+ return map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+int
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::size() const {
+ return map_->size();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::Clear() {
+ map_->clear();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MergeFrom(
+ const MapFieldLite& other) {
+ for (typename Map<Key, T>::const_iterator it = other.map_->begin();
+ it != other.map_->end(); ++it) {
+ (*map_)[it->first] = it->second;
+ }
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::Swap(
+ MapFieldLite* other) {
+ std::swap(map_, other->map_);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+void
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::SetDefaultEnumValue() {
+ MutableInternalMap()->SetDefaultEnumValue(default_enum_value);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+const Map<Key, T>&
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::GetInternalMap() const {
+ return *map_;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+Map<Key, T>*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::MutableInternalMap() {
+ return map_;
+}
+
+#define EntryType \
+ MapEntryLite<Key, T, key_wire_type, value_wire_type, default_enum_value>
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::NewEntry() const {
+ if (arena_ == NULL) {
+ return new EntryType();
+ } else {
+ return Arena::CreateMessage<EntryType>(arena_);
+ }
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::NewEnumEntryWrapper(const Key& key,
+ const T t) const {
+ return EntryType::EnumWrap(key, t, arena_);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+EntryType*
+MapFieldLite<Key, T, key_wire_type, value_wire_type,
+ default_enum_value>::NewEntryWrapper(const Key& key,
+ const T& t) const {
+ return EntryType::Wrap(key, t, arena_);
+}
+
+#undef EntryType
+
+// True if IsInitialized() is true for value field in all elements of t. T is
+// expected to be message. It's useful to have this helper here to keep the
+// protobuf compiler from ever having to emit loops in IsInitialized() methods.
+// We want the C++ compiler to inline this or not as it sees fit.
+template <typename Key, typename T>
+bool AllAreInitialized(const Map<Key, T>& t) {
+ for (typename Map<Key, T>::const_iterator it = t.begin(); it != t.end();
+ ++it) {
+ if (!it->second.IsInitialized()) return false;
+ }
+ return true;
+}
+
+} // namespace internal
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 045f8f2c..61344cbb 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -35,13 +35,16 @@
#endif
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/arena.h>
#include <google/protobuf/map.h>
+#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/map_unittest.pb.h>
#include <google/protobuf/map_test_util.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/map_field_inl.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite_inl.h>
#include <gtest/gtest.h>
namespace google {
@@ -53,6 +56,9 @@ using unittest::TestAllTypes;
class MapFieldBaseStub : public MapFieldBase {
public:
+ typedef void DestructorSkippable_;
+ MapFieldBaseStub() {}
+ explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
void SyncRepeatedFieldWithMap() const {
MapFieldBase::SyncRepeatedFieldWithMap();
}
@@ -63,16 +69,6 @@ class MapFieldBaseStub : public MapFieldBase {
RepeatedPtrField<Message>* InternalRepeatedField() {
return repeated_field_;
}
- // Get underlined map without synchronizing repeated field.
- template <typename MapType>
- const MapType& GetMap() {
- return *reinterpret_cast<MapType*>(base_map_);
- }
- // Get underlined map without synchronizing repeated field.
- template <typename MapType>
- MapType* MutableMap() {
- return reinterpret_cast<MapType*>(base_map_);
- }
bool IsMapClean() { return state_ != 0; }
bool IsRepeatedClean() { return state_ != 1; }
void SetMapDirty() { state_ = 0; }
@@ -81,8 +77,8 @@ class MapFieldBaseStub : public MapFieldBase {
class MapFieldBasePrimitiveTest : public ::testing::Test {
protected:
- typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
- FieldDescriptor::TYPE_INT32> MapFieldType;
+ typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+ WireFormatLite::TYPE_INT32, false> MapFieldType;
MapFieldBasePrimitiveTest() {
// Get descriptors
@@ -144,6 +140,38 @@ TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) {
}
}
+TEST_F(MapFieldBasePrimitiveTest, Arena) {
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ ArenaOptions options;
+ options.initial_block = arena_block.data();
+ options.initial_block_size = arena_block.size();
+ Arena arena(options);
+
+ {
+ NoHeapChecker no_heap;
+
+ MapFieldType* map_field =
+ Arena::Create<MapFieldType>(&arena, &arena, default_entry_);
+
+ // Set content in map
+ (*map_field->MutableMap())[100] = 101;
+
+ // Trigger conversion to repeated field.
+ map_field->GetRepeatedField();
+ }
+
+ {
+ NoHeapChecker no_heap;
+
+ MapFieldBaseStub* map_field =
+ Arena::Create<MapFieldBaseStub>(&arena, &arena);
+
+ // Trigger conversion to repeated field.
+ EXPECT_TRUE(map_field->MutableRepeatedField() != NULL);
+ }
+}
+
namespace {
enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY };
} // anonymous namespace
@@ -152,8 +180,10 @@ class MapFieldStateTest
: public testing::TestWithParam<State> {
public:
protected:
- typedef MapField<int32, int32, FieldDescriptor::TYPE_INT32,
- FieldDescriptor::TYPE_INT32> MapFieldType;
+ typedef MapField<int32, int32, WireFormatLite::TYPE_INT32,
+ WireFormatLite::TYPE_INT32, false> MapFieldType;
+ typedef MapFieldLite<int32, int32, WireFormatLite::TYPE_INT32,
+ WireFormatLite::TYPE_INT32, false> MapFieldLiteType;
MapFieldStateTest() : state_(GetParam()) {
// Build map field
const Descriptor* map_descriptor =
@@ -199,9 +229,8 @@ class MapFieldStateTest
MakeMapDirty(map_field);
MapFieldBase* map_field_base = map_field;
map_field_base->MutableRepeatedField();
- MapFieldBaseStub* stub =
- reinterpret_cast<MapFieldBaseStub*>(map_field_base);
- Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+ Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+ ->MapFieldLiteType::MutableMap();
map->clear();
Expect(map_field, REPEATED_DIRTY, 0, 1, false);
@@ -213,7 +242,8 @@ class MapFieldStateTest
MapFieldBaseStub* stub =
reinterpret_cast<MapFieldBaseStub*>(map_field_base);
- Map<int32, int32>* map = stub->MutableMap<Map<int32, int32> >();
+ Map<int32, int32>* map = implicit_cast<MapFieldLiteType*>(map_field)
+ ->MapFieldLiteType::MutableMap();
RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
switch (state) {
@@ -430,6 +460,7 @@ TEST_P(MapFieldStateTest, MutableMapField) {
}
}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc
new file mode 100644
index 00000000..b65b4d63
--- /dev/null
+++ b/src/google/protobuf/map_lite_test_util.cc
@@ -0,0 +1,93 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/map_lite_test_util.h>
+#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/map_test_util_impl.h>
+
+namespace google {
+namespace protobuf {
+
+void MapLiteTestUtil::SetMapFields(unittest::TestMapLite* message) {
+ MapTestUtilImpl::SetMapFields<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetArenaMapFields(unittest::TestArenaMapLite* message) {
+ MapTestUtilImpl::SetArenaMapFields<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::SetMapFieldsInitialized(unittest::TestMapLite* message) {
+ MapTestUtilImpl::SetMapFieldsInitialized(message);
+}
+
+void MapLiteTestUtil::ModifyMapFields(unittest::TestMapLite* message) {
+ MapTestUtilImpl::ModifyMapFields<unittest::MapEnumLite,
+ unittest::MAP_ENUM_FOO_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectClear(const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectClear(message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSet(const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(message);
+}
+
+void MapLiteTestUtil::ExpectArenaMapFieldsSet(
+ const unittest::TestArenaMapLite& message) {
+ MapTestUtilImpl::ExpectArenaMapFieldsSet<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_BAZ_LITE>(
+ message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsSetInitialized(
+ const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnumLite,
+ unittest::MAP_ENUM_FOO_LITE>(
+ message);
+}
+
+void MapLiteTestUtil::ExpectMapFieldsModified(
+ const unittest::TestMapLite& message) {
+ MapTestUtilImpl::ExpectMapFieldsModified<unittest::MapEnumLite,
+ unittest::MAP_ENUM_BAR_LITE,
+ unittest::MAP_ENUM_FOO_LITE>(
+ message);
+}
+
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h
new file mode 100644
index 00000000..77b5336f
--- /dev/null
+++ b/src/google/protobuf/map_lite_test_util.h
@@ -0,0 +1,80 @@
+// 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_MAP_LITE_TEST_UTIL_H__
+#define GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
+
+#include <google/protobuf/map_lite_unittest.pb.h>
+
+namespace google {
+namespace protobuf {
+
+class MapLiteTestUtil {
+ public:
+ // Set every field in the TestMapLite message to a unique value.
+ static void SetMapFields(protobuf_unittest::TestMapLite* message);
+
+ // Set every field in the TestArenaMapLite message to a unique value.
+ static void SetArenaMapFields(protobuf_unittest::TestArenaMapLite* message);
+
+ // Set every field in the message to a default value.
+ static void SetMapFieldsInitialized(protobuf_unittest::TestMapLite* message);
+
+ // Modify all the map fields of the messsage (which should already have been
+ // initialized with SetMapFields()).
+ static void ModifyMapFields(protobuf_unittest::TestMapLite* message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called.
+ static void ExpectMapFieldsSet(const protobuf_unittest::TestMapLite& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called for TestArenaMapLite.
+ static void ExpectArenaMapFieldsSet(
+ const protobuf_unittest::TestArenaMapLite& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFieldsInitialized() is called.
+ static void ExpectMapFieldsSetInitialized(
+ const protobuf_unittest::TestMapLite& message);
+
+ // Expect that the message is modified as would be expected from
+ // ModifyMapFields().
+ static void ExpectMapFieldsModified(
+ const protobuf_unittest::TestMapLite& message);
+
+ // Check that all fields are empty.
+ static void ExpectClear(const protobuf_unittest::TestMapLite& message);
+};
+
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto
index cc71555d..c69e8d94 100644
--- a/src/google/protobuf/map_lite_unittest.proto
+++ b/src/google/protobuf/map_lite_unittest.proto
@@ -30,10 +30,104 @@
syntax = "proto2";
+option cc_enable_arenas = true;
option optimize_for = LITE_RUNTIME;
+import "google/protobuf/unittest_lite.proto";
+
package protobuf_unittest;
-message MapLite {
- map<int32, int32> map_field = 1;
+message TestMapLite {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<string , string > map_string_string = 14;
+ map<int32 , bytes > map_int32_bytes = 15;
+ map<int32 , MapEnumLite> map_int32_enum = 16;
+ map<int32 , ForeignMessageLite> map_int32_foreign_message = 17;
+ map<int32, int32> teboring = 18;
+}
+
+message TestArenaMapLite {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<int32 , MapEnumLite> map_int32_enum = 14;
+ map<int32 , ForeignMessageArenaLite> map_int32_foreign_message = 15;
+}
+
+// Test embeded message with required fields
+message TestRequiredMessageMapLite {
+ map<int32, TestRequiredLite> map_field = 1;
+}
+
+message TestEnumStartWithNonZeroMapLite {
+ map<int32, Proto2MapEnumStartWithNonZeroLite> map_field = 101;
+}
+
+message TestEnumMapLite {
+ map<int32, Proto2MapEnumLite> known_map_field = 101;
+ map<int32, Proto2MapEnumLite> unknown_map_field = 102;
+}
+
+message TestEnumMapPlusExtraLite {
+ map<int32, Proto2MapEnumPlusExtraLite> known_map_field = 101;
+ map<int32, Proto2MapEnumPlusExtraLite> unknown_map_field = 102;
+}
+
+message TestMessageMapLite {
+ map<int32, TestAllTypesLite> map_int32_message = 1;
+}
+
+enum Proto2MapEnumLite {
+ PROTO2_MAP_ENUM_FOO_LITE = 0;
+ PROTO2_MAP_ENUM_BAR_LITE = 1;
+ PROTO2_MAP_ENUM_BAZ_LITE = 2;
+}
+
+enum Proto2MapEnumPlusExtraLite {
+ E_PROTO2_MAP_ENUM_FOO_LITE = 0;
+ E_PROTO2_MAP_ENUM_BAR_LITE = 1;
+ E_PROTO2_MAP_ENUM_BAZ_LITE = 2;
+ E_PROTO2_MAP_ENUM_EXTRA_LITE = 3;
+}
+
+enum Proto2MapEnumStartWithNonZeroLite {
+ PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE = 1;
+}
+
+enum MapEnumLite {
+ MAP_ENUM_FOO_LITE = 0;
+ MAP_ENUM_BAR_LITE = 1;
+ MAP_ENUM_BAZ_LITE = 2;
+}
+
+message TestRequiredLite {
+ required int32 a = 1;
+ required int32 b = 2;
+ required int32 c = 3;
+}
+
+message ForeignMessageArenaLite {
+ optional int32 c = 1;
}
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index 9db67523..88cba1f2 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -39,7 +39,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/testing/file.h>
-#include <google/protobuf/map_lite_unittest.pb.h>
+#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/map_proto2_unittest.pb.h>
#include <google/protobuf/map_unittest.pb.h>
#include <google/protobuf/map_test_util.h>
@@ -191,6 +191,7 @@ TEST_F(MapImplTest, MutableAt) {
}
#ifdef PROTOBUF_HAS_DEATH_TEST
+
TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
EXPECT_DEATH(map_.at(0), "");
}
@@ -198,6 +199,7 @@ TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
EXPECT_DEATH(const_map_.at(0), "");
}
+
#endif // PROTOBUF_HAS_DEATH_TEST
TEST_F(MapImplTest, CountNonExist) {
@@ -553,6 +555,14 @@ TEST_F(MapImplTest, ConvertToStdMap) {
EXPECT_EQ(101, std_map[100]);
}
+TEST_F(MapImplTest, ConvertToStdVectorOfPairs) {
+ map_[100] = 101;
+ std::vector<std::pair<int32, int32> > std_vec(map_.begin(), map_.end());
+ EXPECT_EQ(1, std_vec.size());
+ EXPECT_EQ(100, std_vec[0].first);
+ EXPECT_EQ(101, std_vec[0].second);
+}
+
// Map Field Reflection Test ========================================
static int Func(int i, int j) {
@@ -1717,6 +1727,20 @@ TEST(GeneratedMapFieldTest, MissedValueWireFormat) {
EXPECT_EQ(0, message.map_int32_int32().at(1));
}
+TEST(GeneratedMapFieldTest, MissedValueTextFormat) {
+ unittest::TestMap message;
+
+ // No value field in text format
+ string text =
+ "map_int32_foreign_message {\n"
+ " key: 1234567890\n"
+ "}";
+
+ EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message));
+ EXPECT_EQ(1, message.map_int32_foreign_message().size());
+ EXPECT_EQ(11, message.ByteSize());
+}
+
TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) {
unittest::TestMap message;
@@ -1737,18 +1761,6 @@ TEST(GeneratedMapFieldTest, CorruptedWireFormat) {
EXPECT_FALSE(message.ParseFromString(data));
}
-TEST(GeneratedMapFieldTest, MessageLiteMap) {
- unittest::MapLite from, to;
- (*from.mutable_map_field())[1] = 1;
-
- string data;
- from.SerializeToString(&data);
- to.ParseFromString(data);
-
- EXPECT_EQ(1, to.map_field().size());
- EXPECT_EQ(1, to.map_field().at(1));
-}
-
TEST(GeneratedMapFieldTest, IsInitialized) {
unittest::TestRequiredMessageMap map_message;
@@ -2247,6 +2259,52 @@ TEST(TextFormatMapTest, SerializeAndParse) {
}
+// arena support =================================================
+TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
+ // Allocate a large initial block to avoid mallocs during hooked test.
+ std::vector<char> arena_block(128 * 1024);
+ ArenaOptions options;
+ options.initial_block = arena_block.data();
+ options.initial_block_size = arena_block.size();
+ Arena arena(options);
+ string data;
+ data.reserve(128 * 1024);
+
+ {
+ NoHeapChecker no_heap;
+
+ unittest::TestArenaMap* from =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ MapTestUtil::SetArenaMapFields(from);
+ from->SerializeToString(&data);
+
+ unittest::TestArenaMap* to =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ to->ParseFromString(data);
+ MapTestUtil::ExpectArenaMapFieldsSet(*to);
+ }
+}
+
+// Use text format parsing and serializing to test reflection api.
+TEST(ArenaTest, RelfectionInTextFormat) {
+ Arena arena;
+ string data;
+
+ TextFormat::Printer printer;
+ TextFormat::Parser parser;
+
+ unittest::TestArenaMap* from =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ unittest::TestArenaMap* to =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+
+ MapTestUtil::SetArenaMapFields(from);
+ printer.PrintToString(*from, &data);
+
+ EXPECT_TRUE(parser.ParseFromString(data, to));
+ MapTestUtil::ExpectArenaMapFieldsSet(*to);
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc
index eb7ea511..1713e373 100644
--- a/src/google/protobuf/map_test_util.cc
+++ b/src/google/protobuf/map_test_util.cc
@@ -29,275 +29,60 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/map_test_util.h>
+#include <google/protobuf/map_test_util_impl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
namespace google {
namespace protobuf {
void MapTestUtil::SetMapFields(unittest::TestMap* message) {
- // Add first element.
- (*message->mutable_map_int32_int32())[0] = 0;
- (*message->mutable_map_int64_int64())[0] = 0;
- (*message->mutable_map_uint32_uint32())[0] = 0;
- (*message->mutable_map_uint64_uint64())[0] = 0;
- (*message->mutable_map_sint32_sint32())[0] = 0;
- (*message->mutable_map_sint64_sint64())[0] = 0;
- (*message->mutable_map_fixed32_fixed32())[0] = 0;
- (*message->mutable_map_fixed64_fixed64())[0] = 0;
- (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
- (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
- (*message->mutable_map_int32_float())[0] = 0.0;
- (*message->mutable_map_int32_double())[0] = 0.0;
- (*message->mutable_map_bool_bool())[0] = false;
- (*message->mutable_map_string_string())["0"] = "0";
- (*message->mutable_map_int32_bytes())[0] = "0";
- (*message->mutable_map_int32_enum())[0] =
- unittest::MAP_ENUM_BAR;
- (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+ MapTestUtilImpl::SetMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+ unittest::MAP_ENUM_BAZ>(message);
+}
- // Add second element
- (*message->mutable_map_int32_int32())[1] = 1;
- (*message->mutable_map_int64_int64())[1] = 1;
- (*message->mutable_map_uint32_uint32())[1] = 1;
- (*message->mutable_map_uint64_uint64())[1] = 1;
- (*message->mutable_map_sint32_sint32())[1] = 1;
- (*message->mutable_map_sint64_sint64())[1] = 1;
- (*message->mutable_map_fixed32_fixed32())[1] = 1;
- (*message->mutable_map_fixed64_fixed64())[1] = 1;
- (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
- (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
- (*message->mutable_map_int32_float())[1] = 1.0;
- (*message->mutable_map_int32_double())[1] = 1.0;
- (*message->mutable_map_bool_bool())[1] = true;
- (*message->mutable_map_string_string())["1"] = "1";
- (*message->mutable_map_int32_bytes())[1] = "1";
- (*message->mutable_map_int32_enum())[1] =
- unittest::MAP_ENUM_BAZ;
- (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+void MapTestUtil::SetArenaMapFields(unittest::TestArenaMap* message) {
+ MapTestUtilImpl::SetArenaMapFields<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+ unittest::MAP_ENUM_BAZ>(message);
}
void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) {
- // Add first element using bracket operator, which should assign default
- // value automatically.
- (*message->mutable_map_int32_int32())[0];
- (*message->mutable_map_int64_int64())[0];
- (*message->mutable_map_uint32_uint32())[0];
- (*message->mutable_map_uint64_uint64())[0];
- (*message->mutable_map_sint32_sint32())[0];
- (*message->mutable_map_sint64_sint64())[0];
- (*message->mutable_map_fixed32_fixed32())[0];
- (*message->mutable_map_fixed64_fixed64())[0];
- (*message->mutable_map_sfixed32_sfixed32())[0];
- (*message->mutable_map_sfixed64_sfixed64())[0];
- (*message->mutable_map_int32_float())[0];
- (*message->mutable_map_int32_double())[0];
- (*message->mutable_map_bool_bool())[0];
- (*message->mutable_map_string_string())["0"];
- (*message->mutable_map_int32_bytes())[0];
- (*message->mutable_map_int32_enum())[0];
- (*message->mutable_map_int32_foreign_message())[0];
+ MapTestUtilImpl::SetMapFieldsInitialized(message);
}
void MapTestUtil::ModifyMapFields(unittest::TestMap* message) {
- (*message->mutable_map_int32_int32())[1] = 2;
- (*message->mutable_map_int64_int64())[1] = 2;
- (*message->mutable_map_uint32_uint32())[1] = 2;
- (*message->mutable_map_uint64_uint64())[1] = 2;
- (*message->mutable_map_sint32_sint32())[1] = 2;
- (*message->mutable_map_sint64_sint64())[1] = 2;
- (*message->mutable_map_fixed32_fixed32())[1] = 2;
- (*message->mutable_map_fixed64_fixed64())[1] = 2;
- (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
- (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
- (*message->mutable_map_int32_float())[1] = 2.0;
- (*message->mutable_map_int32_double())[1] = 2.0;
- (*message->mutable_map_bool_bool())[1] = false;
- (*message->mutable_map_string_string())["1"] = "2";
- (*message->mutable_map_int32_bytes())[1] = "2";
- (*message->mutable_map_int32_enum())[1] =
- unittest::MAP_ENUM_FOO;
- (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+ MapTestUtilImpl::ModifyMapFields<unittest::MapEnum, unittest::MAP_ENUM_FOO>(
+ message);
}
void MapTestUtil::ExpectClear(const unittest::TestMap& message) {
- EXPECT_EQ(0, message.map_int32_int32().size());
- EXPECT_EQ(0, message.map_int64_int64().size());
- EXPECT_EQ(0, message.map_uint32_uint32().size());
- EXPECT_EQ(0, message.map_uint64_uint64().size());
- EXPECT_EQ(0, message.map_sint32_sint32().size());
- EXPECT_EQ(0, message.map_sint64_sint64().size());
- EXPECT_EQ(0, message.map_fixed32_fixed32().size());
- EXPECT_EQ(0, message.map_fixed64_fixed64().size());
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(0, message.map_int32_float().size());
- EXPECT_EQ(0, message.map_int32_double().size());
- EXPECT_EQ(0, message.map_bool_bool().size());
- EXPECT_EQ(0, message.map_string_string().size());
- EXPECT_EQ(0, message.map_int32_bytes().size());
- EXPECT_EQ(0, message.map_int32_enum().size());
- EXPECT_EQ(0, message.map_int32_foreign_message().size());
+ MapTestUtilImpl::ExpectClear(message);
}
void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) {
- EXPECT_EQ(2, message.map_int32_int32().size());
- EXPECT_EQ(2, message.map_int64_int64().size());
- EXPECT_EQ(2, message.map_uint32_uint32().size());
- EXPECT_EQ(2, message.map_uint64_uint64().size());
- EXPECT_EQ(2, message.map_sint32_sint32().size());
- EXPECT_EQ(2, message.map_sint64_sint64().size());
- EXPECT_EQ(2, message.map_fixed32_fixed32().size());
- EXPECT_EQ(2, message.map_fixed64_fixed64().size());
- EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(2, message.map_int32_float().size());
- EXPECT_EQ(2, message.map_int32_double().size());
- EXPECT_EQ(2, message.map_bool_bool().size());
- EXPECT_EQ(2, message.map_string_string().size());
- EXPECT_EQ(2, message.map_int32_bytes().size());
- EXPECT_EQ(2, message.map_int32_enum().size());
- EXPECT_EQ(2, message.map_int32_foreign_message().size());
-
- EXPECT_EQ(0, message.map_int32_int32().at(0));
- EXPECT_EQ(0, message.map_int64_int64().at(0));
- EXPECT_EQ(0, message.map_uint32_uint32().at(0));
- EXPECT_EQ(0, message.map_uint64_uint64().at(0));
- EXPECT_EQ(0, message.map_sint32_sint32().at(0));
- EXPECT_EQ(0, message.map_sint64_sint64().at(0));
- EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
- EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
- EXPECT_EQ(0, message.map_int32_float().at(0));
- EXPECT_EQ(0, message.map_int32_double().at(0));
- EXPECT_EQ(false, message.map_bool_bool().at(0));
- EXPECT_EQ("0", message.map_string_string().at("0"));
- EXPECT_EQ("0", message.map_int32_bytes().at(0));
- EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
- EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
-
- EXPECT_EQ(1, message.map_int32_int32().at(1));
- EXPECT_EQ(1, message.map_int64_int64().at(1));
- EXPECT_EQ(1, message.map_uint32_uint32().at(1));
- EXPECT_EQ(1, message.map_uint64_uint64().at(1));
- EXPECT_EQ(1, message.map_sint32_sint32().at(1));
- EXPECT_EQ(1, message.map_sint64_sint64().at(1));
- EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
- EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
- EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
- EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
- EXPECT_EQ(1, message.map_int32_float().at(1));
- EXPECT_EQ(1, message.map_int32_double().at(1));
- EXPECT_EQ(true, message.map_bool_bool().at(1));
- EXPECT_EQ("1", message.map_string_string().at("1"));
- EXPECT_EQ("1", message.map_int32_bytes().at(1));
- EXPECT_EQ(unittest::MAP_ENUM_BAZ, message.map_int32_enum().at(1));
- EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+ MapTestUtilImpl::ExpectMapFieldsSet<unittest::MapEnum, unittest::MAP_ENUM_BAR,
+ unittest::MAP_ENUM_BAZ>(message);
+}
+
+void MapTestUtil::ExpectArenaMapFieldsSet(
+ const unittest::TestArenaMap& message) {
+ MapTestUtilImpl::ExpectArenaMapFieldsSet<
+ unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_BAZ>(
+ message);
}
void MapTestUtil::ExpectMapFieldsSetInitialized(
const unittest::TestMap& message) {
- EXPECT_EQ(1, message.map_int32_int32().size());
- EXPECT_EQ(1, message.map_int64_int64().size());
- EXPECT_EQ(1, message.map_uint32_uint32().size());
- EXPECT_EQ(1, message.map_uint64_uint64().size());
- EXPECT_EQ(1, message.map_sint32_sint32().size());
- EXPECT_EQ(1, message.map_sint64_sint64().size());
- EXPECT_EQ(1, message.map_fixed32_fixed32().size());
- EXPECT_EQ(1, message.map_fixed64_fixed64().size());
- EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(1, message.map_int32_float().size());
- EXPECT_EQ(1, message.map_int32_double().size());
- EXPECT_EQ(1, message.map_bool_bool().size());
- EXPECT_EQ(1, message.map_string_string().size());
- EXPECT_EQ(1, message.map_int32_bytes().size());
- EXPECT_EQ(1, message.map_int32_enum().size());
- EXPECT_EQ(1, message.map_int32_foreign_message().size());
-
- EXPECT_EQ(0, message.map_int32_int32().at(0));
- EXPECT_EQ(0, message.map_int64_int64().at(0));
- EXPECT_EQ(0, message.map_uint32_uint32().at(0));
- EXPECT_EQ(0, message.map_uint64_uint64().at(0));
- EXPECT_EQ(0, message.map_sint32_sint32().at(0));
- EXPECT_EQ(0, message.map_sint64_sint64().at(0));
- EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
- EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
- EXPECT_EQ(0, message.map_int32_float().at(0));
- EXPECT_EQ(0, message.map_int32_double().at(0));
- EXPECT_EQ(false, message.map_bool_bool().at(0));
- EXPECT_EQ("", message.map_string_string().at("0"));
- EXPECT_EQ("", message.map_int32_bytes().at(0));
- EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(0));
- EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+ MapTestUtilImpl::ExpectMapFieldsSetInitialized<unittest::MapEnum,
+ unittest::MAP_ENUM_FOO>(
+ message);
}
void MapTestUtil::ExpectMapFieldsModified(
const unittest::TestMap& message) {
- // ModifyMapFields only sets the second element of each field. In addition to
- // verifying this, we also verify that the first element and size were *not*
- // modified.
- EXPECT_EQ(2, message.map_int32_int32().size());
- EXPECT_EQ(2, message.map_int64_int64().size());
- EXPECT_EQ(2, message.map_uint32_uint32().size());
- EXPECT_EQ(2, message.map_uint64_uint64().size());
- EXPECT_EQ(2, message.map_sint32_sint32().size());
- EXPECT_EQ(2, message.map_sint64_sint64().size());
- EXPECT_EQ(2, message.map_fixed32_fixed32().size());
- EXPECT_EQ(2, message.map_fixed64_fixed64().size());
- EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
- EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
- EXPECT_EQ(2, message.map_int32_float().size());
- EXPECT_EQ(2, message.map_int32_double().size());
- EXPECT_EQ(2, message.map_bool_bool().size());
- EXPECT_EQ(2, message.map_string_string().size());
- EXPECT_EQ(2, message.map_int32_bytes().size());
- EXPECT_EQ(2, message.map_int32_enum().size());
- EXPECT_EQ(2, message.map_int32_foreign_message().size());
-
- EXPECT_EQ(0, message.map_int32_int32().at(0));
- EXPECT_EQ(0, message.map_int64_int64().at(0));
- EXPECT_EQ(0, message.map_uint32_uint32().at(0));
- EXPECT_EQ(0, message.map_uint64_uint64().at(0));
- EXPECT_EQ(0, message.map_sint32_sint32().at(0));
- EXPECT_EQ(0, message.map_sint64_sint64().at(0));
- EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
- EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
- EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
- EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
- EXPECT_EQ(0, message.map_int32_float().at(0));
- EXPECT_EQ(0, message.map_int32_double().at(0));
- EXPECT_EQ(false, message.map_bool_bool().at(0));
- EXPECT_EQ("0", message.map_string_string().at("0"));
- EXPECT_EQ("0", message.map_int32_bytes().at(0));
- EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0));
- EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
-
- // Actually verify the second (modified) elements now.
- EXPECT_EQ(2, message.map_int32_int32().at(1));
- EXPECT_EQ(2, message.map_int64_int64().at(1));
- EXPECT_EQ(2, message.map_uint32_uint32().at(1));
- EXPECT_EQ(2, message.map_uint64_uint64().at(1));
- EXPECT_EQ(2, message.map_sint32_sint32().at(1));
- EXPECT_EQ(2, message.map_sint64_sint64().at(1));
- EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
- EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
- EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
- EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
- EXPECT_EQ(2, message.map_int32_float().at(1));
- EXPECT_EQ(2, message.map_int32_double().at(1));
- EXPECT_EQ(false, message.map_bool_bool().at(1));
- EXPECT_EQ("2", message.map_string_string().at("1"));
- EXPECT_EQ("2", message.map_int32_bytes().at(1));
- EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(1));
- EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+ MapTestUtilImpl::ExpectMapFieldsModified<
+ unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_FOO>(
+ message);
}
void MapTestUtil::ExpectMapsSize(
@@ -1468,8 +1253,9 @@ void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection(
sub_message = reflection->AddMessage(message, F("map_int32_enum"));
EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message,
key_descriptor));
- EXPECT_EQ(0, sub_message->GetReflection()->GetEnum(*sub_message,
- value_descriptor));
+ EXPECT_EQ(0, sub_message->GetReflection()
+ ->GetEnum(*sub_message, value_descriptor)
+ ->number());
}
// Map using message as value has been tested in other place. Thus, we don't
// test it here.
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index 653cf107..f437e33e 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -40,9 +40,12 @@ namespace unittest = ::protobuf_unittest;
class MapTestUtil {
public:
- // Set every field in the message to a unique value.
+ // Set every field in the TestMap message to a unique value.
static void SetMapFields(unittest::TestMap* message);
+ // Set every field in the TestArenaMap message to a unique value.
+ static void SetArenaMapFields(unittest::TestArenaMap* message);
+
// Set every field in the message to a default value.
static void SetMapFieldsInitialized(unittest::TestMap* message);
@@ -55,6 +58,10 @@ class MapTestUtil {
static void ExpectMapFieldsSet(const unittest::TestMap& message);
// Check that all fields have the values that they should have after
+ // SetMapFields() is called for TestArenaMap.
+ static void ExpectArenaMapFieldsSet(const unittest::TestArenaMap& message);
+
+ // Check that all fields have the values that they should have after
// SetMapFieldsInitialized() is called.
static void ExpectMapFieldsSetInitialized(
const unittest::TestMap& message);
diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
new file mode 100644
index 00000000..5e7882a1
--- /dev/null
+++ b/src/google/protobuf/map_test_util_impl.h
@@ -0,0 +1,474 @@
+// 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_MAP_TEST_UTIL_IMPL_H__
+#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+
+#include <google/protobuf/stubs/common.h>
+
+
+#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
+
+namespace google {
+namespace protobuf_unittest {} // forward declaration
+
+namespace protobuf {
+
+namespace unittest = ::protobuf_unittest;
+
+class MapTestUtilImpl {
+ public:
+ // Set every field in the TestMap message to a unique value.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void SetMapFields(MapMessage* message);
+
+ // Set every field in the TestArenaMap message to a unique value.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void SetArenaMapFields(MapMessage* message);
+
+ // Set every field in the message to a default value.
+ template <typename MapMessage>
+ static void SetMapFieldsInitialized(MapMessage* message);
+
+ // Modify all the map fields of the messsage (which should already have been
+ // initialized with SetMapFields()).
+ template <typename EnumType, EnumType enum_value, typename MapMessage>
+ static void ModifyMapFields(MapMessage* message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void ExpectMapFieldsSet(const MapMessage& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFields() is called for TestArenaMap.
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void ExpectArenaMapFieldsSet(const MapMessage& message);
+
+ // Check that all fields have the values that they should have after
+ // SetMapFieldsInitialized() is called.
+ template <typename EnumType, EnumType enum_value, typename MapMessage>
+ static void ExpectMapFieldsSetInitialized(const MapMessage& message);
+
+ // Expect that the message is modified as would be expected from
+ // ModifyMapFields().
+ template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+ static void ExpectMapFieldsModified(const MapMessage& message);
+
+ // Check that all fields are empty.
+ template <typename MapMessage>
+ static void ExpectClear(const MapMessage& message);
+
+ // // Check that all map fields have the given size.
+ // template <typename MapMessage>
+ // static void ExpectMapsSize(const MapMessage& message, int size);
+
+ // // Get pointers of map entries at given index.
+ // static std::vector<const Message*> GetMapEntries(
+ // const MapMessage& message, int index);
+
+ // // Get pointers of map entries from release.
+ // static std::vector<const Message*> GetMapEntriesFromRelease(
+ // MapMessage* message);
+};
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetMapFields(MapMessage* message) {
+ // Add first element.
+ (*message->mutable_map_int32_int32())[0] = 0;
+ (*message->mutable_map_int64_int64())[0] = 0;
+ (*message->mutable_map_uint32_uint32())[0] = 0;
+ (*message->mutable_map_uint64_uint64())[0] = 0;
+ (*message->mutable_map_sint32_sint32())[0] = 0;
+ (*message->mutable_map_sint64_sint64())[0] = 0;
+ (*message->mutable_map_fixed32_fixed32())[0] = 0;
+ (*message->mutable_map_fixed64_fixed64())[0] = 0;
+ (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+ (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+ (*message->mutable_map_int32_float())[0] = 0.0;
+ (*message->mutable_map_int32_double())[0] = 0.0;
+ (*message->mutable_map_bool_bool())[0] = false;
+ (*message->mutable_map_string_string())["0"] = "0";
+ (*message->mutable_map_int32_bytes())[0] = "0";
+ (*message->mutable_map_int32_enum())[0] = enum_value0;
+ (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+ // Add second element
+ (*message->mutable_map_int32_int32())[1] = 1;
+ (*message->mutable_map_int64_int64())[1] = 1;
+ (*message->mutable_map_uint32_uint32())[1] = 1;
+ (*message->mutable_map_uint64_uint64())[1] = 1;
+ (*message->mutable_map_sint32_sint32())[1] = 1;
+ (*message->mutable_map_sint64_sint64())[1] = 1;
+ (*message->mutable_map_fixed32_fixed32())[1] = 1;
+ (*message->mutable_map_fixed64_fixed64())[1] = 1;
+ (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+ (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+ (*message->mutable_map_int32_float())[1] = 1.0;
+ (*message->mutable_map_int32_double())[1] = 1.0;
+ (*message->mutable_map_bool_bool())[1] = true;
+ (*message->mutable_map_string_string())["1"] = "1";
+ (*message->mutable_map_int32_bytes())[1] = "1";
+ (*message->mutable_map_int32_enum())[1] = enum_value1;
+ (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
+ // Add first element.
+ (*message->mutable_map_int32_int32())[0] = 0;
+ (*message->mutable_map_int64_int64())[0] = 0;
+ (*message->mutable_map_uint32_uint32())[0] = 0;
+ (*message->mutable_map_uint64_uint64())[0] = 0;
+ (*message->mutable_map_sint32_sint32())[0] = 0;
+ (*message->mutable_map_sint64_sint64())[0] = 0;
+ (*message->mutable_map_fixed32_fixed32())[0] = 0;
+ (*message->mutable_map_fixed64_fixed64())[0] = 0;
+ (*message->mutable_map_sfixed32_sfixed32())[0] = 0;
+ (*message->mutable_map_sfixed64_sfixed64())[0] = 0;
+ (*message->mutable_map_int32_float())[0] = 0.0;
+ (*message->mutable_map_int32_double())[0] = 0.0;
+ (*message->mutable_map_bool_bool())[0] = false;
+ (*message->mutable_map_int32_enum())[0] = enum_value0;
+ (*message->mutable_map_int32_foreign_message())[0].set_c(0);
+
+ // Add second element
+ (*message->mutable_map_int32_int32())[1] = 1;
+ (*message->mutable_map_int64_int64())[1] = 1;
+ (*message->mutable_map_uint32_uint32())[1] = 1;
+ (*message->mutable_map_uint64_uint64())[1] = 1;
+ (*message->mutable_map_sint32_sint32())[1] = 1;
+ (*message->mutable_map_sint64_sint64())[1] = 1;
+ (*message->mutable_map_fixed32_fixed32())[1] = 1;
+ (*message->mutable_map_fixed64_fixed64())[1] = 1;
+ (*message->mutable_map_sfixed32_sfixed32())[1] = 1;
+ (*message->mutable_map_sfixed64_sfixed64())[1] = 1;
+ (*message->mutable_map_int32_float())[1] = 1.0;
+ (*message->mutable_map_int32_double())[1] = 1.0;
+ (*message->mutable_map_bool_bool())[1] = true;
+ (*message->mutable_map_int32_enum())[1] = enum_value1;
+ (*message->mutable_map_int32_foreign_message())[1].set_c(1);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::SetMapFieldsInitialized(MapMessage* message) {
+ // Add first element using bracket operator, which should assign default
+ // value automatically.
+ (*message->mutable_map_int32_int32())[0];
+ (*message->mutable_map_int64_int64())[0];
+ (*message->mutable_map_uint32_uint32())[0];
+ (*message->mutable_map_uint64_uint64())[0];
+ (*message->mutable_map_sint32_sint32())[0];
+ (*message->mutable_map_sint64_sint64())[0];
+ (*message->mutable_map_fixed32_fixed32())[0];
+ (*message->mutable_map_fixed64_fixed64())[0];
+ (*message->mutable_map_sfixed32_sfixed32())[0];
+ (*message->mutable_map_sfixed64_sfixed64())[0];
+ (*message->mutable_map_int32_float())[0];
+ (*message->mutable_map_int32_double())[0];
+ (*message->mutable_map_bool_bool())[0];
+ (*message->mutable_map_string_string())["0"];
+ (*message->mutable_map_int32_bytes())[0];
+ (*message->mutable_map_int32_enum())[0];
+ (*message->mutable_map_int32_foreign_message())[0];
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ModifyMapFields(MapMessage* message) {
+ (*message->mutable_map_int32_int32())[1] = 2;
+ (*message->mutable_map_int64_int64())[1] = 2;
+ (*message->mutable_map_uint32_uint32())[1] = 2;
+ (*message->mutable_map_uint64_uint64())[1] = 2;
+ (*message->mutable_map_sint32_sint32())[1] = 2;
+ (*message->mutable_map_sint64_sint64())[1] = 2;
+ (*message->mutable_map_fixed32_fixed32())[1] = 2;
+ (*message->mutable_map_fixed64_fixed64())[1] = 2;
+ (*message->mutable_map_sfixed32_sfixed32())[1] = 2;
+ (*message->mutable_map_sfixed64_sfixed64())[1] = 2;
+ (*message->mutable_map_int32_float())[1] = 2.0;
+ (*message->mutable_map_int32_double())[1] = 2.0;
+ (*message->mutable_map_bool_bool())[1] = false;
+ (*message->mutable_map_string_string())["1"] = "2";
+ (*message->mutable_map_int32_bytes())[1] = "2";
+ (*message->mutable_map_int32_enum())[1] = enum_value;
+ (*message->mutable_map_int32_foreign_message())[1].set_c(2);
+}
+
+template <typename MapMessage>
+void MapTestUtilImpl::ExpectClear(const MapMessage& message) {
+ EXPECT_EQ(0, message.map_int32_int32().size());
+ EXPECT_EQ(0, message.map_int64_int64().size());
+ EXPECT_EQ(0, message.map_uint32_uint32().size());
+ EXPECT_EQ(0, message.map_uint64_uint64().size());
+ EXPECT_EQ(0, message.map_sint32_sint32().size());
+ EXPECT_EQ(0, message.map_sint64_sint64().size());
+ EXPECT_EQ(0, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(0, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(0, message.map_int32_float().size());
+ EXPECT_EQ(0, message.map_int32_double().size());
+ EXPECT_EQ(0, message.map_bool_bool().size());
+ EXPECT_EQ(0, message.map_string_string().size());
+ EXPECT_EQ(0, message.map_int32_bytes().size());
+ EXPECT_EQ(0, message.map_int32_enum().size());
+ EXPECT_EQ(0, message.map_int32_foreign_message().size());
+}
+
+
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) {
+ EXPECT_EQ(2, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int64_int64().size());
+ EXPECT_EQ(2, message.map_uint32_uint32().size());
+ EXPECT_EQ(2, message.map_uint64_uint64().size());
+ EXPECT_EQ(2, message.map_sint32_sint32().size());
+ EXPECT_EQ(2, message.map_sint64_sint64().size());
+ EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(2, message.map_int32_float().size());
+ EXPECT_EQ(2, message.map_int32_double().size());
+ EXPECT_EQ(2, message.map_bool_bool().size());
+ EXPECT_EQ(2, message.map_string_string().size());
+ EXPECT_EQ(2, message.map_int32_bytes().size());
+ EXPECT_EQ(2, message.map_int32_enum().size());
+ EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ("0", message.map_string_string().at("0"));
+ EXPECT_EQ("0", message.map_int32_bytes().at(0));
+ EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+ EXPECT_EQ(1, message.map_int32_int32().at(1));
+ EXPECT_EQ(1, message.map_int64_int64().at(1));
+ EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+ EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+ EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+ EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+ EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+ EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+ EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+ EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+ EXPECT_EQ(1, message.map_int32_float().at(1));
+ EXPECT_EQ(1, message.map_int32_double().at(1));
+ EXPECT_EQ(true, message.map_bool_bool().at(1));
+ EXPECT_EQ("1", message.map_string_string().at("1"));
+ EXPECT_EQ("1", message.map_int32_bytes().at(1));
+ EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+ EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
+ EXPECT_EQ(2, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int64_int64().size());
+ EXPECT_EQ(2, message.map_uint32_uint32().size());
+ EXPECT_EQ(2, message.map_uint64_uint64().size());
+ EXPECT_EQ(2, message.map_sint32_sint32().size());
+ EXPECT_EQ(2, message.map_sint64_sint64().size());
+ EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(2, message.map_int32_float().size());
+ EXPECT_EQ(2, message.map_int32_double().size());
+ EXPECT_EQ(2, message.map_bool_bool().size());
+ EXPECT_EQ(2, message.map_int32_enum().size());
+ EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+ EXPECT_EQ(1, message.map_int32_int32().at(1));
+ EXPECT_EQ(1, message.map_int64_int64().at(1));
+ EXPECT_EQ(1, message.map_uint32_uint32().at(1));
+ EXPECT_EQ(1, message.map_uint64_uint64().at(1));
+ EXPECT_EQ(1, message.map_sint32_sint32().at(1));
+ EXPECT_EQ(1, message.map_sint64_sint64().at(1));
+ EXPECT_EQ(1, message.map_fixed32_fixed32().at(1));
+ EXPECT_EQ(1, message.map_fixed64_fixed64().at(1));
+ EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1));
+ EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1));
+ EXPECT_EQ(1, message.map_int32_float().at(1));
+ EXPECT_EQ(1, message.map_int32_double().at(1));
+ EXPECT_EQ(true, message.map_bool_bool().at(1));
+ EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+ EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c());
+}
+
+template <typename EnumType, EnumType enum_value, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsSetInitialized(
+ const MapMessage& message) {
+ EXPECT_EQ(1, message.map_int32_int32().size());
+ EXPECT_EQ(1, message.map_int64_int64().size());
+ EXPECT_EQ(1, message.map_uint32_uint32().size());
+ EXPECT_EQ(1, message.map_uint64_uint64().size());
+ EXPECT_EQ(1, message.map_sint32_sint32().size());
+ EXPECT_EQ(1, message.map_sint64_sint64().size());
+ EXPECT_EQ(1, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(1, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(1, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(1, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(1, message.map_int32_float().size());
+ EXPECT_EQ(1, message.map_int32_double().size());
+ EXPECT_EQ(1, message.map_bool_bool().size());
+ EXPECT_EQ(1, message.map_string_string().size());
+ EXPECT_EQ(1, message.map_int32_bytes().size());
+ EXPECT_EQ(1, message.map_int32_enum().size());
+ EXPECT_EQ(1, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ("", message.map_string_string().at("0"));
+ EXPECT_EQ("", message.map_int32_bytes().at(0));
+ EXPECT_EQ(enum_value, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize());
+}
+
+template <typename EnumType, EnumType enum_value0,
+ EnumType enum_value1, typename MapMessage>
+void MapTestUtilImpl::ExpectMapFieldsModified(
+ const MapMessage& message) {
+ // ModifyMapFields only sets the second element of each field. In addition to
+ // verifying this, we also verify that the first element and size were *not*
+ // modified.
+ EXPECT_EQ(2, message.map_int32_int32().size());
+ EXPECT_EQ(2, message.map_int64_int64().size());
+ EXPECT_EQ(2, message.map_uint32_uint32().size());
+ EXPECT_EQ(2, message.map_uint64_uint64().size());
+ EXPECT_EQ(2, message.map_sint32_sint32().size());
+ EXPECT_EQ(2, message.map_sint64_sint64().size());
+ EXPECT_EQ(2, message.map_fixed32_fixed32().size());
+ EXPECT_EQ(2, message.map_fixed64_fixed64().size());
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().size());
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().size());
+ EXPECT_EQ(2, message.map_int32_float().size());
+ EXPECT_EQ(2, message.map_int32_double().size());
+ EXPECT_EQ(2, message.map_bool_bool().size());
+ EXPECT_EQ(2, message.map_string_string().size());
+ EXPECT_EQ(2, message.map_int32_bytes().size());
+ EXPECT_EQ(2, message.map_int32_enum().size());
+ EXPECT_EQ(2, message.map_int32_foreign_message().size());
+
+ EXPECT_EQ(0, message.map_int32_int32().at(0));
+ EXPECT_EQ(0, message.map_int64_int64().at(0));
+ EXPECT_EQ(0, message.map_uint32_uint32().at(0));
+ EXPECT_EQ(0, message.map_uint64_uint64().at(0));
+ EXPECT_EQ(0, message.map_sint32_sint32().at(0));
+ EXPECT_EQ(0, message.map_sint64_sint64().at(0));
+ EXPECT_EQ(0, message.map_fixed32_fixed32().at(0));
+ EXPECT_EQ(0, message.map_fixed64_fixed64().at(0));
+ EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0));
+ EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0));
+ EXPECT_EQ(0, message.map_int32_float().at(0));
+ EXPECT_EQ(0, message.map_int32_double().at(0));
+ EXPECT_EQ(false, message.map_bool_bool().at(0));
+ EXPECT_EQ("0", message.map_string_string().at("0"));
+ EXPECT_EQ("0", message.map_int32_bytes().at(0));
+ EXPECT_EQ(enum_value0, message.map_int32_enum().at(0));
+ EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c());
+
+ // Actually verify the second (modified) elements now.
+ EXPECT_EQ(2, message.map_int32_int32().at(1));
+ EXPECT_EQ(2, message.map_int64_int64().at(1));
+ EXPECT_EQ(2, message.map_uint32_uint32().at(1));
+ EXPECT_EQ(2, message.map_uint64_uint64().at(1));
+ EXPECT_EQ(2, message.map_sint32_sint32().at(1));
+ EXPECT_EQ(2, message.map_sint64_sint64().at(1));
+ EXPECT_EQ(2, message.map_fixed32_fixed32().at(1));
+ EXPECT_EQ(2, message.map_fixed64_fixed64().at(1));
+ EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1));
+ EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1));
+ EXPECT_EQ(2, message.map_int32_float().at(1));
+ EXPECT_EQ(2, message.map_int32_double().at(1));
+ EXPECT_EQ(false, message.map_bool_bool().at(1));
+ EXPECT_EQ("2", message.map_string_string().at("1"));
+ EXPECT_EQ("2", message.map_int32_bytes().at(1));
+ EXPECT_EQ(enum_value1, message.map_int32_enum().at(1));
+ EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c());
+}
+
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 88a6d7b8..278b78ae 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -31,8 +31,8 @@
#ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__
#define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
+#include <google/protobuf/arena.h>
#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/message.h>
#include <google/protobuf/wire_format_lite_inl.h>
namespace google {
@@ -92,6 +92,28 @@ class MapValueInitializer<false, Type> {
static inline void Initialize(Type& value, int default_enum_value) {}
};
+template <typename Type, bool is_arena_constructable>
+class MapArenaMessageCreator {
+ public:
+ // Use arena to create message if Type is arena constructable. Otherwise,
+ // create the message on heap.
+ static inline Type* CreateMessage(Arena* arena);
+};
+template <typename Type>
+class MapArenaMessageCreator<Type, true> {
+ public:
+ static inline Type* CreateMessage(Arena* arena) {
+ return Arena::CreateMessage<Type>(arena);
+ }
+};
+template <typename Type>
+class MapArenaMessageCreator<Type, false> {
+ public:
+ static inline Type* CreateMessage(Arena* arena) {
+ return new Type;
+ }
+};
+
// Handlers for key/value stored type in MapField. ==================
// Handler for message
@@ -124,20 +146,24 @@ class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
*value = const_cast<Type*>(&Type::default_instance());
}
// Initialize value when constructing MapEntry
- static inline void Initialize(Type** x) { *x = NULL; }
+ static inline void Initialize(Type** x, Arena* arena) { *x = NULL; }
// Same as above, but use default_enum_value to initialize enum type value.
static inline void InitializeMaybeByDefaultEnum(
- Type** x, int default_enum_value) {
+ Type** x, int default_enum_value, Arena* arena) {
*x = NULL;
}
// Initialize value for the first time mutable accessor is called.
- static inline void EnsureMutable(Type** value) {
- if (*value == NULL) *value = new Type;
+ static inline void EnsureMutable(Type** value, Arena* arena) {
+ if (*value == NULL) {
+ *value =
+ MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>::
+ type::value>::CreateMessage(arena);
+ }
}
// Return default instance if value is not initialized when calling const
// reference accessor.
- static inline const Type& DefaultIfNotInitialized(Type* value,
- Type* default_value) {
+ static inline const Type& DefaultIfNotInitialized(const Type* value,
+ const Type* default_value) {
return value != NULL ? *value : *default_value;
}
// Check if all required fields have values set.
@@ -166,18 +192,23 @@ class MapCppTypeHandler<string> : public MapCommonTypeHandler<string> {
if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr;
}
static inline void AssignDefaultValue(string** value) {}
- static inline void Initialize(string** value) {
+ static inline void Initialize(string** value, Arena* arena) {
*value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ if (arena != NULL) arena->Own(*value);
}
static inline void InitializeMaybeByDefaultEnum(
- string** value, int default_enum_value) {
+ string** value, int default_enum_value, Arena* arena) {
*value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
+ if (arena != NULL) arena->Own(*value);
}
- static inline void EnsureMutable(string** value) {
- if (*value == &::google::protobuf::internal::GetEmptyString()) *value = new string;
+ static inline void EnsureMutable(string** value, Arena* arena) {
+ if (*value == &::google::protobuf::internal::GetEmptyString()) {
+ *value = Arena::Create<string>(arena);
+ }
}
- static inline const string& DefaultIfNotInitialized(string* value,
- string* default_value) {
+ static inline const string& DefaultIfNotInitialized(
+ const string* value,
+ const string* default_value) {
return value != default_value ? *value : *default_value;
}
static inline bool IsInitialized(string* value) { return true; }
@@ -210,12 +241,13 @@ class MapPrimitiveTypeHandler : public MapCommonTypeHandler<Type> {
int default_enum_value) { \
*value = static_cast<CType>(default_enum_value); \
} \
- static inline void Initialize(CType* value) { *value = 0; } \
+ static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \
static inline void InitializeMaybeByDefaultEnum(CType* value, \
- int default_enum_value) { \
+ int default_enum_value, \
+ Arena* arena) { \
*value = static_cast<CType>(default_enum_value); \
} \
- static inline void EnsureMutable(CType* value) {} \
+ static inline void EnsureMutable(CType* value, Arena* arena) {} \
};
PRIMITIVE_HANDLER(int32 )
@@ -228,13 +260,13 @@ PRIMITIVE_HANDLER(bool )
#undef PRIMITIVE_HANDLER
-// Define constants for given proto field type
-template <FieldDescriptor::Type Type>
-class MapFieldTypeTraits {};
+// Define constants for given wire field type
+template <WireFormatLite::FieldType field_type>
+class MapWireFieldTypeTraits {};
#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
template <> \
- class MapFieldTypeTraits<FieldDescriptor::TYPE_##FieldType> { \
+ class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType> { \
public: \
typedef CType CppType; \
static const bool kIsMessage = IsMessage; \
@@ -243,7 +275,7 @@ class MapFieldTypeTraits {};
WireFormatLite::WIRETYPE_##WireFormatType; \
};
-TYPE_TRAITS(MESSAGE , Message, LENGTH_DELIMITED, true, false)
+TYPE_TRAITS(MESSAGE , MessageLite, LENGTH_DELIMITED, true, false)
TYPE_TRAITS(STRING , string , LENGTH_DELIMITED, false, false)
TYPE_TRAITS(BYTES , string , LENGTH_DELIMITED, false, false)
TYPE_TRAITS(INT64 , int64 , VARINT , false, false)
@@ -263,51 +295,46 @@ TYPE_TRAITS(BOOL , bool , VARINT , false, false)
#undef TYPE_TRAITS
-// Handler for proto field type. Define types and constants used in compile
-// time. Also define functions used in parsing and serializing.
-template <FieldDescriptor::Type Type>
-class MapProtoTypeHandler {
+template <WireFormatLite::FieldType field_type>
+class MapWireFieldTypeHandler {
public:
- // Internal stored type in MapEntry for given proto field type.
- typedef typename MapFieldTypeTraits<Type>::CppType CppType;
-
- // Whether given type is a message.
- static const bool kIsMessage = MapFieldTypeTraits<Type>::kIsMessage;
-
- // Whether given type is an enum.
- static const bool kIsEnum = MapFieldTypeTraits<Type>::kIsEnum;
-
- // The wire type of given proto field type.
+ // Internal stored type in MapEntryLite for given wire field type.
+ typedef typename MapWireFieldTypeTraits<field_type>::CppType CppType;
+ // Corresponding wire type for field type.
static const WireFormatLite::WireType kWireType =
- MapFieldTypeTraits<Type>::kWireType;
+ MapWireFieldTypeTraits<field_type>::kWireType;
+ // Whether wire type is for message.
+ static const bool kIsMessage = MapWireFieldTypeTraits<field_type>::kIsMessage;
+ // Whether wire type is for enum.
+ static const bool kIsEnum = MapWireFieldTypeTraits<field_type>::kIsEnum;
// Functions used in parsing and serialization. ===================
-
template <typename ValueType>
static inline int ByteSize(const ValueType& value);
template <typename ValueType>
static inline int GetCachedSize(const ValueType& value);
+ template <typename ValueType>
+ static inline bool Read(io::CodedInputStream* input, ValueType* value);
static inline void Write(int field, const CppType& value,
io::CodedOutputStream* output);
static inline uint8* WriteToArray(int field, const CppType& value,
uint8* output);
- template <typename ValueType>
- static inline bool Read(io::CodedInputStream* input, ValueType* value);
};
template <>
template <typename ValueType>
-inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::ByteSize(
+inline int MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::ByteSize(
const ValueType& value) {
return WireFormatLite::MessageSizeNoVirtual(value);
}
-#define BYTE_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
- const ValueType& value) { \
- return WireFormatLite::DeclaredType##Size(value); \
+#define BYTE_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
+ const ValueType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
BYTE_SIZE(STRING, String)
@@ -322,12 +349,13 @@ BYTE_SIZE(ENUM , Enum)
#undef BYTE_SIZE
-#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::ByteSize( \
- const ValueType& value) { \
- return WireFormatLite::k##DeclaredType##Size; \
+#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::ByteSize( \
+ const ValueType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
FIXED_BYTE_SIZE(DOUBLE , Double)
@@ -342,18 +370,18 @@ FIXED_BYTE_SIZE(BOOL , Bool)
template <>
template <typename ValueType>
-inline int MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::GetCachedSize(
- const ValueType& value) {
+inline int MapWireFieldTypeHandler<
+ WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) {
return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
}
-#define GET_CACHED_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
- const ValueType& value) { \
- return WireFormatLite::DeclaredType##Size(value); \
+#define GET_CACHED_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
+ const ValueType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
GET_CACHED_SIZE(STRING, String)
@@ -368,13 +396,13 @@ GET_CACHED_SIZE(ENUM , Enum)
#undef GET_CACHED_SIZE
-#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
- template <> \
- template <typename ValueType> \
- inline int \
- MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::GetCachedSize( \
- const ValueType& value) { \
- return WireFormatLite::k##DeclaredType##Size; \
+#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
+ template <> \
+ template <typename ValueType> \
+ inline int \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::GetCachedSize( \
+ const ValueType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
GET_FIXED_CACHED_SIZE(DOUBLE , Double)
@@ -388,26 +416,28 @@ GET_FIXED_CACHED_SIZE(BOOL , Bool)
#undef GET_FIXED_CACHED_SIZE
template <>
-inline void MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Write(
- int field, const Message& value, io::CodedOutputStream* output) {
+inline void MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Write(
+ int field, const MessageLite& value, io::CodedOutputStream* output) {
WireFormatLite::WriteMessageMaybeToArray(field, value, output);
}
template <>
-inline uint8* MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::WriteToArray(
- int field, const Message& value, uint8* output) {
+inline uint8*
+MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::WriteToArray(
+ int field, const MessageLite& value, uint8* output) {
return WireFormatLite::WriteMessageToArray(field, value, output);
}
#define WRITE_METHOD(FieldType, DeclaredType) \
template <> \
- inline void MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Write( \
+ inline void \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Write( \
int field, const CppType& value, io::CodedOutputStream* output) { \
return WireFormatLite::Write##DeclaredType(field, value, output); \
} \
template <> \
inline uint8* \
- MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::WriteToArray( \
+ MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::WriteToArray( \
int field, const CppType& value, uint8* output) { \
return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
}
@@ -433,33 +463,33 @@ WRITE_METHOD(BOOL , Bool)
template <>
template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_MESSAGE>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Read(
io::CodedInputStream* input, ValueType* value) {
return WireFormatLite::ReadMessageNoVirtual(input, value);
}
template <>
template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_STRING>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_STRING>::Read(
io::CodedInputStream* input, ValueType* value) {
return WireFormatLite::ReadString(input, value);
}
template <>
template <typename ValueType>
-inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_BYTES>::Read(
+inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_BYTES>::Read(
io::CodedInputStream* input, ValueType* value) {
return WireFormatLite::ReadBytes(input, value);
}
-#define READ_METHOD(FieldType) \
- template <> \
- template <typename ValueType> \
- inline bool MapProtoTypeHandler<FieldDescriptor::TYPE_##FieldType>::Read( \
- io::CodedInputStream* input, ValueType* value) { \
- return WireFormatLite::ReadPrimitive<CppType, \
- WireFormatLite::TYPE_##FieldType>( \
- input, value); \
+#define READ_METHOD(FieldType) \
+ template <> \
+ template <typename ValueType> \
+ inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Read( \
+ io::CodedInputStream* input, ValueType* value) { \
+ return WireFormatLite::ReadPrimitive<CppType, \
+ WireFormatLite::TYPE_##FieldType>( \
+ input, value); \
}
READ_METHOD(INT64)
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index 9232d58f..830f672b 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -30,6 +30,7 @@
syntax = "proto3";
+option cc_enable_arenas = true;
import "google/protobuf/unittest.proto";
@@ -59,6 +60,10 @@ message TestMap {
map<int32 , ForeignMessage> map_int32_foreign_message = 17;
}
+message TestMapSubmessage {
+ optional TestMap test_map = 1;
+}
+
message TestMessageMap {
map<int32, TestAllTypes> map_int32_message = 1;
}
@@ -80,3 +85,21 @@ enum MapEnum {
message TestRequiredMessageMap {
map<int32, TestRequired> map_field = 1;
}
+
+message TestArenaMap {
+ map<int32 , int32 > map_int32_int32 = 1;
+ map<int64 , int64 > map_int64_int64 = 2;
+ map<uint32 , uint32 > map_uint32_uint32 = 3;
+ map<uint64 , uint64 > map_uint64_uint64 = 4;
+ map<sint32 , sint32 > map_sint32_sint32 = 5;
+ map<sint64 , sint64 > map_sint64_sint64 = 6;
+ map<fixed32 , fixed32 > map_fixed32_fixed32 = 7;
+ map<fixed64 , fixed64 > map_fixed64_fixed64 = 8;
+ map<sfixed32, sfixed32> map_sfixed32_sfixed32 = 9;
+ map<sfixed64, sfixed64> map_sfixed64_sfixed64 = 10;
+ map<int32 , float > map_int32_float = 11;
+ map<int32 , double > map_int32_double = 12;
+ map<bool , bool > map_bool_bool = 13;
+ map<int32 , MapEnum > map_int32_enum = 14;
+ map<int32 , ForeignMessage> map_int32_foreign_message = 15;
+}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index afe95461..f58be848 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -441,6 +441,30 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
}
namespace internal {
+namespace {
+void ShutdownRepeatedFieldAccessor() {
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int32> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint32> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<int64> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<uint64> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<float> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<double> >::ShutDown();
+ internal::Singleton<internal::RepeatedFieldPrimitiveAccessor<bool> >::ShutDown();
+ internal::Singleton<internal::RepeatedPtrFieldStringAccessor>::ShutDown();
+ internal::Singleton<internal::RepeatedPtrFieldMessageAccessor>::ShutDown();
+ internal::Singleton<internal::MapFieldAccessor>::ShutDown();
+}
+
+struct ShutdownRepeatedFieldRegister {
+ ShutdownRepeatedFieldRegister() {
+ OnShutdown(&ShutdownRepeatedFieldAccessor);
+ }
+} shutdown_;
+
+} // namespace
+} // 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.
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index a200bc92..6e1929e5 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -208,7 +208,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite {
// This is much, much slower than IsInitialized() as it is implemented
// purely via reflection. Generally, you should not call this unless you
// have already determined that an error exists by calling IsInitialized().
- void FindInitializationErrors(vector<string>* errors) const;
+ void FindInitializationErrors(std::vector<string>* errors) const;
// Like FindInitializationErrors, but joins all the strings, delimited by
// commas, and returns them.
@@ -456,7 +456,7 @@ class LIBPROTOBUF_EXPORT Reflection {
// Swap fields listed in fields vector of two messages.
virtual void SwapFields(Message* message1,
Message* message2,
- const vector<const FieldDescriptor*>& fields)
+ const std::vector<const FieldDescriptor*>& fields)
const = 0;
// Swap two elements of a repeated field.
@@ -470,8 +470,9 @@ class LIBPROTOBUF_EXPORT Reflection {
// return true and repeated fields will only be listed if FieldSize(field)
// would return non-zero. Fields (both normal fields and extension fields)
// will be listed ordered by field number.
- virtual void ListFields(const Message& message,
- vector<const FieldDescriptor*>* output) const = 0;
+ virtual void ListFields(
+ const Message& message,
+ std::vector<const FieldDescriptor*>* output) const = 0;
// Singular field getters ------------------------------------------
// These get the value of a non-repeated field. They return the default
@@ -523,7 +524,7 @@ class LIBPROTOBUF_EXPORT Reflection {
// regardless of the field's underlying representation. When initializing
// a newly-constructed string, though, it's just as fast and more readable
// to use code like:
- // string str = reflection->GetString(field);
+ // string str = reflection->GetString(message, field);
virtual const string& GetStringReference(const Message& message,
const FieldDescriptor* field,
string* scratch) const = 0;
@@ -842,6 +843,19 @@ class LIBPROTOBUF_EXPORT Reflection {
// }
virtual bool SupportsUnknownEnumValues() const { return false; }
+ // Returns the MessageFactory associated with this message. This can be
+ // useful for determining if a message is a generated message or not, for
+ // example:
+ //
+ // if (message->GetReflection()->GetMessageFactory() ==
+ // google::protobuf::MessageFactory::generated_factory()) {
+ // // This is a generated message.
+ // }
+ //
+ // It can also be used to create more messages of this type, though
+ // Message::New() is an easier way to accomplish this.
+ virtual MessageFactory* GetMessageFactory() const;
+
// ---------------------------------------------------------------------------
protected:
@@ -854,8 +868,6 @@ class LIBPROTOBUF_EXPORT Reflection {
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
int ctype, const Descriptor* message_type) const = 0;
- virtual MessageFactory* GetMessageFactory() const;
-
// The following methods are used to implement (Mutable)RepeatedFieldRef.
// A Ref object will store a raw pointer to the repeated field data (obtained
// from RepeatedFieldData()) and a pointer to a Accessor (obtained from
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 106982cc..eab61c14 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -41,6 +41,7 @@
#include <google/protobuf/stubs/common.h>
+
namespace google {
namespace protobuf {
class Arena;
@@ -133,9 +134,10 @@ class LIBPROTOBUF_EXPORT MessageLite {
// just simple wrappers around MergeFromCodedStream(). Clear() will be called
// before merging the input.
- // Fill the message with a protocol buffer parsed from the given input
- // stream. Returns false on a read error or if the input is in the
- // wrong format.
+ // Fill the message with a protocol buffer parsed from the given input stream.
+ // Returns false on a read error or if the input is in the wrong format. A
+ // successful return does not indicate the entire input is consumed, ensure
+ // you call ConsumedEntireMessage() to check that if applicable.
bool ParseFromCodedStream(io::CodedInputStream* input);
// Like ParseFromCodedStream(), but accepts messages that are missing
// required fields.
@@ -154,7 +156,11 @@ class LIBPROTOBUF_EXPORT MessageLite {
// missing required fields.
bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input,
int size);
- // Parse a protocol buffer contained in a string.
+ // Parses a protocol buffer contained in a string. Returns true on success.
+ // This function takes a string in the (non-human-readable) binary wire
+ // format, matching the encoding output by MessageLite::SerializeToString().
+ // If you'd like to convert a human-readable string into a protocol buffer
+ // object, see google::protobuf::TextFormat::ParseFromString().
bool ParseFromString(const string& data);
// Like ParseFromString(), but accepts messages that are missing
// required fields.
diff --git a/src/google/protobuf/new_delete_capture.cc b/src/google/protobuf/new_delete_capture.cc
deleted file mode 100644
index baf42ffe..00000000
--- a/src/google/protobuf/new_delete_capture.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file exists for testing allocation behavior when using arenas by hooking
-// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.cc.
-
-#include <google/protobuf/new_delete_capture.h>
-
-#include <pthread.h>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/malloc_hook.h>
-#include <google/protobuf/stubs/spinlock.h>
-
-namespace google {
-namespace {
-
-pthread_t gthread;
-protobuf_unittest::NewDeleteCapture *ghooked_instance = NULL;
-SpinLock gspinlock(base::LINKER_INITIALIZED);
-
-} // namespace
-
-namespace protobuf_unittest {
-
-NewDeleteCapture::NewDeleteCapture()
- : alloc_count_(0),
- alloc_size_(0),
- alloc_ptr_(NULL),
- free_count_(0),
- free_ptr_(NULL) {}
-
-NewDeleteCapture::~NewDeleteCapture() { Unhook(); }
-
-void NewDeleteCapture::Reset() {
- alloc_count_ = 0;
- alloc_size_ = 0;
- free_count_ = 0;
- alloc_ptr_ = NULL;
- free_ptr_ = NULL;
-}
-
-bool NewDeleteCapture::Hook(bool reset) {
- SpinLockHolder spinlock(&gspinlock);
- if (ghooked_instance != this) {
- GOOGLE_CHECK(ghooked_instance == NULL)
- << " NewDeleteCapture can have only 1 active instance";
- GOOGLE_CHECK(MallocHook::AddNewHook(NewHook));
- GOOGLE_CHECK(MallocHook::AddDeleteHook(DeleteHook));
- gthread = pthread_self();
- ghooked_instance = this;
- if (reset) {
- Reset();
- }
- return true;
- }
- return false;
-}
-
-bool NewDeleteCapture::Unhook() {
- SpinLockHolder spinlock(&gspinlock);
- if (ghooked_instance == this) {
- gthread = pthread_t();
- ghooked_instance = NULL;
- GOOGLE_CHECK(MallocHook::RemoveDeleteHook(DeleteHook));
- GOOGLE_CHECK(MallocHook::RemoveNewHook(NewHook));
- return true;
- }
- return false;
-}
-
-void NewDeleteCapture::NewHook(const void *ptr, size_t size) {
- SpinLockHolder spinlock(&gspinlock);
- if (gthread == pthread_self()) {
- auto &rthis = *ghooked_instance;
- if (++rthis.alloc_count_ == 1) {
- rthis.alloc_size_ = size;
- rthis.alloc_ptr_ = ptr;
- }
- }
-}
-
-void NewDeleteCapture::DeleteHook(const void *ptr) {
- SpinLockHolder spinlock(&gspinlock);
- if (gthread == pthread_self()) {
- auto &rthis = *ghooked_instance;
- if (++rthis.free_count_ == 1) {
- rthis.free_ptr_ = ptr;
- }
- }
-}
-
-} // namespace protobuf_unittest
-} // namespace google
diff --git a/src/google/protobuf/new_delete_capture.h b/src/google/protobuf/new_delete_capture.h
deleted file mode 100644
index 4ab550cd..00000000
--- a/src/google/protobuf/new_delete_capture.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This file exists for testing allocation behavior when using arenas by hooking
-// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.h.
-//
-// Copyright 2014 Google Inc.
-//
-// Author: Martijn Vels
-//
-// A simple class that captures memory allocations and deletes.
-//
-// This class is private to //strings and only intended to be used inside
-// unit tests. It uses the MallocHook functionality to capture memory
-// allocation and delete operations performed by the thread that activated
-// a hook on a specific instance.
-//
-// The class captures the following information:
-// - Total allocation count (new, malloc(), etc).
-// - Total delete count (delete, free(), etc).
-// - The size and returned pointer for the first memory allocation.
-// - The pointer for the first delete operation.
-//
-// The latter 2 infos (size and pointer of first new/delete) are usefull in
-// cases where you can closely scope a Hook() / Unhook sequence around a
-// specific piece of code where you expect no more than 1 pair of new / delete
-// operations.
-//
-// Sample usage where we expect a single unique alloc / free:
-//
-// NewDeleteCapture capture_alloc;
-// const void *ptr;
-// {
-// capture_alloc.Hook();
-// MyAllocationClass my_instance(size);
-// capture_alloc.Unhook();
-//
-// ptr = my_instance.ptr();
-// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
-// GOOGLE_CHECK_EQ(0, capture_alloc.free_count());
-// GOOGLE_CHECK_EQ(size, capture_alloc.alloc_size());
-// GOOGLE_CHECK_EQ(ptr, capture_alloc.alloc_ptr());
-//
-// capture_alloc.Hook();
-// }
-// capture_alloc.Unhook();
-// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count());
-// GOOGLE_CHECK_EQ(1, capture_alloc.free_count());
-// GOOGLE_CHECK_EQ(ptr, capture_alloc.free_ptr());
-//
-// You can only have one NewDeleteCapture instance active at the time. It is
-// total valid to have many instances in different threads, but only one
-// instance can have a hook active.
-//
-// Legal:
-//
-// NewDeleteCapture capture_alloc1;
-// NewDeleteCapture capture_alloc2;
-// const void *ptr;
-// {
-// capture_alloc1.Hook();
-// MyAllocationClass my_instance(size);
-// capture_alloc1.Unhook();
-//
-// capture_alloc2.Hook();
-// my_instance.reset(size);
-// capture_alloc2.Unhook();
-// }
-//
-// Illegal:
-//
-// NewDeleteCapture capture_alloc1;
-// NewDeleteCapture capture_alloc2;
-// const void *ptr;
-// {
-// capture_alloc1.Hook();
-// MyAllocationClass my_instance(size);
-//
-// capture_alloc2.Hook();
-// my_instance.reset(size);
-//
-// capture_alloc1.Unhook();
-// capture_alloc2.Unhook();
-// }
-//
-#ifndef GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
-#define GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
-
-#include <stddef.h>
-
-namespace google {
-namespace protobuf_unittest {
-
-class NewDeleteCapture {
- public:
- // Creates a new inactive capture instance
- NewDeleteCapture();
-
- // Destroys this capture instance. Active hooks are automatically removed.
- ~NewDeleteCapture();
-
- // Activates a hook on this instance. If reset is true (the default), all
- // internal counters will be reset to 0.
- // Returns true if the hook was activated, false if this instance already
- // owned the hook.
- // Requires no other instance owning the hook (check fails)
- bool Hook(bool reset = true);
-
- // De-activate the hook on this instance.
- // Returns true if the hook was removed, false if this instance did not own
- // the hook.
- bool Unhook();
-
- // Resets all counters to 0
- void Reset();
-
- // Returns the total number of allocations (new, malloc(), etc)
- size_t alloc_count() const { return alloc_count_; }
-
- // Returns the total number of deletes (delete, free(), etc)
- size_t free_count() const { return free_count_; }
-
- // Returns the size of the first observed allocation
- size_t alloc_size() const { return alloc_size_; }
-
- // Returns the allocated ptr of the first observed allocation
- const void *alloc_ptr() const { return alloc_ptr_; }
-
- // Returns the ptr of the first observed delete
- const void* free_ptr() const { return free_ptr_; }
-
- private:
- static void NewHook(const void *ptr, size_t size);
- static void DeleteHook(const void *ptr);
-
- private:
- size_t alloc_count_;
- size_t alloc_size_;
- const void *alloc_ptr_;
-
- size_t free_count_;
- const void *free_ptr_;
-};
-
-} // namespace protobuf_unittest
-
-} // namespace google
-#endif // GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 816e52ca..9f8703ae 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -30,6 +30,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_preserve_unknown_enum.pb.h>
+#include <google/protobuf/unittest_preserve_unknown_enum2.pb.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/descriptor.h>
#include <gtest/gtest.h>
@@ -39,46 +40,55 @@ namespace protobuf {
namespace {
void FillMessage(
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) {
message->set_e(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
message->add_repeated_e(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
message->add_repeated_packed_e(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
+ message->add_repeated_packed_unexpected_e(
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
message->set_oneof_e_1(
- proto2_preserve_unknown_enum_unittest::E_EXTRA);
+ proto3_preserve_unknown_enum_unittest::E_EXTRA);
}
void CheckMessage(
- const proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) {
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.e());
EXPECT_EQ(1, message.repeated_e_size());
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.repeated_e(0));
EXPECT_EQ(1, message.repeated_packed_e_size());
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.repeated_packed_e(0));
- EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA,
+ EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
+ message.repeated_packed_unexpected_e(0));
+ EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA,
message.oneof_e_1());
}
void CheckMessage(
- const proto2_preserve_unknown_enum_unittest::MyMessage& message) {
+ const proto3_preserve_unknown_enum_unittest::MyMessage& message) {
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.e()));
EXPECT_EQ(1, message.repeated_e_size());
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.repeated_e(0)));
EXPECT_EQ(1, message.repeated_packed_e_size());
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.repeated_packed_e(0)));
+ EXPECT_EQ(1, message.repeated_packed_unexpected_e_size());
EXPECT_EQ(static_cast<int>(
- proto2_preserve_unknown_enum_unittest::E_EXTRA),
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
+ static_cast<int>(message.repeated_packed_unexpected_e(0)));
+ EXPECT_EQ(static_cast<int>(
+ proto3_preserve_unknown_enum_unittest::E_EXTRA),
static_cast<int>(message.oneof_e_1()));
}
@@ -87,12 +97,12 @@ void CheckMessage(
// Test that parsing preserves an unknown value in the enum field and does not
// punt it to the UnknownFieldSet.
TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) {
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
FillMessage(&orig_message);
string serialized;
orig_message.SerializeToString(&serialized);
- proto2_preserve_unknown_enum_unittest::MyMessage message;
+ proto3_preserve_unknown_enum_unittest::MyMessage message;
EXPECT_EQ(true, message.ParseFromString(serialized));
CheckMessage(message);
@@ -105,13 +115,13 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) {
// Test that reflection based implementation also keeps unknown enum values and
// doesn't put them into UnknownFieldSet.
TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
FillMessage(&orig_message);
string serialized = orig_message.SerializeAsString();
google::protobuf::DynamicMessageFactory factory;
google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
- proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+ proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
EXPECT_EQ(true, message->ParseFromString(serialized));
message->DiscardUnknownFields();
@@ -120,14 +130,61 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) {
CheckMessage(orig_message);
}
+// Test that for proto2 messages, unknown values are in unknown fields.
+TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) {
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ FillMessage(&orig_message);
+
+ string serialized;
+ orig_message.SerializeToString(&serialized);
+
+ proto2_preserve_unknown_enum_unittest::MyMessage message;
+ EXPECT_EQ(true, message.ParseFromString(serialized));
+ // The intermediate message has everything in its "unknown fields".
+ proto2_preserve_unknown_enum_unittest::MyMessage message2 = message;
+ message2.DiscardUnknownFields();
+ EXPECT_EQ(0, message2.ByteSize());
+
+ // But when we pass it to the correct structure, all values are there.
+ serialized.clear();
+ message.SerializeToString(&serialized);
+ EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+ CheckMessage(orig_message);
+}
+
+// Same as before, for a dynamic message.
+TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) {
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ FillMessage(&orig_message);
+
+ string serialized;
+ orig_message.SerializeToString(&serialized);
+
+ google::protobuf::DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<google::protobuf::Message> message(factory.GetPrototype(
+ proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New());
+ EXPECT_EQ(true, message->ParseFromString(serialized));
+ // The intermediate message has everything in its "unknown fields".
+ proto2_preserve_unknown_enum_unittest::MyMessage message2;
+ message2.CopyFrom(*message);
+ message2.DiscardUnknownFields();
+ EXPECT_EQ(0, message2.ByteSize());
+
+ // But when we pass it to the correct structure, all values are there.
+ serialized.clear();
+ message->SerializeToString(&serialized);
+ EXPECT_EQ(true, orig_message.ParseFromString(serialized));
+ CheckMessage(orig_message);
+}
+
// Test that reflection provides EnumValueDescriptors for unknown values.
TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
- proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
+ proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message;
FillMessage(&orig_message);
string serialized;
orig_message.SerializeToString(&serialized);
- proto2_preserve_unknown_enum_unittest::MyMessage message;
+ proto3_preserve_unknown_enum_unittest::MyMessage message;
EXPECT_EQ(true, message.ParseFromString(serialized));
CheckMessage(message);
@@ -138,7 +195,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
// This should dynamically create an EnumValueDescriptor.
const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field);
EXPECT_EQ(enum_value->number(),
- static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+ static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
// Fetching value for a second time should return the same pointer.
const google::protobuf::EnumValueDescriptor* enum_value_second =
@@ -150,7 +207,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
d->FindFieldByName("repeated_e");
enum_value = r->GetRepeatedEnum(message, repeated_field, 0);
EXPECT_EQ(enum_value->number(),
- static_cast<int>(proto2_preserve_unknown_enum_unittest::E_EXTRA));
+ static_cast<int>(proto3_preserve_unknown_enum_unittest::E_EXTRA));
// Should reuse the same EnumValueDescriptor, even for a different field.
EXPECT_EQ(enum_value, enum_value_second);
@@ -164,7 +221,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) {
// Test that the new integer-based enum reflection API works.
TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) {
- proto2_preserve_unknown_enum_unittest::MyMessage message;
+ proto3_preserve_unknown_enum_unittest::MyMessage message;
const google::protobuf::Reflection* r = message.GetReflection();
const google::protobuf::Descriptor* d = message.GetDescriptor();
@@ -220,7 +277,7 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) {
protobuf_unittest::TestAllTypes proto2_message;
- proto2_preserve_unknown_enum_unittest::MyMessage new_message;
+ proto3_preserve_unknown_enum_unittest::MyMessage new_message;
const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection();
const google::protobuf::Reflection* new_reflection = new_message.GetReflection();
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index 17d89a18..03c761c1 100644..100755
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -33,6 +33,11 @@
#ifndef GOOGLE_PROTOBUF_REFLECTION_H__
#define GOOGLE_PROTOBUF_REFLECTION_H__
+#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
#include <google/protobuf/message.h>
namespace google {
@@ -223,7 +228,7 @@ class RepeatedFieldRef<
const Message* default_instance_;
};
-// MutableRepeatedFieldRef definition for non-message types.
+// MutableRepeatedFieldRef definition for message types.
template<typename T>
class MutableRepeatedFieldRef<
T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
@@ -297,10 +302,298 @@ class MutableRepeatedFieldRef<
const AccessorType* accessor_;
const Message* default_instance_;
};
+
+namespace internal {
+// Interfaces used to implement reflection RepeatedFieldRef API.
+// Reflection::GetRepeatedAccessor() should return a pointer to an singleton
+// object that implements the below interface.
+//
+// This interface passes/returns values using void pointers. The actual type
+// of the value depends on the field's cpp_type. Following is a mapping from
+// cpp_type to the type that should be used in this interface:
+//
+// field->cpp_type() T Actual type of void*
+// CPPTYPE_INT32 int32 int32
+// CPPTYPE_UINT32 uint32 uint32
+// CPPTYPE_INT64 int64 int64
+// CPPTYPE_UINT64 uint64 uint64
+// CPPTYPE_DOUBLE double double
+// CPPTYPE_FLOAT float float
+// CPPTYPE_BOOL bool bool
+// CPPTYPE_ENUM generated enum type int32
+// CPPTYPE_STRING string string
+// CPPTYPE_MESSAGE generated message type google::protobuf::Message
+// or google::protobuf::Message
+//
+// Note that for enums we use int32 in the interface.
+//
+// You can map from T to the actual type using RefTypeTraits:
+// typedef RefTypeTraits<T>::AccessorValueType ActualType;
+class LIBPROTOBUF_EXPORT RepeatedFieldAccessor {
+ public:
+ // Typedefs for clarity.
+ typedef void Field;
+ typedef void Value;
+ typedef void Iterator;
+
+ virtual ~RepeatedFieldAccessor();
+ virtual bool IsEmpty(const Field* data) const = 0;
+ virtual int Size(const Field* data) const = 0;
+ // Depends on the underlying representation of the repeated field, this
+ // method can return a pointer to the underlying object if such an object
+ // exists, or fill the data into scratch_space and return scratch_space.
+ // Callers of this method must ensure scratch_space is a valid pointer
+ // to a mutable object of the correct type.
+ virtual const Value* Get(
+ const Field* data, int index, Value* scratch_space) const = 0;
+
+ virtual void Clear(Field* data) const = 0;
+ virtual void Set(Field* data, int index, const Value* value) const = 0;
+ virtual void Add(Field* data, const Value* value) const = 0;
+ virtual void RemoveLast(Field* data) const = 0;
+ virtual void SwapElements(Field* data, int index1, int index2) const = 0;
+ virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator,
+ Field* other_data) const = 0;
+
+ // Create an iterator that points at the begining of the repeated field.
+ virtual Iterator* BeginIterator(const Field* data) const = 0;
+ // Create an iterator that points at the end of the repeated field.
+ virtual Iterator* EndIterator(const Field* data) const = 0;
+ // Make a copy of an iterator and return the new copy.
+ virtual Iterator* CopyIterator(const Field* data,
+ const Iterator* iterator) const = 0;
+ // Move an iterator to point to the next element.
+ virtual Iterator* AdvanceIterator(const Field* data,
+ Iterator* iterator) const = 0;
+ // Compare whether two iterators point to the same element.
+ virtual bool EqualsIterator(const Field* data, const Iterator* a,
+ const Iterator* b) const = 0;
+ // Delete an iterator created by BeginIterator(), EndIterator() and
+ // CopyIterator().
+ virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0;
+ // Like Get() but for iterators.
+ virtual const Value* GetIteratorValue(const Field* data,
+ const Iterator* iterator,
+ Value* scratch_space) const = 0;
+
+ // Templated methods that make using this interface easier for non-message
+ // types.
+ template<typename T>
+ T Get(const Field* data, int index) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ ActualType scratch_space;
+ return static_cast<T>(
+ *reinterpret_cast<const ActualType*>(
+ Get(data, index, static_cast<Value*>(&scratch_space))));
+ }
+
+ template<typename T, typename ValueType>
+ void Set(Field* data, int index, const ValueType& value) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ // In this RepeatedFieldAccessor interface we pass/return data using
+ // raw pointers. Type of the data these raw pointers point to should
+ // be ActualType. Here we have a ValueType object and want a ActualType
+ // pointer. We can't cast a ValueType pointer to an ActualType pointer
+ // directly because their type might be different (for enums ValueType
+ // may be a generated enum type while ActualType is int32). To be safe
+ // we make a copy to get a temporary ActualType object and use it.
+ ActualType tmp = static_cast<ActualType>(value);
+ Set(data, index, static_cast<const Value*>(&tmp));
+ }
+
+ template<typename T, typename ValueType>
+ void Add(Field* data, const ValueType& value) const {
+ typedef typename RefTypeTraits<T>::AccessorValueType ActualType;
+ // In this RepeatedFieldAccessor interface we pass/return data using
+ // raw pointers. Type of the data these raw pointers point to should
+ // be ActualType. Here we have a ValueType object and want a ActualType
+ // pointer. We can't cast a ValueType pointer to an ActualType pointer
+ // directly because their type might be different (for enums ValueType
+ // may be a generated enum type while ActualType is int32). To be safe
+ // we make a copy to get a temporary ActualType object and use it.
+ ActualType tmp = static_cast<ActualType>(value);
+ Add(data, static_cast<const Value*>(&tmp));
+ }
+};
+
+// Implement (Mutable)RepeatedFieldRef::iterator
+template<typename T>
+class RepeatedFieldRefIterator
+ : public std::iterator<std::forward_iterator_tag, T> {
+ typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType;
+ typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType;
+ typedef typename RefTypeTraits<T>::IteratorPointerType IteratorPointerType;
+
+ public:
+ // Constructor for non-message fields.
+ RepeatedFieldRefIterator(const void* data,
+ const RepeatedFieldAccessor* accessor,
+ bool begin)
+ : data_(data), accessor_(accessor),
+ iterator_(begin ? accessor->BeginIterator(data) :
+ accessor->EndIterator(data)),
+ scratch_space_(new AccessorValueType) {
+ }
+ // Constructor for message fields.
+ RepeatedFieldRefIterator(const void* data,
+ const RepeatedFieldAccessor* accessor,
+ bool begin,
+ AccessorValueType* scratch_space)
+ : data_(data), accessor_(accessor),
+ iterator_(begin ? accessor->BeginIterator(data) :
+ accessor->EndIterator(data)),
+ scratch_space_(scratch_space) {
+ }
+ ~RepeatedFieldRefIterator() {
+ accessor_->DeleteIterator(data_, iterator_);
+ }
+ RepeatedFieldRefIterator operator++(int) {
+ RepeatedFieldRefIterator tmp(*this);
+ iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+ return tmp;
+ }
+ RepeatedFieldRefIterator& operator++() {
+ iterator_ = accessor_->AdvanceIterator(data_, iterator_);
+ return *this;
+ }
+ IteratorValueType operator*() const {
+ return static_cast<IteratorValueType>(
+ *static_cast<const AccessorValueType*>(
+ accessor_->GetIteratorValue(
+ data_, iterator_, scratch_space_.get())));
+ }
+ IteratorPointerType operator->() const {
+ return static_cast<IteratorPointerType>(
+ accessor_->GetIteratorValue(
+ data_, iterator_, scratch_space_.get()));
+ }
+ bool operator!=(const RepeatedFieldRefIterator& other) const {
+ assert(data_ == other.data_);
+ assert(accessor_ == other.accessor_);
+ return !accessor_->EqualsIterator(data_, iterator_, other.iterator_);
+ }
+ bool operator==(const RepeatedFieldRefIterator& other) const {
+ return !this->operator!=(other);
+ }
+
+ RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other)
+ : data_(other.data_), accessor_(other.accessor_),
+ iterator_(accessor_->CopyIterator(data_, other.iterator_)) {
+ }
+ RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) {
+ if (this != &other) {
+ accessor_->DeleteIterator(data_, iterator_);
+ data_ = other.data_;
+ accessor_ = other.accessor_;
+ iterator_ = accessor_->CopyIterator(data_, other.iterator_);
+ }
+ return *this;
+ }
+
+ protected:
+ const void* data_;
+ const RepeatedFieldAccessor* accessor_;
+ void* iterator_;
+ google::protobuf::scoped_ptr<AccessorValueType> scratch_space_;
+};
+
+// TypeTraits that maps the type parameter T of RepeatedFieldRef or
+// MutableRepeatedFieldRef to corresponding iterator type,
+// RepeatedFieldAccessor type, etc.
+template<typename T>
+struct PrimitiveTraits {
+ static const bool is_primitive = false;
+};
+#define DEFINE_PRIMITIVE(TYPE, type) \
+ template<> struct PrimitiveTraits<type> { \
+ static const bool is_primitive = true; \
+ static const FieldDescriptor::CppType cpp_type = \
+ FieldDescriptor::CPPTYPE_ ## TYPE; \
+ };
+DEFINE_PRIMITIVE(INT32, int32)
+DEFINE_PRIMITIVE(UINT32, uint32)
+DEFINE_PRIMITIVE(INT64, int64)
+DEFINE_PRIMITIVE(UINT64, uint64)
+DEFINE_PRIMITIVE(FLOAT, float)
+DEFINE_PRIMITIVE(DOUBLE, double)
+DEFINE_PRIMITIVE(BOOL, bool)
+#undef DEFINE_PRIMITIVE
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef T AccessorValueType;
+ typedef T IteratorValueType;
+ typedef T* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ PrimitiveTraits<T>::cpp_type;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<is_proto_enum<T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ // We use int32 for repeated enums in RepeatedFieldAccessor.
+ typedef int32 AccessorValueType;
+ typedef T IteratorValueType;
+ typedef int32* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_ENUM;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef string AccessorValueType;
+ typedef string IteratorValueType;
+ typedef string* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_STRING;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct MessageDescriptorGetter {
+ static const Descriptor* get() {
+ return T::default_instance().GetDescriptor();
+ }
+};
+template<>
+struct MessageDescriptorGetter<Message> {
+ static const Descriptor* get() {
+ return NULL;
+ }
+};
+
+template<typename T>
+struct RefTypeTraits<
+ T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> {
+ typedef RepeatedFieldRefIterator<T> iterator;
+ typedef RepeatedFieldAccessor AccessorType;
+ typedef Message AccessorValueType;
+ typedef const T& IteratorValueType;
+ typedef const T* IteratorPointerType;
+ static const FieldDescriptor::CppType cpp_type =
+ FieldDescriptor::CPPTYPE_MESSAGE;
+ static const Descriptor* GetMessageFieldDescriptor() {
+ return MessageDescriptorGetter<T>::get();
+ }
+};
+} // namespace internal
} // namespace protobuf
} // namespace google
-// Implementation details for (Mutable)RepeatedFieldRef.
-#include <google/protobuf/repeated_field_reflection.h>
-
#endif // GOOGLE_PROTOBUF_REFLECTION_H__
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 4798eeda..f5f5d3f4 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -2264,7 +2264,7 @@ RepeatedPtrField<Element>::pointer_end() const {
// Iterators and helper functions that follow the spirit of the STL
// std::back_insert_iterator and std::back_inserter but are tailor-made
-// for RepeatedField and RepatedPtrField. Typical usage would be:
+// for RepeatedField and RepeatedPtrField. Typical usage would be:
//
// std::copy(some_sequence.begin(), some_sequence.end(),
// google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence()));
diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc
index 8b821806..fcebe5ce 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.cc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -410,6 +410,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
EXPECT_TRUE(mrf_message.empty());
#ifdef PROTOBUF_HAS_DEATH_TEST
+
// Make sure types are checked correctly at runtime.
const FieldDescriptor* fd_optional_int32 =
desc->FindFieldByName("optional_int32");
@@ -419,6 +420,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
message, fd_repeated_int32), "");
EXPECT_DEATH(refl->GetRepeatedFieldRef<TestAllTypes>(
message, fd_repeated_foreign_message), "");
+
#endif // PROTOBUF_HAS_DEATH_TEST
}
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 15c0c93e..66e74523 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -1131,7 +1131,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) {
string v = "f";
RepeatedPtrField<string>::const_iterator it =
- lower_bound(proto_array_.begin(), proto_array_.end(), v);
+ std::lower_bound(proto_array_.begin(), proto_array_.end(), v);
EXPECT_EQ(*it, "n");
EXPECT_TRUE(it == proto_array_.begin() + 3);
@@ -1292,8 +1292,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
{
string v = "f";
RepeatedPtrField<string>::pointer_iterator it =
- lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(),
- &v, StringLessThan());
+ std::lower_bound(proto_array_.pointer_begin(),
+ proto_array_.pointer_end(), &v, StringLessThan());
GOOGLE_CHECK(*it != NULL);
@@ -1302,10 +1302,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) {
}
{
string v = "f";
- RepeatedPtrField<string>::const_pointer_iterator it =
- lower_bound(const_proto_array_->pointer_begin(),
- const_proto_array_->pointer_end(),
- &v, StringLessThan());
+ RepeatedPtrField<string>::const_pointer_iterator it = std::lower_bound(
+ const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(),
+ &v, StringLessThan());
GOOGLE_CHECK(*it != NULL);
@@ -1343,9 +1342,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) {
EXPECT_EQ("foo", proto_array_.Get(0));
EXPECT_EQ("n", proto_array_.Get(5));
EXPECT_EQ("x", proto_array_.Get(9));
- sort(proto_array_.pointer_begin(),
- proto_array_.pointer_end(),
- StringLessThan());
+ std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(),
+ StringLessThan());
EXPECT_EQ("a", proto_array_.Get(0));
EXPECT_EQ("baz", proto_array_.Get(2));
EXPECT_EQ("y", proto_array_.Get(9));
@@ -1478,9 +1476,9 @@ TEST_F(RepeatedFieldInsertionIteratorsTest,
new_data->set_bb(i);
}
TestAllTypes testproto;
- copy(data.begin(), data.end(),
- AllocatedRepeatedPtrFieldBackInserter(
- testproto.mutable_repeated_nested_message()));
+ std::copy(data.begin(), data.end(),
+ AllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_nested_message()));
EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
}
@@ -1497,9 +1495,8 @@ TEST_F(RepeatedFieldInsertionIteratorsTest,
*new_data = "name-" + SimpleItoa(i);
}
TestAllTypes testproto;
- copy(data.begin(), data.end(),
- AllocatedRepeatedPtrFieldBackInserter(
- testproto.mutable_repeated_string()));
+ std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter(
+ testproto.mutable_repeated_string()));
EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
}
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
new file mode 100644
index 00000000..9f27eb43
--- /dev/null
+++ b/src/google/protobuf/struct.proto
@@ -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.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "StructProto";
+option java_package = "com.google.protobuf";
+
+
+// `Struct` represents a structured data value, consisting of fields
+// which map to dynamically typed values. In some languages, `Struct`
+// might be supported by a native representation. For example, in
+// scripting languages like JS a struct is represented as an
+// object. The details of that representation are described together
+// with the proto support for the language.
+message Struct {
+ // Map of dynamically typed values.
+ map<string, Value> fields = 1;
+}
+
+// `Value` represents a dynamically typed value which can be either
+// null, a number, a string, a boolean, a recursive struct value, or a
+// list of values. A producer of value is expected to set one of that
+// variants, absence of any variant indicates an error.
+message Value {
+ oneof kind {
+ // Represents a null value.
+ NullValue null_value = 1;
+ // Represents a double value.
+ double number_value = 2;
+ // Represents a string value.
+ string string_value = 3;
+ // Represents a boolean value.
+ bool bool_value = 4;
+ // Represents a structured value.
+ Struct struct_value = 5;
+ // Represents a repeated `Value`.
+ ListValue list_value = 6;
+ }
+}
+
+// `NullValue` is a singleton enumeration to represent the null
+// value for the `Value` type union.
+enum NullValue {
+ // Null value.
+ NULL_VALUE = 0;
+}
+
+// `ListValue` is a wrapper around a repeated field of values.
+message ListValue {
+ // Repeated field of dynamically typed values.
+ repeated Value values = 1;
+}
diff --git a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
index e3cd14cf..f5837c9e 100644
--- a/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
+++ b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
@@ -65,7 +65,7 @@ inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
"2:\n"
".set pop\n"
: "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
- : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+ : "r" (old_value), "r" (new_value), "m" (*ptr)
: "memory");
return prev;
}
@@ -197,7 +197,7 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
"2:\n"
".set pop\n"
: "=&r" (prev), "=m" (*ptr), "=&r" (tmp)
- : "Ir" (old_value), "r" (new_value), "m" (*ptr)
+ : "r" (old_value), "r" (new_value), "m" (*ptr)
: "memory");
return prev;
}
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index 5b6a073d..82d5052e 100644..100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -37,13 +37,14 @@
#include <string.h>
#include <google/protobuf/stubs/common.h>
-#include "config.h"
+#include <google/protobuf/stubs/pbconfig.h>
-#if defined(HAVE_HASH_MAP) && defined(HAVE_HASH_SET)
-#include HASH_MAP_H
-#include HASH_SET_H
+#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \
+ defined(GOOGLE_PROTOBUF_HAVE_HASH_SET)
+#include GOOGLE_PROTOBUF_HASH_MAP_H
+#include GOOGLE_PROTOBUF_HASH_SET_H
#else
-#define MISSING_HASH
+#define GOOGLE_PROTOBUF_MISSING_HASH
#include <map>
#include <set>
#endif
@@ -51,7 +52,7 @@
namespace google {
namespace protobuf {
-#ifdef MISSING_HASH
+#ifdef GOOGLE_PROTOBUF_MISSING_HASH
// This system doesn't have hash_map or hash_set. Emulate them using map and
// set.
@@ -88,15 +89,17 @@ struct hash<const char*> {
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
- typename EqualKey = int >
-class hash_map : public std::map<Key, Data, HashFcn> {
+ typename EqualKey = std::equal_to<Key>,
+ typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map : public std::map<Key, Data, HashFcn, EqualKey, Alloc> {
public:
- hash_map(int = 0) {}
+ hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(),
+ const Alloc& = Alloc()) {}
};
template <typename Key,
typename HashFcn = hash<Key>,
- typename EqualKey = int >
+ typename EqualKey = std::equal_to<Key> >
class hash_set : public std::set<Key, HashFcn> {
public:
hash_set(int = 0) {}
@@ -105,7 +108,7 @@ class hash_set : public std::set<Key, HashFcn> {
#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION)
template <typename Key>
-struct hash : public HASH_NAMESPACE::hash_compare<Key> {
+struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<Key> {
};
// MSVC's hash_compare<const char*> hashes based on the string contents but
@@ -119,23 +122,26 @@ class CstringLess {
template <>
struct hash<const char*>
- : public HASH_NAMESPACE::hash_compare<const char*, CstringLess> {
-};
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare<
+ const char*, CstringLess> {};
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
- typename EqualKey = int >
-class hash_map : public HASH_NAMESPACE::hash_map<
- Key, Data, HashFcn> {
+ typename EqualKey = std::equal_to<Key>,
+ typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+ Key, Data, HashFcn, EqualKey, Alloc> {
public:
- hash_map(int = 0) {}
+ hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(),
+ const Alloc& = Alloc()) {}
};
-template <typename Key,
- typename HashFcn = hash<Key>,
- typename EqualKey = int >
-class hash_set : public HASH_NAMESPACE::hash_set<
- Key, HashFcn> {
+template <typename Key, typename HashFcn = hash<Key>,
+ typename EqualKey = std::equal_to<Key> >
+class hash_set
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+ Key, HashFcn, EqualKey> {
public:
hash_set(int = 0) {}
};
@@ -143,7 +149,7 @@ class hash_set : public HASH_NAMESPACE::hash_set<
#else
template <typename Key>
-struct hash : public HASH_NAMESPACE::hash<Key> {
+struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash<Key> {
};
template <typename Key>
@@ -168,23 +174,27 @@ struct hash<const char*> {
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
- typename EqualKey = std::equal_to<Key> >
-class hash_map : public HASH_NAMESPACE::HASH_MAP_CLASS<
- Key, Data, HashFcn, EqualKey> {
+ typename EqualKey = std::equal_to<Key>,
+ typename Alloc = std::allocator< std::pair<const Key, Data> > >
+class hash_map
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS<
+ Key, Data, HashFcn, EqualKey, Alloc> {
public:
- hash_map(int = 0) {}
+ hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(),
+ const Alloc& = Alloc()) {}
};
-template <typename Key,
- typename HashFcn = hash<Key>,
+template <typename Key, typename HashFcn = hash<Key>,
typename EqualKey = std::equal_to<Key> >
-class hash_set : public HASH_NAMESPACE::HASH_SET_CLASS<
- Key, HashFcn, EqualKey> {
+class hash_set
+ : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS<
+ Key, HashFcn, EqualKey> {
public:
hash_set(int = 0) {}
};
-#endif
+#undef GOOGLE_PROTOBUF_MISSING_HASH
+#endif // !GOOGLE_PROTOBUF_MISSING_HASH
template <>
struct hash<string> {
diff --git a/src/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h
index e123e4fe..9301f549 100644
--- a/src/google/protobuf/stubs/singleton.h
+++ b/src/google/protobuf/stubs/singleton.h
@@ -44,6 +44,10 @@ class Singleton {
GoogleOnceInit(&once_, &Singleton<T>::Init);
return instance_;
}
+ static void ShutDown() {
+ delete instance_;
+ instance_ = NULL;
+ }
private:
static void Init() {
instance_ = new T();
@@ -56,7 +60,7 @@ template<typename T>
ProtobufOnceType Singleton<T>::once_;
template<typename T>
-T* Singleton<T>::instance_;
+T* Singleton<T>::instance_ = NULL;
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 86d45685..7955d261 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -1303,6 +1303,211 @@ string ToHex(uint64 num) {
return string(bufptr, buf + 16 - bufptr);
}
+namespace strings {
+
+AlphaNum::AlphaNum(strings::Hex hex) {
+ char *const end = &digits[kFastToBufferSize];
+ char *writer = end;
+ uint64 value = hex.value;
+ uint64 width = hex.spec;
+ // We accomplish minimum width by OR'ing in 0x10000 to the user's value,
+ // where 0x10000 is the smallest hex number that is as wide as the user
+ // asked for.
+ uint64 mask = ((static_cast<uint64>(1) << (width - 1) * 4)) | value;
+ static const char hexdigits[] = "0123456789abcdef";
+ do {
+ *--writer = hexdigits[value & 0xF];
+ value >>= 4;
+ mask >>= 4;
+ } while (mask != 0);
+ piece_data_ = writer;
+ piece_size_ = end - writer;
+}
+
+} // namespace strings
+
+// ----------------------------------------------------------------------
+// StrCat()
+// This merges the given strings or integers, with no delimiter. This
+// is designed to be the fastest possible way to construct a string out
+// of a mix of raw C strings, C++ strings, and integer values.
+// ----------------------------------------------------------------------
+
+// Append is merely a version of memcpy that returns the address of the byte
+// after the area just overwritten. It comes in multiple flavors to minimize
+// call overhead.
+static char *Append1(char *out, const AlphaNum &x) {
+ memcpy(out, x.data(), x.size());
+ return out + x.size();
+}
+
+static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) {
+ memcpy(out, x1.data(), x1.size());
+ out += x1.size();
+
+ memcpy(out, x2.data(), x2.size());
+ return out + x2.size();
+}
+
+static char *Append4(char *out,
+ const AlphaNum &x1, const AlphaNum &x2,
+ const AlphaNum &x3, const AlphaNum &x4) {
+ memcpy(out, x1.data(), x1.size());
+ out += x1.size();
+
+ memcpy(out, x2.data(), x2.size());
+ out += x2.size();
+
+ memcpy(out, x3.data(), x3.size());
+ out += x3.size();
+
+ memcpy(out, x4.data(), x4.size());
+ return out + x4.size();
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b) {
+ string result;
+ result.resize(a.size() + b.size());
+ char *const begin = &*result.begin();
+ char *out = Append2(begin, a, b);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+ string result;
+ result.resize(a.size() + b.size() + c.size());
+ char *const begin = &*result.begin();
+ char *out = Append2(begin, a, b);
+ out = Append1(out, c);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append1(out, e);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append2(out, e, f);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size() + g.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append2(out, e, f);
+ out = Append1(out, g);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g, const AlphaNum &h) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size() + g.size() + h.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append4(out, e, f, g, h);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) {
+ string result;
+ result.resize(a.size() + b.size() + c.size() + d.size() + e.size() +
+ f.size() + g.size() + h.size() + i.size());
+ char *const begin = &*result.begin();
+ char *out = Append4(begin, a, b, c, d);
+ out = Append4(out, e, f, g, h);
+ out = Append1(out, i);
+ GOOGLE_DCHECK_EQ(out, begin + result.size());
+ return result;
+}
+
+// It's possible to call StrAppend with a char * pointer that is partway into
+// the string we're appending to. However the results of this are random.
+// Therefore, check for this in debug mode. Use unsigned math so we only have
+// to do one comparison.
+#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \
+ GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \
+ uintptr_t((dest).size()))
+
+void StrAppend(string *result, const AlphaNum &a) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ result->append(a.data(), a.size());
+}
+
+void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+ string::size_type old_size = result->size();
+ result->resize(old_size + a.size() + b.size());
+ char *const begin = &*result->begin();
+ char *out = Append2(begin + old_size, a, b);
+ GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+ const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+ string::size_type old_size = result->size();
+ result->resize(old_size + a.size() + b.size() + c.size());
+ char *const begin = &*result->begin();
+ char *out = Append2(begin + old_size, a, b);
+ out = Append1(out, c);
+ GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
+void StrAppend(string *result,
+ const AlphaNum &a, const AlphaNum &b,
+ const AlphaNum &c, const AlphaNum &d) {
+ GOOGLE_DCHECK_NO_OVERLAP(*result, a);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, b);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, c);
+ GOOGLE_DCHECK_NO_OVERLAP(*result, d);
+ string::size_type old_size = result->size();
+ result->resize(old_size + a.size() + b.size() + c.size() + d.size());
+ char *const begin = &*result->begin();
+ char *out = Append4(begin + old_size, a, b, c, d);
+ GOOGLE_DCHECK_EQ(out, begin + result->size());
+}
+
int GlobalReplaceSubstring(const string& substring,
const string& replacement,
string* s) {
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index f2e1a944..920701eb 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -495,57 +495,168 @@ LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer);
static const int kDoubleToBufferSize = 32;
static const int kFloatToBufferSize = 24;
-// ----------------------------------------------------------------------
-// ToString() are internal help methods used in StrCat() and Join()
-// ----------------------------------------------------------------------
-namespace internal {
-inline string ToString(int i) {
- return SimpleItoa(i);
-}
+namespace strings {
-inline string ToString(string a) {
- return a;
-}
-} // namespace internal
+struct Hex {
+ uint64 value;
+ enum PadSpec {
+ NONE = 1,
+ ZERO_PAD_2,
+ ZERO_PAD_3,
+ ZERO_PAD_4,
+ ZERO_PAD_5,
+ ZERO_PAD_6,
+ ZERO_PAD_7,
+ ZERO_PAD_8,
+ ZERO_PAD_9,
+ ZERO_PAD_10,
+ ZERO_PAD_11,
+ ZERO_PAD_12,
+ ZERO_PAD_13,
+ ZERO_PAD_14,
+ ZERO_PAD_15,
+ ZERO_PAD_16,
+ } spec;
+ template <class Int>
+ explicit Hex(Int v, PadSpec s = NONE)
+ : spec(s) {
+ // Prevent sign-extension by casting integers to
+ // their unsigned counterparts.
+#ifdef LANG_CXX11
+ static_assert(
+ sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
+ "Unknown integer type");
+#endif
+ value = sizeof(v) == 1 ? static_cast<uint8>(v)
+ : sizeof(v) == 2 ? static_cast<uint16>(v)
+ : sizeof(v) == 4 ? static_cast<uint32>(v)
+ : static_cast<uint64>(v);
+ }
+};
-// ----------------------------------------------------------------------
-// StrCat()
-// These methods join some strings together.
-// ----------------------------------------------------------------------
-template <typename T1, typename T2, typename T3, typename T4, typename T5,
- typename T6, typename T7>
-string StrCat(
- const T1& a, const T2& b, const T3& c, const T4& d, const T5& e,
- const T6& f, const T7& g) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c) + internal::ToString(d) + internal::ToString(e) +
- internal::ToString(f) + internal::ToString(g);
-}
+struct AlphaNum {
+ const char *piece_data_; // move these to string_ref eventually
+ size_t piece_size_; // move these to string_ref eventually
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-string StrCat(
- const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c) + internal::ToString(d) + internal::ToString(e);
-}
+ char digits[kFastToBufferSize];
-template <typename T1, typename T2, typename T3, typename T4>
-string StrCat(
- const T1& a, const T2& b, const T3& c, const T4& d) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c) + internal::ToString(d);
-}
+ // No bool ctor -- bools convert to an integral type.
+ // A bool ctor would also convert incoming pointers (bletch).
-template <typename T1, typename T2, typename T3>
-string StrCat(const T1& a, const T2& b, const T3& c) {
- return internal::ToString(a) + internal::ToString(b) +
- internal::ToString(c);
-}
+ AlphaNum(int32 i32)
+ : piece_data_(digits),
+ piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
+ AlphaNum(uint32 u32)
+ : piece_data_(digits),
+ piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
+ AlphaNum(int64 i64)
+ : piece_data_(digits),
+ piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
+ AlphaNum(uint64 u64)
+ : piece_data_(digits),
+ piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
-template <typename T1, typename T2>
-string StrCat(const T1& a, const T2& b) {
- return internal::ToString(a) + internal::ToString(b);
-}
+ AlphaNum(float f)
+ : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
+ AlphaNum(double f)
+ : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}
+
+ AlphaNum(Hex hex);
+
+ AlphaNum(const char* c_str)
+ : piece_data_(c_str), piece_size_(strlen(c_str)) {}
+ // TODO: Add a string_ref constructor, eventually
+ // AlphaNum(const StringPiece &pc) : piece(pc) {}
+
+ AlphaNum(const string& str)
+ : piece_data_(str.data()), piece_size_(str.size()) {}
+
+ size_t size() const { return piece_size_; }
+ const char *data() const { return piece_data_; }
+
+ private:
+ // Use ":" not ':'
+ AlphaNum(char c); // NOLINT(runtime/explicit)
+
+ // Disallow copy and assign.
+ AlphaNum(const AlphaNum&);
+ void operator=(const AlphaNum&);
+};
+
+} // namespace strings
+
+using strings::AlphaNum;
+
+// ----------------------------------------------------------------------
+// StrCat()
+// This merges the given strings or numbers, with no delimiter. This
+// is designed to be the fastest possible way to construct a string out
+// of a mix of raw C strings, strings, bool values,
+// and numeric values.
+//
+// Don't use this for user-visible strings. The localization process
+// works poorly on strings built up out of fragments.
+//
+// For clarity and performance, don't use StrCat when appending to a
+// string. In particular, avoid using any of these (anti-)patterns:
+// str.append(StrCat(...)
+// str += StrCat(...)
+// str = StrCat(str, ...)
+// where the last is the worse, with the potential to change a loop
+// from a linear time operation with O(1) dynamic allocations into a
+// quadratic time operation with O(n) dynamic allocations. StrAppend
+// is a better choice than any of the above, subject to the restriction
+// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
+// be a reference into str.
+// ----------------------------------------------------------------------
+
+string StrCat(const AlphaNum &a, const AlphaNum &b);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g, const AlphaNum &h);
+string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c,
+ const AlphaNum &d, const AlphaNum &e, const AlphaNum &f,
+ const AlphaNum &g, const AlphaNum &h, const AlphaNum &i);
+
+inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); }
+
+// ----------------------------------------------------------------------
+// StrAppend()
+// Same as above, but adds the output to the given string.
+// WARNING: For speed, StrAppend does not try to check each of its input
+// arguments to be sure that they are not a subset of the string being
+// appended to. That is, while this will work:
+//
+// string s = "foo";
+// s += s;
+//
+// This will not (necessarily) work:
+//
+// string s = "foo";
+// StrAppend(&s, s);
+//
+// Note: while StrCat supports appending up to 9 arguments, StrAppend
+// is currently limited to 4. That's rarely an issue except when
+// automatically transforming StrCat to StrAppend, and can easily be
+// worked around as consecutive calls to StrAppend are quite efficient.
+// ----------------------------------------------------------------------
+
+void StrAppend(string* dest, const AlphaNum& a);
+void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b);
+void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c);
+void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b,
+ const AlphaNum& c, const AlphaNum& d);
// ----------------------------------------------------------------------
// Join()
@@ -559,7 +670,7 @@ void Join(Iterator start, Iterator end,
if (it != start) {
result->append(delim);
}
- result->append(internal::ToString(*it));
+ StrAppend(result, *it);
}
}
diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3
new file mode 100644
index 00000000..934f36fa
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message_proto3
Binary files differ
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index 5344ec15..3d07b127 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -192,5 +192,9 @@ void File::DeleteRecursively(const string& name,
#endif
}
+bool File::ChangeWorkingDirectory(const string& new_working_directory) {
+ return chdir(new_working_directory.c_str()) == 0;
+}
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h
index d2aeabf2..2f63f80e 100644
--- a/src/google/protobuf/testing/file.h
+++ b/src/google/protobuf/testing/file.h
@@ -77,6 +77,9 @@ class File {
static void DeleteRecursively(const string& name,
void* dummy1, void* dummy2);
+ // Change working directory to given directory.
+ static bool ChangeWorkingDirectory(const string& new_working_directory);
+
static bool GetContents(
const string& name, string* output, bool /*is_default*/) {
return ReadFileToString(name, output);
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 8e867c09..ec070c51 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -1360,9 +1360,8 @@ void TextFormat::Printer::SetDefaultFieldValuePrinter(
bool TextFormat::Printer::RegisterFieldValuePrinter(
const FieldDescriptor* field,
const FieldValuePrinter* printer) {
- return field != NULL
- && printer != NULL
- && custom_printers_.insert(make_pair(field, printer)).second;
+ return field != NULL && printer != NULL &&
+ custom_printers_.insert(std::make_pair(field, printer)).second;
}
bool TextFormat::Printer::PrintToString(const Message& message,
@@ -1422,7 +1421,7 @@ void TextFormat::Printer::Print(const Message& message,
vector<const FieldDescriptor*> fields;
reflection->ListFields(message, &fields);
if (print_message_fields_in_index_order_) {
- sort(fields.begin(), fields.end(), FieldIndexSorter());
+ std::sort(fields.begin(), fields.end(), FieldIndexSorter());
}
for (int i = 0; i < fields.size(); i++) {
PrintField(message, reflection, fields[i], generator);
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 44d68cab..9e2cb070 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -278,8 +278,20 @@ class LIBPROTOBUF_EXPORT TextFormat {
};
// Parses a text-format protocol message from the given input stream to
- // the given message object. This function parses the format written
- // by Print().
+ // the given message object. This function parses the human-readable format
+ // written by Print(). Returns true on success. The message is cleared first,
+ // even if the function fails -- See Merge() to avoid this behavior.
+ //
+ // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}"
+ //
+ // One use for this function is parsing handwritten strings in test code.
+ // Another use is to parse the output from google::protobuf::Message::DebugString()
+ // (or ShortDebugString()), because these functions output using
+ // google::protobuf::TextFormat::Print().
+ //
+ // If you would like to read a protocol buffer serialized in the
+ // (non-human-readable) binary wire format, see
+ // google::protobuf::MessageLite::ParseFromString().
static bool Parse(io::ZeroCopyInputStream* input, Message* output);
// Like Parse(), but reads directly from a string.
static bool ParseFromString(const string& input, Message* output);
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
new file mode 100644
index 00000000..ac8e009c
--- /dev/null
+++ b/src/google/protobuf/timestamp.proto
@@ -0,0 +1,103 @@
+// 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 google.protobuf;
+
+option java_generate_equals_and_hash = true;
+option java_multiple_files = true;
+option java_outer_classname = "TimestampProto";
+option java_package = "com.google.protobuf";
+
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings. (See https://www.ietf.org/rfc/rfc3339.txt.)
+//
+// Example 1: compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+// Example 5: compute Timestamp from Python `datetime.datetime`.
+//
+// now = datetime.datetime.utcnow()
+// seconds = int(time.mktime(now.timetuple()))
+// nanos = now.microsecond * 1000
+// timestamp = Timestamp(seconds=seconds, nanos=nanos)
+//
+message Timestamp {
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ int64 seconds = 1;
+
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ int32 nanos = 2;
+}
diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto
index 1a420838..36fb8656 100644
--- a/src/google/protobuf/unittest_no_arena.proto
+++ b/src/google/protobuf/unittest_no_arena.proto
@@ -113,7 +113,7 @@ message TestAllTypes {
optional protobuf_unittest_import.PublicImportMessage
optional_public_import_message = 26;
- optional NestedMessage optional_lazy_message = 27 [lazy=true];
+ optional NestedMessage optional_message = 27 [lazy=true];
// Repeated
repeated int32 repeated_int32 = 31;
@@ -180,6 +180,7 @@ message TestAllTypes {
NestedMessage oneof_nested_message = 112;
string oneof_string = 113;
bytes oneof_bytes = 114;
+ NestedMessage lazy_oneof_nested_message = 115 [lazy=true];
}
}
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
index ba050d70..67e57499 100644
--- a/src/google/protobuf/unittest_preserve_unknown_enum.proto
+++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -30,7 +30,7 @@
syntax = "proto3";
-package proto2_preserve_unknown_enum_unittest;
+package proto3_preserve_unknown_enum_unittest;
enum MyEnum {
FOO = 0;
@@ -49,9 +49,10 @@ message MyMessage {
optional 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
oneof o {
- MyEnum oneof_e_1 = 4;
- MyEnum oneof_e_2 = 5;
+ MyEnum oneof_e_1 = 5;
+ MyEnum oneof_e_2 = 6;
}
}
@@ -59,8 +60,9 @@ message MyMessagePlusExtra {
optional 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];
oneof o {
- MyEnumPlusExtra oneof_e_1 = 4;
- MyEnumPlusExtra oneof_e_2 = 5;
+ MyEnumPlusExtra oneof_e_1 = 5;
+ MyEnumPlusExtra oneof_e_2 = 6;
}
}
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
new file mode 100644
index 00000000..adf42968
--- /dev/null
+++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
@@ -0,0 +1,50 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+
+package proto2_preserve_unknown_enum_unittest;
+
+enum MyEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+}
+
+message MyMessage {
+ optional MyEnum e = 1;
+ repeated MyEnum repeated_e = 2;
+ repeated MyEnum repeated_packed_e = 3 [packed=true];
+ repeated MyEnum repeated_packed_unexpected_e = 4; // not packed
+ oneof o {
+ MyEnum oneof_e_1 = 5;
+ MyEnum oneof_e_2 = 6;
+ }
+}
diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
index 53f23d87..6d7bada8 100644
--- a/src/google/protobuf/unittest_proto3_arena.proto
+++ b/src/google/protobuf/unittest_proto3_arena.proto
@@ -47,9 +47,10 @@ message TestAllTypes {
}
enum NestedEnum {
- FOO = 0;
- BAR = 1;
- BAZ = 2;
+ ZERO = 0;
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
NEG = -1; // Intentionally negative.
}
@@ -81,6 +82,11 @@ message TestAllTypes {
optional NestedEnum optional_nested_enum = 21;
optional 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];
@@ -118,6 +124,11 @@ message TestAllTypes {
repeated NestedEnum repeated_nested_enum = 51;
repeated ForeignEnum repeated_foreign_enum = 52;
+ // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+ // inside proto2 messages.
+ //
+ // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+
repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
repeated string repeated_cord = 55 [ctype=CORD];
@@ -131,6 +142,31 @@ message TestAllTypes {
}
}
+// Test messages for packed fields
+
+message TestPackedTypes {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnum packed_enum = 103 [packed = true];
+}
+
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+ NestedTestAllTypes child = 1;
+ TestAllTypes payload = 2;
+}
+
// Define these after TestAllTypes to make sure the compiler can handle
// that.
message ForeignMessage {
@@ -138,7 +174,13 @@ message ForeignMessage {
}
enum ForeignEnum {
- FOREIGN_FOO = 0;
- FOREIGN_BAR = 1;
- FOREIGN_BAZ = 2;
+ FOREIGN_ZERO = 0;
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
}
+
diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h
index fb5380aa..39c10cbc 100644
--- a/src/google/protobuf/unknown_enum_impl.h
+++ b/src/google/protobuf/unknown_enum_impl.h
@@ -99,6 +99,29 @@ bool GetRepeatedEnumUnknowns_Template(
}
// NOTE: You should not call these functions directly. Instead use
+// CLEAR_UNKNOWN_ENUM(), defined in the public header. The macro-versions
+// operate in a type-safe manner and behave appropriately for the proto
+// version of the message, whereas these versions assume a specific proto
+// version and allow the caller to pass in any arbitrary integer value as a
+// field number.
+//
+// Clears the unknown entries of the given field of the message.
+void ClearUnknownEnum(Message* message, int32 field_number);
+// In proto1, clears the field if the value is out of range.
+// TODO(karner): Delete this or make it proto2-only once the migration
+// to proto2 is complete.
+void ClearUnknownEnumProto1(Message* message, int32 field_number);
+template <typename T>
+void ClearUnknownEnum_Template(T* message, int32 field_number) {
+ if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
+ !internal::is_base_of<ProtocolMessage, T>::value) {
+ ClearUnknownEnum(message, field_number);
+ } else {
+ ClearUnknownEnumProto1(message, field_number);
+ }
+}
+
+// NOTE: You should not call these functions directly. Instead use
// SET_UNKNOWN_ENUM(), defined in the public header. The macro-versions
// operate in a type-safe manner and behave appropriately for the proto
// version of the message, whereas these versions assume a specific proto
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index e8c0a13c..987b1979 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -222,13 +222,12 @@ class LIBPROTOBUF_EXPORT UnknownField {
// UnknownField is being created.
inline void SetType(Type type);
- uint32 number_;
- uint32 type_;
-
union LengthDelimited {
string* string_value_;
};
+ uint32 number_;
+ uint32 type_;
union {
uint64 varint_;
uint32 fixed32_;
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index f4f02157..c5bbbf2e 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -141,7 +141,7 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag,
bool WireFormat::SkipMessage(io::CodedInputStream* input,
UnknownFieldSet* unknown_fields) {
- while(true) {
+ while (true) {
uint32 tag = input->ReadTag();
if (tag == 0) {
// End of input. This is a valid place to end, so return true.
@@ -159,6 +159,31 @@ bool WireFormat::SkipMessage(io::CodedInputStream* input,
}
}
+bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+ uint32 field_number,
+ bool (*is_valid)(int),
+ UnknownFieldSet* unknown_fields,
+ RepeatedField<int>* values) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+ return false;
+ }
+ if (is_valid == NULL || is_valid(value)) {
+ values->Add(value);
+ } else {
+ unknown_fields->AddVarint(field_number, value);
+ }
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
+
void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output) {
for (int i = 0; i < unknown_fields.field_count(); i++) {
@@ -520,6 +545,14 @@ bool WireFormat::ParseAndMergeField(
field->enum_type()->FindValueByNumber(value);
if (enum_value != NULL) {
message_reflection->AddEnum(message, field, enum_value);
+ } else {
+ // The enum value is not one of the known values. Add it to the
+ // UnknownFieldSet.
+ int64 sign_extended_value = static_cast<int64>(value);
+ message_reflection->MutableUnknownFields(message)
+ ->AddVarint(
+ WireFormatLite::GetTagFieldNumber(tag),
+ sign_extended_value);
}
}
}
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 9f26eb29..8de491a6 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -138,6 +138,14 @@ class LIBPROTOBUF_EXPORT WireFormat {
static bool SkipMessage(io::CodedInputStream* input,
UnknownFieldSet* unknown_fields);
+ // Read a packed enum field. If the is_valid function is not NULL, values for
+ // which is_valid(value) returns false are appended to unknown_fields_stream.
+ static bool ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input,
+ uint32 field_number,
+ bool (*is_valid)(int),
+ UnknownFieldSet* unknown_fields,
+ RepeatedField<int>* values);
+
// Write the contents of an UnknownFieldSet to the output.
static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields,
io::CodedOutputStream* output);
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 50616551..2ce4920c 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -304,6 +304,34 @@ bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input,
return true;
}
+bool WireFormatLite::ReadPackedEnumPreserveUnknowns(
+ io::CodedInputStream* input,
+ int field_number,
+ bool (*is_valid)(int),
+ io::CodedOutputStream* unknown_fields_stream,
+ RepeatedField<int>* values) {
+ uint32 length;
+ if (!input->ReadVarint32(&length)) return false;
+ io::CodedInputStream::Limit limit = input->PushLimit(length);
+ while (input->BytesUntilLimit() > 0) {
+ int value;
+ if (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+ int, WireFormatLite::TYPE_ENUM>(input, &value)) {
+ return false;
+ }
+ if (is_valid == NULL || is_valid(value)) {
+ values->Add(value);
+ } else {
+ uint32 tag = WireFormatLite::MakeTag(field_number,
+ WireFormatLite::WIRETYPE_VARINT);
+ unknown_fields_stream->WriteVarint32(tag);
+ unknown_fields_stream->WriteVarint32(value);
+ }
+ }
+ input->PopLimit(limit);
+ return true;
+}
+
void WireFormatLite::WriteInt32(int field_number, int32 value,
io::CodedOutputStream* output) {
WriteTag(field_number, WIRETYPE_VARINT, output);
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index acf88ead..76bc75a1 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -291,11 +291,20 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
template <typename CType, enum FieldType DeclaredType>
static bool ReadPackedPrimitiveNoInline(input, RepeatedField<CType>* value);
- // Read a packed enum field. Values for which is_valid() returns false are
- // dropped. If is_valid == NULL, no values are dropped.
+ // Read a packed enum field. If the is_valid function is not NULL, values for
+ // which is_valid(value) returns false are silently dropped.
static bool ReadPackedEnumNoInline(input,
bool (*is_valid)(int),
- RepeatedField<int>* value);
+ RepeatedField<int>* values);
+
+ // Read a packed enum field. If the is_valid function is not NULL, values for
+ // which is_valid(value) returns false are appended to unknown_fields_stream.
+ static bool ReadPackedEnumPreserveUnknowns(
+ input,
+ field_number,
+ bool (*is_valid)(int),
+ io::CodedOutputStream* unknown_fields_stream,
+ RepeatedField<int>* values);
// Read a string. ReadString(..., string* value) requires an existing string.
static inline bool ReadString(input, string* value);
@@ -647,7 +656,7 @@ inline double WireFormatLite::DecodeDouble(uint64 value) {
inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
// Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 31);
+ return (static_cast<uint32>(n) << 1) ^ (n >> 31);
}
inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
@@ -656,7 +665,7 @@ inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
// Note: the right-shift must be arithmetic
- return (n << 1) ^ (n >> 63);
+ return (static_cast<uint64>(n) << 1) ^ (n >> 63);
}
inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
new file mode 100644
index 00000000..5164c24c
--- /dev/null
+++ b/src/google/protobuf/wrappers.proto
@@ -0,0 +1,97 @@
+// 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.
+
+// Wrappers for primitive (non-message) types. These types are useful
+// for embedding primitives in the `google.protobuf.Any` type and for places
+// where we need to distinguish between the absence of a primitive
+// typed field and its default value.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "WrappersProto";
+option java_package = "com.google.protobuf";
+
+
+// Wrapper message for double.
+message DoubleValue {
+ // The double value.
+ double value = 1;
+}
+
+// Wrapper message for float.
+message FloatValue {
+ // The float value.
+ float value = 1;
+}
+
+// Wrapper message for int64.
+message Int64Value {
+ // The int64 value.
+ int64 value = 1;
+}
+
+// Wrapper message for uint64.
+message UInt64Value {
+ // The uint64 value.
+ uint64 value = 1;
+}
+
+// Wrapper message for int32.
+message Int32Value {
+ // The int32 value.
+ int32 value = 1;
+}
+
+// Wrapper message for uint32.
+message UInt32Value {
+ // The uint32 value.
+ uint32 value = 1;
+}
+
+// Wrapper message for bool.
+message BoolValue {
+ // The bool value.
+ bool value = 1;
+}
+
+// Wrapper message for string.
+message StringValue {
+ // The string value.
+ string value = 1;
+}
+
+// Wrapper message for bytes.
+message BytesValue {
+ // The bytes value.
+ bytes value = 1;
+}
diff --git a/vsprojects/config.h b/vsprojects/config.h
index 2c64450a..a93bb033 100644..100755
--- a/vsprojects/config.h
+++ b/vsprojects/config.h
@@ -1,28 +1,19 @@
/* protobuf config.h for MSVC. On other platforms, this is generated
* automatically by autoheader / autoconf / configure. */
-/* the location of <hash_map> */
-#define HASH_MAP_H <hash_map>
+#include <google/protobuf/stubs/pbconfig.h>
-/* the namespace of hash_map/hash_set */
-// Apparently Microsoft decided to move hash_map *back* to the std namespace
-// in MSVC 2010:
-// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
-// TODO(kenton): Use unordered_map instead, which is available in MSVC 2010.
-#if _MSC_VER < 1310 || _MSC_VER >= 1600
-#define HASH_NAMESPACE std
-#else
-#define HASH_NAMESPACE stdext
-#endif
-
-/* the location of <hash_set> */
-#define HASH_SET_H <hash_set>
+#define HASH_MAP_H GOOGLE_PROTOBUF_HASH_MAP_H
+#define HASH_NAMESPACE GOOGLE_PROTOBUF_HASH_NAMESPACE
+#define HASH_SET_H GOOGLE_PROTOBUF_HASH_SET_H
-/* define if the compiler has hash_map */
-#define HAVE_HASH_MAP 1
+#ifdef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+#define HAVE_HASH_MAP GOOGLE_PROTOBUF_HAVE_HASH_MAP
+#endif
-/* define if the compiler has hash_set */
-#define HAVE_HASH_SET 1
+#ifdef GOOGLE_PROTOBUF_HAVE_HASH_SET
+#define HAVE_HASH_SET GOOGLE_PROTOBUF_HAVE_HASH_SET
+#endif
/* define if you want to use zlib. See readme.txt for additional
* requirements. */
diff --git a/vsprojects/extract_includes.bat b/vsprojects/extract_includes.bat
index 587c1a8a..ddf7f33f 100755
--- a/vsprojects/extract_includes.bat
+++ b/vsprojects/extract_includes.bat
@@ -6,7 +6,9 @@ md include\google\protobuf\io
md include\google\protobuf\compiler
md include\google\protobuf\compiler\cpp
md include\google\protobuf\compiler\java
+md include\google\protobuf\compiler\javanano
md include\google\protobuf\compiler\python
+md include\google\protobuf\compiler\ruby
copy ..\src\google\protobuf\arena.h include\google\protobuf\arena.h
copy ..\src\google\protobuf\arenastring.h include\google\protobuf\arenastring.h
copy ..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h
@@ -14,16 +16,19 @@ copy ..\src\google\protobuf\compiler\command_line_interface.h include\google\pro
copy ..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
copy ..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
copy ..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
+copy ..\src\google\protobuf\compiler\javanano\javanano_generator.h include\google\protobuf\compiler\javanano\javanano_generator.h
copy ..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h
copy ..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h
copy ..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h
copy ..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h
+copy ..\src\google\protobuf\compiler\ruby\ruby_generator.h include\google\protobuf\compiler\ruby\ruby_generator.h
copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h
copy ..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h
copy ..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h
copy ..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h
copy ..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h
copy ..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h
+copy ..\src\google\protobuf\generated_enum_util.h include\google\protobuf\generated_enum_util.h
copy ..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h
copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h
copy ..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h
@@ -35,7 +40,9 @@ copy ..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zer
copy ..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h
copy ..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h
copy ..\src\google\protobuf\map_entry.h include\google\protobuf\map_entry.h
+copy ..\src\google\protobuf\map_entry_lite.h include\google\protobuf\map_entry_lite.h
copy ..\src\google\protobuf\map_field.h include\google\protobuf\map_field.h
+copy ..\src\google\protobuf\map_field_lite.h include\google\protobuf\map_field_lite.h
copy ..\src\google\protobuf\map_field_inl.h include\google\protobuf\map_field_inl.h
copy ..\src\google\protobuf\map.h include\google\protobuf\map.h
copy ..\src\google\protobuf\map_type_handler.h include\google\protobuf\map_type_handler.h
@@ -68,6 +75,7 @@ copy ..\src\google\protobuf\stubs\fastmem.h include\google\protobuf\stubs\fastme
copy ..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h
copy ..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h
copy ..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h
+copy ..\src\google\protobuf\stubs\hash.h include\google\protobuf\stubs\hash.h
copy ..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h
copy ..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h
copy ..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h
@@ -76,3 +84,4 @@ copy ..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_
copy ..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h
copy ..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h
copy ..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h
+copy google\protobuf\stubs\pbconfig.h include\google\protobuf\stubs\pbconfig.h
diff --git a/vsprojects/google/protobuf/stubs/pbconfig.h b/vsprojects/google/protobuf/stubs/pbconfig.h
new file mode 100755
index 00000000..18250a22
--- /dev/null
+++ b/vsprojects/google/protobuf/stubs/pbconfig.h
@@ -0,0 +1,39 @@
+/* protobuf config.h for MSVC. On other platforms, this is generated
+ * automatically by autoheader / autoconf / configure. */
+
+// NOTE: if you add new macros in this file manually, please propagate the macro
+// to vsprojects/config.h.
+
+/* the namespace of hash_map/hash_set */
+// Apparently Microsoft decided to move hash_map *back* to the std namespace
+// in MSVC 2010:
+// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
+// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That
+// said, use unordered_map for MSVC 2010 and beyond is our safest bet.
+#if _MSC_VER >= 1600
+#define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+#define GOOGLE_PROTOBUF_HASH_MAP_H <unordered_map>
+#define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map
+#define GOOGLE_PROTOBUF_HASH_SET_H <unordered_set>
+#define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set
+#elif _MSC_VER >= 1310
+#define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext
+#define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map>
+#define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#define GOOGLE_PROTOBUF_HASH_SET_H <hash_set>
+#define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#else
+#define GOOGLE_PROTOBUF_HASH_NAMESPACE std
+#define GOOGLE_PROTOBUF_HASH_MAP_H <hash_map>
+#define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map
+#define GOOGLE_PROTOBUF_HASH_SET_H <hash_set>
+#define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
+#endif
+
+/* the location of <hash_set> */
+
+/* define if the compiler has hash_map */
+#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
+
+/* define if the compiler has hash_set */
+#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
diff --git a/vsprojects/libprotobuf-lite.vcproj b/vsprojects/libprotobuf-lite.vcproj
index 09eca4d8..d245448d 100644
--- a/vsprojects/libprotobuf-lite.vcproj
+++ b/vsprojects/libprotobuf-lite.vcproj
@@ -164,6 +164,10 @@
>
</File>
<File
+ RelativePath=".\google\protobuf\stubs\pbconfig.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\extension_set.h"
>
</File>
@@ -179,6 +183,9 @@
RelativePath="..\src\google\protobuf\stubs\map-util.h"
>
</File>
+ <File RelativePath="..\src\google\protobuf\generated_enum_util.h"></File>
+ <File RelativePath="..\src\google\protobuf\map_entry_lite.h"></File>
+ <File RelativePath="..\src\google\protobuf\map_field_lite.h"></File>
<File
RelativePath="..\src\google\protobuf\message_lite.h"
>
diff --git a/vsprojects/libprotobuf.vcproj b/vsprojects/libprotobuf.vcproj
index 095d3948..e782885f 100644
--- a/vsprojects/libprotobuf.vcproj
+++ b/vsprojects/libprotobuf.vcproj
@@ -164,6 +164,10 @@
>
</File>
<File
+ RelativePath=".\google\protobuf\stubs\pbconfig.h"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\descriptor.h"
>
</File>
@@ -219,6 +223,9 @@
RelativePath="..\src\google\protobuf\message_lite.h"
>
</File>
+ <File RelativePath="..\src\google\protobuf\generated_enum_util.h"></File>
+ <File RelativePath="..\src\google\protobuf\map_entry_lite.h"></File>
+ <File RelativePath="..\src\google\protobuf\map_field_lite.h"></File>
<File
RelativePath="..\src\google\protobuf\stubs\atomicops.h"
>
diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj
index 6b1e8864..455c2cc2 100644
--- a/vsprojects/libprotoc.vcproj
+++ b/vsprojects/libprotoc.vcproj
@@ -1,526 +1,542 @@
<?xml version="1.0" encoding="UTF-8"?>
<VisualStudioProject
- ProjectType="Visual C++"
- Version="9.00"
- Name="libprotoc"
- ProjectGUID="{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}"
- Keyword="Win32Proj"
- TargetFrameworkVersion="0"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="$(OutDir)\$(ProjectName)"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- Optimization="0"
- AdditionalIncludeDirectories="../src;."
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="$(OutDir)\$(ProjectName)"
- ConfigurationType="4"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
- AdditionalIncludeDirectories="../src;."
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
- RuntimeLibrary="2"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="true"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLibrarianTool"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\src\google\protobuf\compiler\code_generator.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\command_line_interface.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\subprocess.h"
- >
- </File>
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="libprotoc"
+ ProjectGUID="{B84FF31A-5F9A-46F8-AB22-DBFC9BECE3BE}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ Optimization="0"
+ AdditionalIncludeDirectories="../src;."
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 /wd4305"
+ AdditionalIncludeDirectories="../src;."
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBPROTOC_EXPORTS;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\compiler\code_generator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\command_line_interface.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\subprocess.h"
+ >
+ </File>
<File
RelativePath="..\src\google\protobuf\compiler\zip_writer.h"
>
</File>
- <File
- RelativePath="..\src\google\protobuf\compiler\plugin.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\plugin.pb.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_options.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_context.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_enum.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_extension.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_file.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_generator.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_helpers.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_message.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_message_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_service.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_string_field.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.h"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\python\python_generator.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\src\google\protobuf\compiler\code_generator.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\command_line_interface.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_map_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_context.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_enum.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_extension.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_file.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_generator.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_helpers.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_map_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_message.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_message_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_service.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\java\java_string_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\plugin.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\plugin.pb.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\python\python_generator.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\subprocess.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\zip_writer.cc"
- >
- </File>
- </Filter>
- </Files>
- <Globals>
- </Globals>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\plugin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\plugin.pb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_options.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_context.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_enum.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_extension.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_generator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_helpers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_service.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_string_field.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
+ >
+ </File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_map_field.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_params.h"></File>
+ <File RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.h"></File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\python\python_generator.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\src\google\protobuf\compiler\code_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\command_line_interface.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_extension.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_file.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_helpers.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_map_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_primitive_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_service.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_string_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\ruby\ruby_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_context.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_enum.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_extension.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_file.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_generator_factory.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_helpers.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_map_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_message_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_name_resolver.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_service.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_shared_code_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\java\java_string_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_map_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\plugin.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\plugin.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\python\python_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\subprocess.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\zip_writer.cc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
</VisualStudioProject>
diff --git a/vsprojects/lite-test.vcproj b/vsprojects/lite-test.vcproj
index bb338092..8d172248 100644
--- a/vsprojects/lite-test.vcproj
+++ b/vsprojects/lite-test.vcproj
@@ -182,6 +182,8 @@
RelativePath="..\src\google\protobuf\test_util_lite.h"
>
</File>
+ <File RelativePath=".\google\protobuf\map_lite_unittest.pb.h"></File>
+ <File RelativePath="..\src\google\protobuf\map_lite_test_util.h"></File>
<File
RelativePath=".\google\protobuf\unittest_lite.pb.h"
>
@@ -218,6 +220,8 @@
RelativePath=".\google\protobuf\unittest_lite.pb.cc"
>
</File>
+ <File RelativePath=".\google\protobuf\map_lite_unittest.pb.cc"></File>
+ <File RelativePath="..\src\google\protobuf\map_lite_test_util.cc"></File>
<File
RelativePath=".\google\protobuf\unittest_import_lite.pb.cc"
>
@@ -299,6 +303,30 @@
/>
</FileConfiguration>
</File>
+ <File
+ RelativePath="..\src\google\protobuf\map_lite_unittest.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating map_lite_unittest.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating map_lite_unittest.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto&#x0D;&#x0A;"
+ Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
</Files>
<Globals>
</Globals>
diff --git a/vsprojects/tests.vcproj b/vsprojects/tests.vcproj
index 23c81f0e..0d42949e 100644
--- a/vsprojects/tests.vcproj
+++ b/vsprojects/tests.vcproj
@@ -194,6 +194,9 @@
RelativePath="..\src\google\protobuf\test_util.h"
>
</File>
+ <File RelativePath="..\src\google\protobuf\map_test_util_impl.h"></File>
+ <File RelativePath="..\src\google\protobuf\map_test_util.h"></File>
+ <File RelativePath="..\src\google\protobuf\arena_test_util.h"></File>
<File
RelativePath="..\src\google\protobuf\compiler\mock_code_generator.h"
>
@@ -346,6 +349,7 @@
RelativePath="..\src\google\protobuf\map_test_util.cc"
>
</File>
+ <File RelativePath="..\src\google\protobuf\arena_test_util.cc"></File>
<File
RelativePath="..\src\google\protobuf\message_unittest.cc"
>
@@ -431,7 +435,7 @@
>
</File>
<File
- RelativePath=".\google\protobuf\map_lite_unittest.pb.cc"
+ RelativePath=".\google\protobuf\unittest_preserve_unknown_enum2.pb.cc"
>
</File>
<File
@@ -524,16 +528,16 @@
</File>
</Filter>
<File
- RelativePath="..\src\google\protobuf\map_lite_unittest.proto"
+ RelativePath="..\src\google\protobuf\unittest_preserve_unknown_enum2.proto"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
- Description="Generating map_lite_unittest.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto"
- Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+ Description="Generating unittest_preserve_unknown_enum2.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum2.proto"
+ Outputs="google\protobuf\unittest_preserve_unknown_enum2.pb.h;google\protobuf\unittest_preserve_unknown_enum2.pb.cc"
/>
</FileConfiguration>
<FileConfiguration
@@ -541,9 +545,9 @@
>
<Tool
Name="VCCustomBuildTool"
- Description="Generating map_lite_unittest.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto"
- Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+ Description="Generating unittest_preserve_unknown_enum2.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum2.proto"
+ Outputs="google\protobuf\unittest_preserve_unknown_enum2.pb.h;google\protobuf\unittest_preserve_unknown_enum2.pb.cc"
/>
</FileConfiguration>
</File>