aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Feng Xiao <xfxyjwf@gmail.com>2015-08-22 18:25:48 -0700
committerGravatar Feng Xiao <xfxyjwf@gmail.com>2015-08-22 18:25:48 -0700
commiteee38b0c018b3279f77d03dff796f440f40d3516 (patch)
tree7ff0978e30238d493fc7899b75abeb6d66939f07
parentc3bc155aceda36ecb01cde2367a3b427f2d7ce40 (diff)
Down-integrate from google3.
-rw-r--r--cmake/install.cmake206
-rw-r--r--cmake/protobuf-config-version.cmake.in2
-rw-r--r--cmake/protobuf-config.cmake.in54
-rw-r--r--java/src/main/java/com/google/protobuf/ByteString.java22
-rw-r--r--java/src/main/java/com/google/protobuf/CodedOutputStream.java103
-rw-r--r--java/src/main/java/com/google/protobuf/Descriptors.java6
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessage.java115
-rw-r--r--java/src/main/java/com/google/protobuf/GeneratedMessageLite.java109
-rw-r--r--java/src/main/java/com/google/protobuf/Internal.java12
-rw-r--r--java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java2
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringArrayList.java5
-rw-r--r--java/src/main/java/com/google/protobuf/LazyStringList.java13
-rw-r--r--java/src/main/java/com/google/protobuf/Message.java3
-rw-r--r--java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java2
-rw-r--r--java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java257
-rw-r--r--java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java5
-rw-r--r--java/src/main/java/com/google/protobuf/Utf8.java132
-rw-r--r--java/src/main/java/com/google/protobuf/WireFormat.java2
-rw-r--r--java/src/test/java/com/google/protobuf/BoundedByteStringTest.java1
-rw-r--r--java/src/test/java/com/google/protobuf/CheckUtf8Test.java7
-rw-r--r--java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java110
-rw-r--r--java/src/test/java/com/google/protobuf/FieldPresenceTest.java10
-rw-r--r--java/src/test/java/com/google/protobuf/GeneratedMessageTest.java3
-rw-r--r--java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java21
-rw-r--r--java/src/test/java/com/google/protobuf/LiteTest.java3
-rw-r--r--java/src/test/java/com/google/protobuf/LiteralByteStringTest.java61
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java26
-rw-r--r--java/src/test/java/com/google/protobuf/MapForProto2Test.java26
-rw-r--r--java/src/test/java/com/google/protobuf/MapTest.java42
-rw-r--r--java/src/test/java/com/google/protobuf/ParserTest.java16
-rw-r--r--java/src/test/java/com/google/protobuf/RopeByteStringTest.java8
-rw-r--r--java/src/test/java/com/google/protobuf/TestUtil.java1
-rw-r--r--java/src/test/java/com/google/protobuf/TextFormatTest.java2
-rw-r--r--java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java2
-rw-r--r--java/src/test/java/com/google/protobuf/WireFormatTest.java2
-rwxr-xr-xpython/google/protobuf/internal/containers.py11
-rwxr-xr-xpython/google/protobuf/internal/generator_test.py3
-rwxr-xr-xpython/google/protobuf/internal/message_test.py115
-rw-r--r--python/google/protobuf/internal/packed_field_test.proto73
-rwxr-xr-xpython/google/protobuf/internal/python_message.py151
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py48
-rwxr-xr-xpython/google/protobuf/internal/test_util.py3
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py31
-rwxr-xr-xpython/google/protobuf/internal/unknown_fields_test.py72
-rw-r--r--python/google/protobuf/pyext/cpp_message.py36
-rw-r--r--python/google/protobuf/pyext/descriptor.cc2
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.cc7
-rw-r--r--python/google/protobuf/pyext/descriptor_pool.h10
-rw-r--r--python/google/protobuf/pyext/extension_dict.cc6
-rw-r--r--python/google/protobuf/pyext/message.cc724
-rw-r--r--python/google/protobuf/pyext/message.h4
-rw-r--r--python/google/protobuf/pyext/message_map_container.cc1
-rw-r--r--python/google/protobuf/pyext/repeated_composite_container.cc211
-rw-r--r--python/google/protobuf/pyext/repeated_scalar_container.cc11
-rw-r--r--python/google/protobuf/pyext/scalar_map_container.cc1
-rw-r--r--python/google/protobuf/pyext/scoped_pyobject_ptr.h16
-rwxr-xr-xpython/google/protobuf/reflection.py96
-rwxr-xr-xpython/google/protobuf/text_format.py2
-rw-r--r--src/google/protobuf/any.cc4
-rw-r--r--src/google/protobuf/any.h2
-rwxr-xr-xsrc/google/protobuf/arena.cc40
-rw-r--r--src/google/protobuf/arena.h178
-rw-r--r--src/google/protobuf/arena_test_util.cc1
-rw-r--r--src/google/protobuf/arena_unittest.cc55
-rwxr-xr-xsrc/google/protobuf/arenastring.h11
-rw-r--r--src/google/protobuf/arenastring_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/code_generator.cc1
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc5
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc33
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.h5
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc254
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h32
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc13
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc24
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h7
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc187
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc616
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.h20
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc31
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc2
-rw-r--r--src/google/protobuf/compiler/importer_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc4
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field_lite.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_enum_lite.cc226
-rw-r--r--src/google/protobuf/compiler/java/java_enum_lite.h99
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_field.h1
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h4
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc24
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.cc24
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc132
-rw-r--r--src/google/protobuf/compiler/java/java_message.h1
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc13
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.cc14
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc92
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field_lite.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_service.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc22
-rw-r--r--src/google/protobuf/compiler/java/java_string_field_lite.cc189
-rw-r--r--src/google/protobuf/compiler/parser.cc1
-rw-r--r--src/google/protobuf/compiler/parser.h6
-rw-r--r--src/google/protobuf/compiler/plugin.cc1
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc36
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h28
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc1
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h1
-rw-r--r--src/google/protobuf/compiler/subprocess.cc1
-rw-r--r--src/google/protobuf/descriptor.cc24
-rw-r--r--src/google/protobuf/descriptor.h4
-rw-r--r--src/google/protobuf/descriptor.pb.cc482
-rw-r--r--src/google/protobuf/descriptor.pb.h346
-rw-r--r--src/google/protobuf/descriptor.proto11
-rw-r--r--src/google/protobuf/descriptor_database_unittest.cc2
-rw-r--r--src/google/protobuf/descriptor_unittest.cc85
-rw-r--r--src/google/protobuf/dynamic_message.cc27
-rw-r--r--src/google/protobuf/dynamic_message.h1
-rw-r--r--src/google/protobuf/dynamic_message_unittest.cc2
-rw-r--r--src/google/protobuf/extension_set.h7
-rw-r--r--src/google/protobuf/extension_set_heavy.cc16
-rw-r--r--src/google/protobuf/extension_set_unittest.cc3
-rw-r--r--src/google/protobuf/generated_message_reflection.cc133
-rw-r--r--src/google/protobuf/generated_message_reflection.h40
-rw-r--r--src/google/protobuf/generated_message_reflection_unittest.cc52
-rw-r--r--src/google/protobuf/io/coded_stream.cc5
-rw-r--r--src/google/protobuf/io/coded_stream.h31
-rw-r--r--src/google/protobuf/io/coded_stream_inl.h1
-rw-r--r--src/google/protobuf/io/coded_stream_unittest.cc2
-rw-r--r--src/google/protobuf/io/gzip_stream.cc2
-rw-r--r--src/google/protobuf/io/printer.cc1
-rw-r--r--src/google/protobuf/io/printer_unittest.cc1
-rw-r--r--src/google/protobuf/io/strtod.cc1
-rw-r--r--src/google/protobuf/io/tokenizer.cc1
-rw-r--r--src/google/protobuf/io/tokenizer.h1
-rw-r--r--src/google/protobuf/io/tokenizer_unittest.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.cc1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_impl_lite.h1
-rw-r--r--src/google/protobuf/io/zero_copy_stream_unittest.cc3
-rw-r--r--src/google/protobuf/lite_unittest.cc39
-rw-r--r--src/google/protobuf/map.h423
-rw-r--r--src/google/protobuf/map_entry.h81
-rw-r--r--src/google/protobuf/map_entry_lite.h162
-rw-r--r--src/google/protobuf/map_field.cc316
-rw-r--r--src/google/protobuf/map_field.h194
-rw-r--r--src/google/protobuf/map_field_inl.h231
-rw-r--r--src/google/protobuf/map_field_test.cc23
-rw-r--r--src/google/protobuf/map_lite_unittest.proto17
-rw-r--r--src/google/protobuf/map_proto2_unittest.proto8
-rw-r--r--src/google/protobuf/map_test.cc190
-rw-r--r--src/google/protobuf/map_test_util.cc726
-rw-r--r--src/google/protobuf/map_test_util.h131
-rw-r--r--src/google/protobuf/map_test_util_impl.h16
-rw-r--r--src/google/protobuf/map_type_handler.h729
-rw-r--r--src/google/protobuf/map_unittest.proto14
-rw-r--r--src/google/protobuf/message.cc19
-rw-r--r--src/google/protobuf/message.h113
-rw-r--r--src/google/protobuf/message_lite.cc62
-rw-r--r--src/google/protobuf/message_unittest.cc1
-rw-r--r--src/google/protobuf/metadata.h17
-rw-r--r--src/google/protobuf/no_field_presence_test.cc40
-rw-r--r--src/google/protobuf/proto3_arena_unittest.cc26
-rw-r--r--src/google/protobuf/proto_cast.h1
-rw-r--r--src/google/protobuf/proto_cast_test.cc2
-rwxr-xr-xsrc/google/protobuf/reflection.h2
-rw-r--r--src/google/protobuf/reflection_ops_unittest.cc1
-rw-r--r--src/google/protobuf/repeated_field.cc9
-rw-r--r--src/google/protobuf/repeated_field.h90
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc2
-rw-r--r--src/google/protobuf/service.h5
-rw-r--r--src/google/protobuf/test_util.cc1
-rw-r--r--src/google/protobuf/test_util_lite.cc1
-rw-r--r--src/google/protobuf/text_format_unittest.cc2
-rw-r--r--src/google/protobuf/unittest_mset.proto19
-rw-r--r--src/google/protobuf/unknown_enum_impl.h9
-rw-r--r--src/google/protobuf/unknown_enum_test.proto2
-rw-r--r--src/google/protobuf/unknown_field_set.cc1
-rw-r--r--src/google/protobuf/unknown_field_set.h1
-rw-r--r--src/google/protobuf/unknown_field_set_unittest.cc3
-rw-r--r--src/google/protobuf/util/internal/datapiece.cc6
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.cc66
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter.h13
-rw-r--r--src/google/protobuf/util/internal/default_value_objectwriter_test.cc58
-rw-r--r--src/google/protobuf/util/internal/error_listener.h2
-rw-r--r--src/google/protobuf/util/internal/field_mask_utility.cc23
-rw-r--r--src/google/protobuf/util/internal/json_escaping.cc1
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter.cc3
-rw-r--r--src/google/protobuf/util/internal/json_objectwriter_test.cc189
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.cc62
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser.h12
-rw-r--r--src/google/protobuf/util/internal/json_stream_parser_test.cc23
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.cc17
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource.h10
-rw-r--r--src/google/protobuf/util/internal/protostream_objectsource_test.cc40
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.cc79
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter.h41
-rw-r--r--src/google/protobuf/util/internal/protostream_objectwriter_test.cc306
-rw-r--r--src/google/protobuf/util/internal/snake2camel_objectwriter.h46
-rw-r--r--src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc260
-rw-r--r--src/google/protobuf/util/internal/testdata/default_value.proto7
-rw-r--r--src/google/protobuf/util/internal/type_info.cc25
-rw-r--r--src/google/protobuf/util/internal/type_info.h15
-rw-r--r--src/google/protobuf/util/internal/type_info_test_helper.cc7
-rw-r--r--src/google/protobuf/util/internal/utility.cc4
-rw-r--r--src/google/protobuf/util/internal/utility.h11
-rw-r--r--src/google/protobuf/util/json_util.h10
-rw-r--r--src/google/protobuf/util/json_util_test.cc43
-rw-r--r--src/google/protobuf/util/message_differencer.cc1
-rwxr-xr-xsrc/google/protobuf/util/message_differencer_unittest.cc3
-rw-r--r--src/google/protobuf/util/type_resolver_util.cc43
-rw-r--r--src/google/protobuf/util/type_resolver_util.h2
-rw-r--r--src/google/protobuf/wire_format.cc1
-rw-r--r--src/google/protobuf/wire_format_lite.cc7
-rw-r--r--src/google/protobuf/wire_format_lite.h167
-rw-r--r--src/google/protobuf/wire_format_lite_inl.h1
-rw-r--r--src/google/protobuf/wire_format_unittest.cc16
226 files changed, 8484 insertions, 3661 deletions
diff --git a/cmake/install.cmake b/cmake/install.cmake
index e14ef1d2..dbb4265d 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -1,103 +1,103 @@
-include(GNUInstallDirs)
-
-foreach(_library
- libprotobuf-lite
- libprotobuf
- libprotoc)
- set_property(TARGET ${_library}
- PROPERTY INTERFACE_INCLUDE_DIRECTORIES
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
- install(TARGETS ${_library} EXPORT protobuf-targets
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}
- LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library})
-endforeach()
-
-install(TARGETS protoc EXPORT protobuf-targets
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
-
-if(TRUE)
- file(STRINGS extract_includes.bat.in _extract_strings
- REGEX "^copy")
- foreach(_extract_string ${_extract_strings})
- string(REPLACE "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\" ""
- _extract_string ${_extract_string})
- string(REPLACE "\\" "/" _extract_string ${_extract_string})
- string(REGEX MATCH "^[^ ]+"
- _extract_from ${_extract_string})
- string(REGEX REPLACE "^${_extract_from} ([^$]+)" "\\1"
- _extract_to ${_extract_string})
- get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/${_extract_from}" ABSOLUTE)
- get_filename_component(_extract_name ${_extract_to} NAME)
- get_filename_component(_extract_to ${_extract_to} PATH)
- string(REPLACE "include/" "${CMAKE_INSTALL_INCLUDEDIR}/"
- _extract_to "${_extract_to}")
- if(EXISTS "${_extract_from}")
- install(FILES "${_extract_from}"
- DESTINATION "${_extract_to}"
- COMPONENT protobuf-headers
- RENAME "${_extract_name}")
- else()
- message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "
- "\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "
- "but there not exists. The file will not be installed.")
- endif()
- endforeach()
-endif()
-
-# Internal function for parsing auto tools scripts
-function(_protobuf_auto_list FILE_NAME VARIABLE)
- file(STRINGS ${FILE_NAME} _strings)
- set(_list)
- foreach(_string ${_strings})
- set(_found)
- string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")
- if(_found)
- string(LENGTH "${_found}" _length)
- string(SUBSTRING "${_string}" ${_length} -1 _draft_list)
- foreach(_item ${_draft_list})
- string(STRIP "${_item}" _item)
- list(APPEND _list "${_item}")
- endforeach()
- endif()
- endforeach()
- set(${VARIABLE} ${_list} PARENT_SCOPE)
-endfunction()
-
-# Install well-known type proto files
-_protobuf_auto_list("../src/Makefile.am" nobase_dist_proto_DATA)
-foreach(_file ${nobase_dist_proto_DATA})
- get_filename_component(_file_from "../src/${_file}" ABSOLUTE)
- get_filename_component(_file_name ${_file} NAME)
- get_filename_component(_file_path ${_file} PATH)
- if(EXISTS "${_file_from}")
- install(FILES "${_file_from}"
- DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_file_path}"
- COMPONENT protobuf-protos
- RENAME "${_file_name}")
- else()
- message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "
- "\"${protobuf_SOURCE_DIR}/../src/Makefile.am\" as nobase_dist_proto_DATA "
- "but there not exists. The file will not be installed.")
- endif()
-endforeach()
-
-# Export configuration
-
-install(EXPORT protobuf-targets
- DESTINATION "lib/cmake/protobuf"
- COMPONENT protobuf-export)
-
-configure_file(protobuf-config.cmake.in
- protobuf-config.cmake @ONLY)
-configure_file(protobuf-config-version.cmake.in
- protobuf-config-version.cmake @ONLY)
-configure_file(protobuf-module.cmake.in
- protobuf-module.cmake @ONLY)
-
-install(FILES
- "${protobuf_BINARY_DIR}/protobuf-config.cmake"
- "${protobuf_BINARY_DIR}/protobuf-config-version.cmake"
- "${protobuf_BINARY_DIR}/protobuf-module.cmake"
- DESTINATION "lib/cmake/protobuf"
- COMPONENT protobuf-export)
+include(GNUInstallDirs)
+
+foreach(_library
+ libprotobuf-lite
+ libprotobuf
+ libprotoc)
+ set_property(TARGET ${_library}
+ PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
+ install(TARGETS ${_library} EXPORT protobuf-targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${_library}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${_library})
+endforeach()
+
+install(TARGETS protoc EXPORT protobuf-targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
+
+if(TRUE)
+ file(STRINGS extract_includes.bat.in _extract_strings
+ REGEX "^copy")
+ foreach(_extract_string ${_extract_strings})
+ string(REPLACE "copy \${PROTOBUF_SOURCE_WIN32_PATH}\\" ""
+ _extract_string ${_extract_string})
+ string(REPLACE "\\" "/" _extract_string ${_extract_string})
+ string(REGEX MATCH "^[^ ]+"
+ _extract_from ${_extract_string})
+ string(REGEX REPLACE "^${_extract_from} ([^$]+)" "\\1"
+ _extract_to ${_extract_string})
+ get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/${_extract_from}" ABSOLUTE)
+ get_filename_component(_extract_name ${_extract_to} NAME)
+ get_filename_component(_extract_to ${_extract_to} PATH)
+ string(REPLACE "include/" "${CMAKE_INSTALL_INCLUDEDIR}/"
+ _extract_to "${_extract_to}")
+ if(EXISTS "${_extract_from}")
+ install(FILES "${_extract_from}"
+ DESTINATION "${_extract_to}"
+ COMPONENT protobuf-headers
+ RENAME "${_extract_name}")
+ else()
+ message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "
+ "\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "
+ "but there not exists. The file will not be installed.")
+ endif()
+ endforeach()
+endif()
+
+# Internal function for parsing auto tools scripts
+function(_protobuf_auto_list FILE_NAME VARIABLE)
+ file(STRINGS ${FILE_NAME} _strings)
+ set(_list)
+ foreach(_string ${_strings})
+ set(_found)
+ string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")
+ if(_found)
+ string(LENGTH "${_found}" _length)
+ string(SUBSTRING "${_string}" ${_length} -1 _draft_list)
+ foreach(_item ${_draft_list})
+ string(STRIP "${_item}" _item)
+ list(APPEND _list "${_item}")
+ endforeach()
+ endif()
+ endforeach()
+ set(${VARIABLE} ${_list} PARENT_SCOPE)
+endfunction()
+
+# Install well-known type proto files
+_protobuf_auto_list("../src/Makefile.am" nobase_dist_proto_DATA)
+foreach(_file ${nobase_dist_proto_DATA})
+ get_filename_component(_file_from "../src/${_file}" ABSOLUTE)
+ get_filename_component(_file_name ${_file} NAME)
+ get_filename_component(_file_path ${_file} PATH)
+ if(EXISTS "${_file_from}")
+ install(FILES "${_file_from}"
+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_file_path}"
+ COMPONENT protobuf-protos
+ RENAME "${_file_name}")
+ else()
+ message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "
+ "\"${protobuf_SOURCE_DIR}/../src/Makefile.am\" as nobase_dist_proto_DATA "
+ "but there not exists. The file will not be installed.")
+ endif()
+endforeach()
+
+# Export configuration
+
+install(EXPORT protobuf-targets
+ DESTINATION "lib/cmake/protobuf"
+ COMPONENT protobuf-export)
+
+configure_file(protobuf-config.cmake.in
+ protobuf-config.cmake @ONLY)
+configure_file(protobuf-config-version.cmake.in
+ protobuf-config-version.cmake @ONLY)
+configure_file(protobuf-module.cmake.in
+ protobuf-module.cmake @ONLY)
+
+install(FILES
+ "${protobuf_BINARY_DIR}/protobuf-config.cmake"
+ "${protobuf_BINARY_DIR}/protobuf-config-version.cmake"
+ "${protobuf_BINARY_DIR}/protobuf-module.cmake"
+ DESTINATION "lib/cmake/protobuf"
+ COMPONENT protobuf-export)
diff --git a/cmake/protobuf-config-version.cmake.in b/cmake/protobuf-config-version.cmake.in
index 07ab40b9..1f171c66 100644
--- a/cmake/protobuf-config-version.cmake.in
+++ b/cmake/protobuf-config-version.cmake.in
@@ -1 +1 @@
-set(PACKAGE_VERSION @protobuf_VERSION@)
+set(PACKAGE_VERSION @protobuf_VERSION@)
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index 51d715cf..bb0997b8 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -1,27 +1,27 @@
-# Version info variables
-set(PROTOBUF_VERSION "@protobuf_VERSION@")
-set(PROTOBUF_VERSION_STRING "@protobuf_VERSION_STRING@")
-
-# Current dir
-get_filename_component(_PROTOBUF_PACKAGE_PREFIX
- "${CMAKE_CURRENT_LIST_FILE}" PATH)
-
-# Imported targets
-include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-targets.cmake")
-
-# Compute the installation prefix relative to this file.
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
- "${_PROTOBUF_PACKAGE_PREFIX}" PATH)
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
- "${_PROTOBUF_IMPORT_PREFIX}" PATH)
-get_filename_component(_PROTOBUF_IMPORT_PREFIX
- "${_PROTOBUF_IMPORT_PREFIX}" PATH)
-
-# CMake FindProtobuf module compatible file
-if(NOT DEFINED PROTOBUF_MODULE_COMPATIBLE OR "${PROTOBUF_MODULE_COMPATIBLE}")
- include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-module.cmake")
-endif()
-
-# Cleanup temporary variables.
-set(_PROTOBUF_PACKAGE_PREFIX)
-set(_PROTOBUF_IMPORT_PREFIX)
+# Version info variables
+set(PROTOBUF_VERSION "@protobuf_VERSION@")
+set(PROTOBUF_VERSION_STRING "@protobuf_VERSION_STRING@")
+
+# Current dir
+get_filename_component(_PROTOBUF_PACKAGE_PREFIX
+ "${CMAKE_CURRENT_LIST_FILE}" PATH)
+
+# Imported targets
+include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-targets.cmake")
+
+# Compute the installation prefix relative to this file.
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+ "${_PROTOBUF_PACKAGE_PREFIX}" PATH)
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+ "${_PROTOBUF_IMPORT_PREFIX}" PATH)
+get_filename_component(_PROTOBUF_IMPORT_PREFIX
+ "${_PROTOBUF_IMPORT_PREFIX}" PATH)
+
+# CMake FindProtobuf module compatible file
+if(NOT DEFINED PROTOBUF_MODULE_COMPATIBLE OR "${PROTOBUF_MODULE_COMPATIBLE}")
+ include("${_PROTOBUF_PACKAGE_PREFIX}/protobuf-module.cmake")
+endif()
+
+# Cleanup temporary variables.
+set(_PROTOBUF_PACKAGE_PREFIX)
+set(_PROTOBUF_IMPORT_PREFIX)
diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java
index 1d5d4e8a..0bd1750d 100644
--- a/java/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/src/main/java/com/google/protobuf/ByteString.java
@@ -294,10 +294,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* <b>Performance notes:</b> The returned {@code ByteString} is an
* immutable tree of byte arrays ("chunks") of the stream data. The
* first chunk is small, with subsequent chunks each being double
- * the size, up to 8K. If the caller knows the precise length of
- * the stream and wishes to avoid all unnecessary copies and
- * allocations, consider using the two-argument version of this
- * method, below.
+ * the size, up to 8K.
+ *
+ * <p>Each byte read from the input stream will be copied twice to ensure
+ * that the resulting ByteString is truly immutable.
*
* @param streamToDrain The source stream, which is read completely
* but not closed.
@@ -320,12 +320,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
*
* <b>Performance notes:</b> The returned {@code ByteString} is an
* immutable tree of byte arrays ("chunks") of the stream data. The
- * chunkSize parameter sets the size of these byte arrays. In
- * particular, if the chunkSize is precisely the same as the length
- * of the stream, unnecessary allocations and copies will be
- * avoided. Otherwise, the chunks will be of the given size, except
- * for the last chunk, which will be resized (via a reallocation and
- * copy) to contain the remainder of the stream.
+ * chunkSize parameter sets the size of these byte arrays.
+ *
+ * <p>Each byte read from the input stream will be copied twice to ensure
+ * that the resulting ByteString is truly immutable.
*
* @param streamToDrain The source stream, which is read completely
* but not closed.
@@ -386,6 +384,7 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
if (bytesRead == 0) {
return null;
} else {
+ // Always make a copy since InputStream could steal a reference to buf.
return ByteString.copyFrom(buf, 0, bytesRead);
}
}
@@ -736,7 +735,8 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
* returns the number of bytes remaining in the stream. The methods
* {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)}
* and {@link InputStream#skip(long)} will read/skip as many bytes as are
- * available.
+ * available. The method {@link InputStream#markSupported()} returns
+ * {@code true}.
* <p>
* The methods in the returned {@link InputStream} might <b>not</b> be
* thread safe.
diff --git a/java/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
index 954fde08..291bd20a 100644
--- a/java/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -30,9 +30,13 @@
package com.google.protobuf;
+import com.google.protobuf.Utf8.UnpairedSurrogateException;
+
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
/**
* Encodes and writes protocol message fields.
@@ -49,6 +53,10 @@ import java.nio.ByteBuffer;
* @author kneton@google.com Kenton Varda
*/
public final class CodedOutputStream {
+
+ private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
+
+ // TODO(dweis): Consider migrating to a ByteBuffer.
private final byte[] buffer;
private final int limit;
private int position;
@@ -415,15 +423,87 @@ public final class CodedOutputStream {
}
/** Write a {@code string} field to the stream. */
+ // TODO(dweis): Document behavior on ill-formed UTF-16 input.
public void writeStringNoTag(final String value) throws IOException {
+ try {
+ efficientWriteStringNoTag(value);
+ } catch (UnpairedSurrogateException e) {
+ logger.log(Level.WARNING,
+ "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", e);
+ inefficientWriteStringNoTag(value);
+ }
+ }
+
+ /** Write a {@code string} field to the stream. */
+ private void inefficientWriteStringNoTag(final String value) throws IOException {
// Unfortunately there does not appear to be any way to tell Java to encode
// UTF-8 directly into our buffer, so we have to let it create its own byte
// array and then copy.
+ // TODO(dweis): Consider using nio Charset methods instead.
final byte[] bytes = value.getBytes(Internal.UTF_8);
writeRawVarint32(bytes.length);
writeRawBytes(bytes);
}
+ /**
+ * Write a {@code string} field to the stream efficiently. If the {@code string} is malformed,
+ * this method rolls back its changes and throws an {@link UnpairedSurrogateException} with the
+ * intent that the caller will catch and retry with {@link #inefficientWriteStringNoTag(String)}.
+ *
+ * @param value the string to write to the stream
+ *
+ * @throws UnpairedSurrogateException when {@code value} is ill-formed UTF-16.
+ */
+ private void efficientWriteStringNoTag(final String value) throws IOException {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeRawVarint32Size(maxLength);
+
+ // If we are streaming and the potential length is too big to fit in our buffer, we take the
+ // slower path. Otherwise, we're good to try the fast path.
+ if (output != null && maxLengthVarIntSize + maxLength > limit - position) {
+ // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
+ // does the same internally and then does *another copy* to return a byte[] of exactly the
+ // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
+ // UTF-8 encoded bytes.
+ final byte[] encodedBytes = new byte[maxLength];
+ int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
+ writeRawVarint32(actualLength);
+ writeRawBytes(encodedBytes, 0, actualLength);
+ } else {
+ // Optimize for the case where we know this length results in a constant varint length as this
+ // saves a pass for measuring the length of the string.
+ final int minLengthVarIntSize = computeRawVarint32Size(value.length());
+ int oldPosition = position;
+ final int length;
+ try {
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ position = oldPosition + minLengthVarIntSize;
+ int newPosition = Utf8.encode(value, buffer, position, limit - position);
+ // Since this class is stateful and tracks the position, we rewind and store the state,
+ // prepend the length, then reset it back to the end of the string.
+ position = oldPosition;
+ length = newPosition - oldPosition - minLengthVarIntSize;
+ writeRawVarint32(length);
+ position = newPosition;
+ } else {
+ length = Utf8.encodedLength(value);
+ writeRawVarint32(length);
+ position = Utf8.encode(value, buffer, position, limit - position);
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Be extra careful and restore the original position for retrying the write with the less
+ // efficient path.
+ position = oldPosition;
+ throw e;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ totalBytesWritten += length;
+ }
+ }
+
/** Write a {@code group} field to the stream. */
public void writeGroupNoTag(final MessageLite value) throws IOException {
value.writeTo(this);
@@ -826,9 +906,16 @@ public final class CodedOutputStream {
* {@code string} field.
*/
public static int computeStringSizeNoTag(final String value) {
- final byte[] bytes = value.getBytes(Internal.UTF_8);
- return computeRawVarint32Size(bytes.length) +
- bytes.length;
+ int length;
+ try {
+ length = Utf8.encodedLength(value);
+ } catch (UnpairedSurrogateException e) {
+ // TODO(dweis): Consider using nio Charset methods instead.
+ final byte[] bytes = value.getBytes(Internal.UTF_8);
+ length = bytes.length;
+ }
+
+ return computeRawVarint32Size(length) + length;
}
/**
@@ -1007,9 +1094,15 @@ public final class CodedOutputStream {
public static class OutOfSpaceException extends IOException {
private static final long serialVersionUID = -6947486886997889499L;
+ private static final String MESSAGE =
+ "CodedOutputStream was writing to a flat byte array and ran out of space.";
+
OutOfSpaceException() {
- super("CodedOutputStream was writing to a flat byte array and ran " +
- "out of space.");
+ super(MESSAGE);
+ }
+
+ OutOfSpaceException(Throwable cause) {
+ super(MESSAGE, cause);
}
}
diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java
index 3658410c..fb9005bd 100644
--- a/java/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/src/main/java/com/google/protobuf/Descriptors.java
@@ -1118,9 +1118,9 @@ public final class Descriptors {
static {
// Refuse to init if someone added a new declared type.
if (Type.values().length != FieldDescriptorProto.Type.values().length) {
- throw new RuntimeException(
- "descriptor.proto has a new declared type but Desrciptors.java " +
- "wasn't updated.");
+ throw new RuntimeException(""
+ + "descriptor.proto has a new declared type but Descriptors.java "
+ + "wasn't updated.");
}
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
index 9457d999..d84fa75c 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -121,22 +121,44 @@ public abstract class GeneratedMessage extends AbstractMessage
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
- for (final FieldDescriptor field : descriptor.getFields()) {
- if (field.isRepeated()) {
- final List<?> value = (List<?>) getField(field);
- if (!value.isEmpty()) {
- result.put(field, value);
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
}
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
} else {
- if (hasField(field)) {
- if (getBytesForString
- && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
- result.put(field, getFieldRaw(field));
- } else {
- result.put(field, getField(field));
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
}
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
}
}
+ // Add the field to the map
+ if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ result.put(field, getFieldRaw(field));
+ } else {
+ result.put(field, getField(field));
+ }
}
return result;
}
@@ -398,17 +420,40 @@ public abstract class GeneratedMessage extends AbstractMessage
final TreeMap<FieldDescriptor, Object> result =
new TreeMap<FieldDescriptor, Object>();
final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
- for (final FieldDescriptor field : descriptor.getFields()) {
- if (field.isRepeated()) {
- final List value = (List) getField(field);
- if (!value.isEmpty()) {
- result.put(field, value);
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
}
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
} else {
- if (hasField(field)) {
- result.put(field, getField(field));
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
+ }
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
}
}
+ // Add the field to the map
+ result.put(field, getField(field));
}
return result;
}
@@ -2696,4 +2741,38 @@ public abstract class GeneratedMessage extends AbstractMessage
return (Extension<MessageType, T>) extension;
}
+
+ protected static int computeStringSize(final int fieldNumber, final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
+ } else {
+ return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static int computeStringSizeNoTag(final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSizeNoTag((String) value);
+ } else {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ }
+ }
+
+ protected static void writeString(
+ CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeString(fieldNumber, (String) value);
+ } else {
+ output.writeBytes(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static void writeStringNoTag(
+ CodedOutputStream output, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeStringNoTag((String) value);
+ } else {
+ output.writeBytesNoTag((ByteString) value);
+ }
+ }
}
diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index bd6bc463..a535b718 100644
--- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -48,7 +48,6 @@ 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}.
@@ -60,24 +59,6 @@ public abstract class GeneratedMessageLite<
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;
@@ -90,20 +71,17 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final Parser<MessageType> getParserForType() {
- return (Parser<MessageType>) PROTOTYPE_MAP
- .get(getClass()).getParserForType();
+ return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER);
}
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final MessageType getDefaultInstanceForType() {
- return (MessageType) PROTOTYPE_MAP
- .get(getClass()).getDefaultInstanceForType();
+ return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE);
}
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final BuilderType newBuilderForType() {
- return (BuilderType) PROTOTYPE_MAP
- .get(getClass()).newBuilderForType();
+ return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
}
/**
@@ -141,7 +119,9 @@ public abstract class GeneratedMessageLite<
MERGE_FROM,
MAKE_IMMUTABLE,
NEW_INSTANCE,
- NEW_BUILDER;
+ NEW_BUILDER,
+ GET_DEFAULT_INSTANCE,
+ GET_PARSER;
}
/**
@@ -168,9 +148,21 @@ public abstract class GeneratedMessageLite<
* <p>
* For use by generated code only.
*/
- protected abstract Object dynamicMethod(
- MethodToInvoke method,
- Object... args);
+ protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1);
+
+ /**
+ * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+ */
+ protected Object dynamicMethod(MethodToInvoke method, Object arg0) {
+ return dynamicMethod(method, arg0, null);
+ }
+
+ /**
+ * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+ */
+ protected Object dynamicMethod(MethodToInvoke method) {
+ return dynamicMethod(method, null, null);
+ }
/**
* Merge some unknown fields into the {@link UnknownFieldSetLite} for this
@@ -1059,18 +1051,22 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked")
protected Object readResolve() throws ObjectStreamException {
try {
- Class messageClass = Class.forName(messageClassName);
- Parser<?> parser =
- (Parser<?>) messageClass.getField("PARSER").get(null);
- return parser.parsePartialFrom(asBytes);
+ Class<?> messageClass = Class.forName(messageClassName);
+ java.lang.reflect.Field defaultInstanceField =
+ messageClass.getDeclaredField("DEFAULT_INSTANCE");
+ defaultInstanceField.setAccessible(true);
+ MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
+ return defaultInstance.newBuilderForType()
+ .mergeFrom(asBytes)
+ .buildPartial();
} catch (ClassNotFoundException e) {
- throw new RuntimeException("Unable to find proto buffer class", e);
+ throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
} catch (NoSuchFieldException e) {
- throw new RuntimeException("Unable to find PARSER", e);
+ throw new RuntimeException("Unable to find DEFAULT_INSTANCE in " + messageClassName, e);
} catch (SecurityException e) {
- throw new RuntimeException("Unable to call PARSER", e);
+ throw new RuntimeException("Unable to call DEFAULT_INSTANCE in " + messageClassName, e);
} catch (IllegalAccessException e) {
- throw new RuntimeException("Unable to call parseFrom method", e);
+ throw new RuntimeException("Unable to call parsePartialFrom", e);
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException("Unable to understand proto buffer", e);
}
@@ -1103,45 +1099,6 @@ public abstract class GeneratedMessageLite<
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();
- }
- }
/**
* A static helper method for checking if a message is initialized, optionally memoizing.
diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java
index 20054b79..fefda904 100644
--- a/java/src/main/java/com/google/protobuf/Internal.java
+++ b/java/src/main/java/com/google/protobuf/Internal.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import java.io.IOException;
+import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.AbstractList;
@@ -358,6 +359,17 @@ public class Internal {
}
}
+ @SuppressWarnings("unchecked")
+ public static <T extends MessageLite> T getDefaultInstance(Class<T> clazz) {
+ try {
+ Method method = clazz.getMethod("getDefaultInstance");
+ return (T) method.invoke(method);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failed to get default instance for " + clazz, e);
+ }
+ }
+
/**
* An empty byte array constant used in generated code.
*/
diff --git a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 367fa23b..0a761052 100644
--- a/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -69,7 +69,7 @@ public class InvalidProtocolBufferException extends IOException {
static InvalidProtocolBufferException truncatedMessage() {
return new InvalidProtocolBufferException(
"While parsing a protocol message, the input ended unexpectedly " +
- "in the middle of a field. This could mean either than the " +
+ "in the middle of a field. This could mean either that the " +
"input has been truncated or that an embedded message " +
"misreported its own length.");
}
diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
index a2997e1c..c3be3cca 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -215,6 +215,11 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
modCount++;
}
+ @Override
+ public Object getRaw(int index) {
+ return list.get(index);
+ }
+
// @Override
public ByteString getByteString(int index) {
Object o = list.get(index);
diff --git a/java/src/main/java/com/google/protobuf/LazyStringList.java b/java/src/main/java/com/google/protobuf/LazyStringList.java
index 235126b6..3eeedca1 100644
--- a/java/src/main/java/com/google/protobuf/LazyStringList.java
+++ b/java/src/main/java/com/google/protobuf/LazyStringList.java
@@ -56,7 +56,18 @@ public interface LazyStringList extends ProtocolStringList {
* ({@code index < 0 || index >= size()})
*/
ByteString getByteString(int index);
-
+
+ /**
+ * Returns the element at the specified position in this list as an Object
+ * that will either be a String or a ByteString.
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * ({@code index < 0 || index >= size()})
+ */
+ Object getRaw(int index);
+
/**
* Returns the element at the specified position in this list as byte[].
*
diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java
index fa0265e2..9516d71f 100644
--- a/java/src/main/java/com/google/protobuf/Message.java
+++ b/java/src/main/java/com/google/protobuf/Message.java
@@ -121,6 +121,9 @@ public interface Message extends MessageLite, MessageOrBuilder {
* using the same merging rules.<br>
* * For repeated fields, the elements in {@code other} are concatenated
* with the elements in this message.
+ * * For oneof groups, if the other message has one of the fields set,
+ * the group of this message is cleared and replaced by the field
+ * of the other message, so that the oneof constraint is preserved.
*
* This is equivalent to the {@code Message::MergeFrom} method in C++.
*/
diff --git a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index be737b1a..f91cdbce 100644
--- a/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/java/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -73,7 +73,7 @@ public class RepeatedFieldBuilder
private GeneratedMessage.BuilderParent parent;
// List of messages. Never null. It may be immutable, in which case
- // isMessagesListImmutable will be true. See note below.
+ // isMessagesListMutable will be false. See note below.
private List<MType> messages;
// Whether messages is an mutable array that can be modified.
diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
index 7ea84022..45d5fc35 100644
--- a/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
+++ b/java/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import java.io.IOException;
+import java.util.Arrays;
/**
* {@code UnknownFieldSetLite} is used to keep track of fields which were seen
@@ -45,8 +46,11 @@ import java.io.IOException;
*/
public final class UnknownFieldSetLite {
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
+ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+
private static final UnknownFieldSetLite DEFAULT_INSTANCE =
- new UnknownFieldSetLite(ByteString.EMPTY);
+ new UnknownFieldSetLite(0, EMPTY_INT_ARRAY, EMPTY_OBJECT_ARRAY);
/**
* Get an empty {@code UnknownFieldSetLite}.
@@ -71,19 +75,41 @@ public final class UnknownFieldSetLite {
* {@code second}.
*/
static UnknownFieldSetLite concat(UnknownFieldSetLite first, UnknownFieldSetLite second) {
- return new UnknownFieldSetLite(first.byteString.concat(second.byteString));
+ int count = first.count + second.count;
+ int[] tags = Arrays.copyOf(first.tags, count);
+ System.arraycopy(second.tags, 0, tags, first.count, second.count);
+ Object[] objects = Arrays.copyOf(first.objects, count);
+ System.arraycopy(second.objects, 0, objects, first.count, second.count);
+ return new UnknownFieldSetLite(count, tags, objects);
}
-
+
+ /**
+ * The number of elements in the set.
+ */
+ private int count;
+
+ /**
+ * The tag numbers for the elements in the set.
+ */
+ private int[] tags;
+
/**
- * The internal representation of the unknown fields.
+ * The boxed values of the elements in the set.
*/
- private final ByteString byteString;
+ private Object[] objects;
+
+ /**
+ * The lazily computed serialized size of the set.
+ */
+ private int memoizedSerializedSize = -1;
/**
- * Constructs the {@code UnknownFieldSetLite} as a thin wrapper around {@link ByteString}.
+ * Constructs the {@code UnknownFieldSetLite}.
*/
- private UnknownFieldSetLite(ByteString byteString) {
- this.byteString = byteString;
+ private UnknownFieldSetLite(int count, int[] tags, Object[] objects) {
+ this.count = count;
+ this.tags = tags;
+ this.objects = objects;
}
/**
@@ -92,17 +118,73 @@ public final class UnknownFieldSetLite {
* <p>For use by generated code only.
*/
public void writeTo(CodedOutputStream output) throws IOException {
- output.writeRawBytes(byteString);
+ for (int i = 0; i < count; i++) {
+ int tag = tags[i];
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ output.writeUInt64(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ output.writeFixed32(fieldNumber, (Integer) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ output.writeFixed64(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ output.writeBytes(fieldNumber, (ByteString) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+ ((UnknownFieldSetLite) objects[i]).writeTo(output);
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ break;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
}
-
/**
* Get the number of bytes required to encode this set.
*
* <p>For use by generated code only.
*/
public int getSerializedSize() {
- return byteString.size();
+ int size = memoizedSerializedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ size = 0;
+ for (int i = 0; i < count; i++) {
+ int tag = tags[i];
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ size += CodedOutputStream.computeUInt64Size(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ size += CodedOutputStream.computeFixed32Size(fieldNumber, (Integer) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ size += CodedOutputStream.computeFixed64Size(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ size += CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ size += CodedOutputStream.computeTagSize(fieldNumber) * 2
+ + ((UnknownFieldSetLite) objects[i]).getSerializedSize();
+ break;
+ default:
+ throw new IllegalStateException(InvalidProtocolBufferException.invalidWireType());
+ }
+ }
+
+ memoizedSerializedSize = size;
+
+ return size;
}
@Override
@@ -111,16 +193,34 @@ public final class UnknownFieldSetLite {
return true;
}
- if (obj instanceof UnknownFieldSetLite) {
- return byteString.equals(((UnknownFieldSetLite) obj).byteString);
+ if (obj == null) {
+ return false;
+ }
+
+ if (!(obj instanceof UnknownFieldSetLite)) {
+ return false;
+ }
+
+ UnknownFieldSetLite other = (UnknownFieldSetLite) obj;
+ if (count != other.count
+ // TODO(dweis): Only have to compare up to count but at worst 2x worse than we need to do.
+ || !Arrays.equals(tags, other.tags)
+ || !Arrays.deepEquals(objects, other.objects)) {
+ return false;
}
- return false;
+ return true;
}
@Override
public int hashCode() {
- return byteString.hashCode();
+ int hashCode = 17;
+
+ hashCode = 31 * hashCode + count;
+ hashCode = 31 * hashCode + Arrays.hashCode(tags);
+ hashCode = 31 * hashCode + Arrays.deepHashCode(objects);
+
+ return hashCode;
}
/**
@@ -131,28 +231,49 @@ public final class UnknownFieldSetLite {
* <p>For use by generated code only.
*/
public static final class Builder {
+
+ // Arbitrarily chosen.
+ // TODO(dweis): Tune this number?
+ private static final int MIN_CAPACITY = 8;
+
+ private int count = 0;
+ private int[] tags = EMPTY_INT_ARRAY;
+ private Object[] objects = EMPTY_OBJECT_ARRAY;
- private ByteString.Output byteStringOutput;
- private CodedOutputStream output;
private boolean built;
/**
- * Constructs a {@code Builder}. Lazily initialized by
- * {@link #ensureInitializedButNotBuilt()}.
+ * Constructs a {@code Builder}.
*/
private Builder() {}
/**
* Ensures internal state is initialized for use.
*/
- private void ensureInitializedButNotBuilt() {
+ private void ensureNotBuilt() {
if (built) {
throw new IllegalStateException("Do not reuse UnknownFieldSetLite Builders.");
}
-
- if (output == null && byteStringOutput == null) {
- byteStringOutput = ByteString.newOutput(100 /* initialCapacity */);
- output = CodedOutputStream.newInstance(byteStringOutput);
+ }
+
+ private void storeField(int tag, Object value) {
+ ensureCapacity();
+
+ tags[count] = tag;
+ objects[count] = value;
+ count++;
+ }
+
+ /**
+ * Ensures that our arrays are long enough to store more metadata.
+ */
+ private void ensureCapacity() {
+ if (count == tags.length) {
+ int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1;
+ int newLength = count + increment;
+
+ tags = Arrays.copyOf(tags, newLength);
+ objects = Arrays.copyOf(objects, newLength);
}
}
@@ -166,31 +287,28 @@ public final class UnknownFieldSetLite {
*/
public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
throws IOException {
- ensureInitializedButNotBuilt();
+ ensureNotBuilt();
final int fieldNumber = WireFormat.getTagFieldNumber(tag);
switch (WireFormat.getTagWireType(tag)) {
case WireFormat.WIRETYPE_VARINT:
- output.writeUInt64(fieldNumber, input.readInt64());
+ storeField(tag, input.readInt64());
return true;
case WireFormat.WIRETYPE_FIXED32:
- output.writeFixed32(fieldNumber, input.readFixed32());
+ storeField(tag, input.readFixed32());
return true;
case WireFormat.WIRETYPE_FIXED64:
- output.writeFixed64(fieldNumber, input.readFixed64());
+ storeField(tag, input.readFixed64());
return true;
case WireFormat.WIRETYPE_LENGTH_DELIMITED:
- output.writeBytes(fieldNumber, input.readBytes());
+ storeField(tag, input.readBytes());
return true;
case WireFormat.WIRETYPE_START_GROUP:
final Builder subBuilder = newBuilder();
subBuilder.mergeFrom(input);
input.checkLastTagWas(
WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
-
- output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
- subBuilder.build().writeTo(output);
- output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ storeField(tag, subBuilder.build());
return true;
case WireFormat.WIRETYPE_END_GROUP:
return false;
@@ -210,12 +328,10 @@ public final class UnknownFieldSetLite {
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
- ensureInitializedButNotBuilt();
- try {
- output.writeUInt64(fieldNumber, value);
- } catch (IOException e) {
- // Should never happen.
- }
+ ensureNotBuilt();
+
+ storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value);
+
return this;
}
@@ -229,11 +345,24 @@ public final class UnknownFieldSetLite {
if (fieldNumber == 0) {
throw new IllegalArgumentException("Zero is not a valid field number.");
}
- ensureInitializedButNotBuilt();
- try {
- output.writeBytes(fieldNumber, value);
- } catch (IOException e) {
- // Should never happen.
+ ensureNotBuilt();
+
+ storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
+
+ return this;
+ }
+
+ /**
+ * Parse an entire message from {@code input} and merge its fields into
+ * this set.
+ */
+ private Builder mergeFrom(final CodedInputStream input) throws IOException {
+ // Ensures initialization in mergeFieldFrom.
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0 || !mergeFieldFrom(tag, input)) {
+ break;
+ }
}
return this;
}
@@ -254,44 +383,12 @@ public final class UnknownFieldSetLite {
}
built = true;
-
- final UnknownFieldSetLite result;
- // If we were never initialized, no data was written.
- if (output == null) {
- result = getDefaultInstance();
- } else {
- try {
- output.flush();
- } catch (IOException e) {
- // Should never happen.
- }
- ByteString byteString = byteStringOutput.toByteString();
- if (byteString.isEmpty()) {
- result = getDefaultInstance();
- } else {
- result = new UnknownFieldSetLite(byteString);
- }
+
+ if (count == 0) {
+ return DEFAULT_INSTANCE;
}
- // Allow for garbage collection.
- output = null;
- byteStringOutput = null;
- return result;
- }
-
- /**
- * Parse an entire message from {@code input} and merge its fields into
- * this set.
- */
- private Builder mergeFrom(final CodedInputStream input) throws IOException {
- // Ensures initialization in mergeFieldFrom.
- while (true) {
- final int tag = input.readTag();
- if (tag == 0 || !mergeFieldFrom(tag, input)) {
- break;
- }
- }
- return this;
+ return new UnknownFieldSetLite(count, tags, objects);
}
}
}
diff --git a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
index 5cc005df..5257c5a2 100644
--- a/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
+++ b/java/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -57,6 +57,11 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
public String get(int index) {
return list.get(index);
}
+
+ @Override
+ public Object getRaw(int index) {
+ return list.getRaw(index);
+ }
@Override
public int size() {
diff --git a/java/src/main/java/com/google/protobuf/Utf8.java b/java/src/main/java/com/google/protobuf/Utf8.java
index 4271b41b..0699778f 100644
--- a/java/src/main/java/com/google/protobuf/Utf8.java
+++ b/java/src/main/java/com/google/protobuf/Utf8.java
@@ -66,6 +66,12 @@ package com.google.protobuf;
*/
final class Utf8 {
private Utf8() {}
+
+ /**
+ * Maximum number of bytes per Java UTF-16 char in UTF-8.
+ * @see java.nio.charset.CharsetEncoder#maxBytesPerChar()
+ */
+ static final int MAX_BYTES_PER_CHAR = 3;
/**
* State value indicating that the byte sequence is well-formed and
@@ -346,4 +352,130 @@ final class Utf8 {
default: throw new AssertionError();
}
}
+
+
+ // These UTF-8 handling methods are copied from Guava's Utf8 class with a modification to throw
+ // a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can
+ // fallback to more lenient behavior.
+
+ static class UnpairedSurrogateException extends IllegalArgumentException {
+
+ private UnpairedSurrogateException(int index) {
+ super("Unpaired surrogate at index " + index);
+ }
+ }
+
+ /**
+ * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+ * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+ * both time and space.
+ *
+ * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+ * surrogates)
+ */
+ static int encodedLength(CharSequence sequence) {
+ // Warning to maintainers: this implementation is highly optimized.
+ int utf16Length = sequence.length();
+ int utf8Length = utf16Length;
+ int i = 0;
+
+ // This loop optimizes for pure ASCII.
+ while (i < utf16Length && sequence.charAt(i) < 0x80) {
+ i++;
+ }
+
+ // This loop optimizes for chars less than 0x800.
+ for (; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += ((0x7f - c) >>> 31); // branch free!
+ } else {
+ utf8Length += encodedLengthGeneral(sequence, i);
+ break;
+ }
+ }
+
+ if (utf8Length < utf16Length) {
+ // Necessary and sufficient condition for overflow because of maximum 3x expansion
+ throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+ + (utf8Length + (1L << 32)));
+ }
+ return utf8Length;
+ }
+
+ private static int encodedLengthGeneral(CharSequence sequence, int start) {
+ int utf16Length = sequence.length();
+ int utf8Length = 0;
+ for (int i = start; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += (0x7f - c) >>> 31; // branch free!
+ } else {
+ utf8Length += 2;
+ // jdk7+: if (Character.isSurrogate(c)) {
+ if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+ // Check that we have a well-formed surrogate pair.
+ int cp = Character.codePointAt(sequence, i);
+ if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ throw new UnpairedSurrogateException(i);
+ }
+ i++;
+ }
+ }
+ }
+ return utf8Length;
+ }
+
+ static int encode(CharSequence sequence, byte[] bytes, int offset, int length) {
+ int utf16Length = sequence.length();
+ int j = offset;
+ int i = 0;
+ int limit = offset + length;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) {
+ bytes[j + i] = (byte) c;
+ }
+ if (i == utf16Length) {
+ return j + utf16Length;
+ }
+ j += i;
+ for (char c; i < utf16Length; i++) {
+ c = sequence.charAt(i);
+ if (c < 0x80 && j < limit) {
+ bytes[j++] = (byte) c;
+ } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
+ bytes[j++] = (byte) ((0xF << 6) | (c >>> 6));
+ bytes[j++] = (byte) (0x80 | (0x3F & c));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ bytes[j++] = (byte) ((0xF << 5) | (c >>> 12));
+ bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
+ bytes[j++] = (byte) (0x80 | (0x3F & c));
+ } else if (j <= limit - 4) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes
+ final char low;
+ if (i + 1 == sequence.length()
+ || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
+ throw new UnpairedSurrogateException((i - 1));
+ }
+ int codePoint = Character.toCodePoint(c, low);
+ bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
+ bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+ bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+ bytes[j++] = (byte) (0x80 | (0x3F & codePoint));
+ } else {
+ // If we are surrogates and we're not a surrogate pair, always throw an
+ // IllegalArgumentException instead of an ArrayOutOfBoundsException.
+ if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE)
+ && (i + 1 == sequence.length()
+ || !Character.isSurrogatePair(c, sequence.charAt(i + 1)))) {
+ throw new UnpairedSurrogateException(i);
+ }
+ throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+ }
+ }
+ return j;
+ }
+ // End Guava UTF-8 methods.
}
diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java
index ba83b666..8dbe1ae3 100644
--- a/java/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/src/main/java/com/google/protobuf/WireFormat.java
@@ -58,7 +58,7 @@ public final class WireFormat {
static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
/** Given a tag value, determines the wire type (the lower 3 bits). */
- static int getTagWireType(final int tag) {
+ public static int getTagWireType(final int tag) {
return tag & TAG_TYPE_MASK;
}
diff --git a/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
index 1562a1a6..447e6ef3 100644
--- a/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -85,6 +85,7 @@ public class BoundedByteStringTest extends LiteralByteStringTest {
testString.substring(2, testString.length() - 6), roundTripString);
}
+ @Override
public void testJavaSerialization() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
diff --git a/java/src/test/java/com/google/protobuf/CheckUtf8Test.java b/java/src/test/java/com/google/protobuf/CheckUtf8Test.java
index 6470e9ca..3d6381c9 100644
--- a/java/src/test/java/com/google/protobuf/CheckUtf8Test.java
+++ b/java/src/test/java/com/google/protobuf/CheckUtf8Test.java
@@ -58,8 +58,7 @@ public class CheckUtf8Test extends TestCase {
public void testParseRequiredStringWithGoodUtf8() throws Exception {
ByteString serialized =
BytesWrapper.newBuilder().setReq(UTF8_BYTE_STRING).build().toByteString();
- assertEquals(UTF8_BYTE_STRING_TEXT,
- StringWrapper.PARSER.parseFrom(serialized).getReq());
+ assertEquals(UTF8_BYTE_STRING_TEXT, StringWrapper.parser().parseFrom(serialized).getReq());
}
public void testBuildRequiredStringWithBadUtf8() throws Exception {
@@ -93,7 +92,7 @@ public class CheckUtf8Test extends TestCase {
ByteString serialized =
BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
try {
- StringWrapper.PARSER.parseFrom(serialized);
+ StringWrapper.parser().parseFrom(serialized);
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
@@ -131,7 +130,7 @@ public class CheckUtf8Test extends TestCase {
ByteString serialized =
BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
try {
- StringWrapperSize.PARSER.parseFrom(serialized);
+ StringWrapperSize.parser().parseFrom(serialized);
fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
} catch (InvalidProtocolBufferException exception) {
assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
diff --git a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
index 365789c0..360e759e 100644
--- a/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
+++ b/java/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -40,6 +40,7 @@ import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -325,10 +326,41 @@ public class CodedOutputStreamTest extends TestCase {
for (int i = 0; i < 1024; ++i) {
codedStream.writeRawBytes(value, 0, value.length);
}
+ String string =
+ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+ // Ensure we take the slower fast path.
+ assertTrue(CodedOutputStream.computeRawVarint32Size(string.length())
+ != CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+
+ codedStream.writeStringNoTag(string);
+ int stringSize = CodedOutputStream.computeStringSizeNoTag(string);
+
// Make sure we have written more bytes than the buffer could hold. This is
// to make the test complete.
assertTrue(codedStream.getTotalBytesWritten() > BUFFER_SIZE);
- assertEquals(value.length * 1024, codedStream.getTotalBytesWritten());
+
+ // Verify that the total bytes written is correct
+ assertEquals((value.length * 1024) + stringSize, codedStream.getTotalBytesWritten());
+ }
+
+ // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that covers more than just
+ // this case.
+ public void testWriteStringNoTag_fastpath() throws Exception {
+ int bufferSize = 153;
+ String threeBytesPer = "\u0981";
+ String string = threeBytesPer;
+ for (int i = 0; i < 50; i++) {
+ string += threeBytesPer;
+ }
+ // These checks ensure we will tickle the slower fast path.
+ assertEquals(1, CodedOutputStream.computeRawVarint32Size(string.length()));
+ assertEquals(
+ 2, CodedOutputStream.computeRawVarint32Size(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+ assertEquals(bufferSize, string.length() * Utf8.MAX_BYTES_PER_CHAR);
+
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(ByteBuffer.allocate(bufferSize), bufferSize);
+ output.writeStringNoTag(string);
}
public void testWriteToByteBuffer() throws Exception {
@@ -398,4 +430,80 @@ public class CodedOutputStreamTest extends TestCase {
assertEqualBytes(bytes(0x02, 0x33, 0x44, 0x00), destination);
assertEquals(3, codedStream.getTotalBytesWritten());
}
+
+ public void testSerializeInvalidUtf8() throws Exception {
+ String[] invalidStrings = new String[] {
+ newString(Character.MIN_HIGH_SURROGATE),
+ "foobar" + newString(Character.MIN_HIGH_SURROGATE),
+ newString(Character.MIN_LOW_SURROGATE),
+ "foobar" + newString(Character.MIN_LOW_SURROGATE),
+ newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)
+ };
+
+ CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream());
+ CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]);
+ for (String s : invalidStrings) {
+ // TODO(dweis): These should all fail; instead they are corrupting data.
+ CodedOutputStream.computeStringSizeNoTag(s);
+ outputWithStream.writeStringNoTag(s);
+ outputWithArray.writeStringNoTag(s);
+ }
+ }
+
+ private static String newString(char... chars) {
+ return new String(chars);
+ }
+
+ /** Regression test for https://github.com/google/protobuf/issues/292 */
+ public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception {
+ String testCase = "Foooooooo";
+ assertEquals(CodedOutputStream.computeRawVarint32Size(testCase.length()),
+ CodedOutputStream.computeRawVarint32Size(testCase.length() * 3));
+ assertEquals(11, CodedOutputStream.computeStringSize(1, testCase));
+ // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes.
+ // An array of size 1 will cause a failure when trying to write the varint.
+ for (int i = 0; i < 11; i++) {
+ CodedOutputStream output = CodedOutputStream.newInstance(new byte[i]);
+ try {
+ output.writeString(1, testCase);
+ fail("Should have thrown an out of space exception");
+ } catch (CodedOutputStream.OutOfSpaceException expected) {}
+ }
+ }
+
+ public void testDifferentStringLengths() throws Exception {
+ // Test string serialization roundtrip using strings of the following lengths,
+ // with ASCII and Unicode characters requiring different UTF-8 byte counts per
+ // char, hence causing the length delimiter varint to sometimes require more
+ // bytes for the Unicode strings than the ASCII string of the same length.
+ int[] lengths = new int[] {
+ 0,
+ 1,
+ (1 << 4) - 1, // 1 byte for ASCII and Unicode
+ (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode
+ (1 << 11) - 1, // 2 bytes for ASCII and Unicode
+ (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
+ (1 << 17) - 1, // 3 bytes for ASCII and Unicode
+ };
+ for (int i : lengths) {
+ testEncodingOfString('q', i); // 1 byte per char
+ testEncodingOfString('\u07FF', i); // 2 bytes per char
+ testEncodingOfString('\u0981', i); // 3 bytes per char
+ }
+ }
+
+ private void testEncodingOfString(char c, int length) throws Exception {
+ String fullString = fullString(c, length);
+ TestAllTypes testAllTypes = TestAllTypes.newBuilder()
+ .setOptionalString(fullString)
+ .build();
+ assertEquals(
+ fullString, TestAllTypes.parseFrom(testAllTypes.toByteArray()).getOptionalString());
+ }
+
+ private String fullString(char c, int length) {
+ char[] result = new char[length];
+ Arrays.fill(result, c);
+ return new String(result);
+ }
}
diff --git a/java/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
index acf2b023..eaeec0b8 100644
--- a/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
+++ b/java/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -142,6 +142,16 @@ public class FieldPresenceTest extends TestCase {
"OneofNestedMessage"));
}
+ public void testOneofEquals() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message1 = builder.build();
+ // Set message2's oneof_uint32 field to defalut value. The two
+ // messages should be different when check with oneof case.
+ builder.setOneofUint32(0);
+ TestAllTypes message2 = builder.build();
+ assertFalse(message1.equals(message2));
+ }
+
public void testFieldPresence() {
// Optional non-message fields set to their default value are treated the
// same way as not set.
diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 2bd8d1a9..70812b95 100644
--- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -187,8 +187,7 @@ public class GeneratedMessageTest extends TestCase {
}
public void testParsedMessagesAreImmutable() throws Exception {
- TestAllTypes value = TestAllTypes.PARSER.parseFrom(
- TestUtil.getAllSet().toByteString());
+ TestAllTypes value = TestAllTypes.parser().parseFrom(TestUtil.getAllSet().toByteString());
assertIsUnmodifiable(value.getRepeatedInt32List());
assertIsUnmodifiable(value.getRepeatedInt64List());
assertIsUnmodifiable(value.getRepeatedUint32List());
diff --git a/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
index acd18003..0ef414aa 100644
--- a/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
+++ b/java/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -89,7 +89,7 @@ public class LazyStringEndToEndTest extends TestCase {
TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
ByteString.copyFrom(sink));
}
-
+
public void testCaching() {
String a = "a";
String b = "b";
@@ -106,24 +106,13 @@ public class LazyStringEndToEndTest extends TestCase {
assertSame(c, proto.getRepeatedString(1));
- // There's no way to directly observe that the ByteString is cached
- // correctly on serialization, but we can observe that it had to recompute
- // the string after serialization.
+ // Ensure serialization keeps strings cached.
proto.toByteString();
- String aPrime = proto.getOptionalString();
- assertNotSame(a, aPrime);
- assertEquals(a, aPrime);
- String bPrime = proto.getRepeatedString(0);
- assertNotSame(b, bPrime);
- assertEquals(b, bPrime);
- String cPrime = proto.getRepeatedString(1);
- assertNotSame(c, cPrime);
- assertEquals(c, cPrime);
// And now the string should stay cached.
- assertSame(aPrime, proto.getOptionalString());
- assertSame(bPrime, proto.getRepeatedString(0));
- assertSame(cPrime, proto.getRepeatedString(1));
+ assertSame(a, proto.getOptionalString());
+ assertSame(b, proto.getRepeatedString(0));
+ assertSame(c, proto.getRepeatedString(1));
}
public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java
index 8c3b5e5c..b1f298ff 100644
--- a/java/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteTest.java
@@ -42,6 +42,7 @@ import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage;
import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder;
import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
import junit.framework.TestCase;
@@ -1400,6 +1401,8 @@ public class LiteTest extends TestCase {
assertEquals("hi", messageAfterBuild.getOneofString());
assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase());
assertEquals(1, builder.getOneofUint32());
+ TestAllTypesLiteOrBuilder messageOrBuilder = builder;
+ assertEquals(OneofFieldCase.ONEOF_UINT32, messageOrBuilder.getOneofFieldCase());
TestAllExtensionsLite.Builder extendableMessageBuilder =
TestAllExtensionsLite.newBuilder();
diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
index 958b6a7e..7dfda2ae 100644
--- a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -34,6 +34,7 @@ import junit.framework.TestCase;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
@@ -209,6 +210,62 @@ public class LiteralByteStringTest extends TestCase {
Arrays.equals(referenceBytes, myBuffer.array()));
}
+ public void testMarkSupported() {
+ InputStream stream = stringUnderTest.newInput();
+ assertTrue(classUnderTest + ".newInput() must support marking", stream.markSupported());
+ }
+
+ public void testMarkAndReset() throws IOException {
+ int fraction = stringUnderTest.size() / 3;
+
+ InputStream stream = stringUnderTest.newInput();
+ stream.mark(stringUnderTest.size()); // First, mark() the end.
+
+ skipFully(stream, fraction); // Skip a large fraction, but not all.
+ int available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the 'middle', half the bytes are available",
+ (stringUnderTest.size() - fraction) == available);
+ stream.reset();
+
+ skipFully(stream, stringUnderTest.size()); // Skip to the end.
+ available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the end, no more bytes are available",
+ 0 == available);
+ }
+
+ /**
+ * Discards {@code n} bytes of data from the input stream. This method
+ * will block until the full amount has been skipped. Does not close the
+ * stream.
+ * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+ *
+ * @param in the input stream to read from
+ * @param n the number of bytes to skip
+ * @throws EOFException if this stream reaches the end before skipping all
+ * the bytes
+ * @throws IOException if an I/O error occurs, or the stream does not
+ * support skipping
+ */
+ static void skipFully(InputStream in, long n) throws IOException {
+ long toSkip = n;
+ while (n > 0) {
+ long amt = in.skip(n);
+ if (amt == 0) {
+ // Force a blocking read to avoid infinite loop
+ if (in.read() == -1) {
+ long skipped = toSkip - n;
+ throw new EOFException("reached end of stream after skipping "
+ + skipped + " bytes; " + toSkip + " bytes expected");
+ }
+ n--;
+ } else {
+ n -= amt;
+ }
+ }
+ }
+
public void testAsReadOnlyByteBuffer() {
ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
byte[] roundTripBytes = new byte[referenceBytes.length];
@@ -305,13 +362,13 @@ public class LiteralByteStringTest extends TestCase {
assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
}
- public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException{
+ public void testToString_returnsCanonicalEmptyString() {
assertSame(classUnderTest + " must be the same string references",
ByteString.EMPTY.toString(Internal.UTF_8),
new LiteralByteString(new byte[]{}).toString(Internal.UTF_8));
}
- public void testToString_raisesException() throws UnsupportedEncodingException{
+ public void testToString_raisesException() {
try {
ByteString.EMPTY.toString("invalid");
fail("Should have thrown an exception.");
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
index 6cff689f..3d8c9bc4 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -74,6 +74,16 @@ public class MapForProto2LiteTest extends TestCase {
builder.getMutableStringToInt32Field().put("3", 33);
}
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
private void assertMapValuesSet(TestMap message) {
assertEquals(3, message.getInt32ToInt32Field().size());
assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
@@ -330,26 +340,36 @@ public class MapForProto2LiteTest extends TestCase {
assertMapValuesCleared(message);
}
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ 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());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesUpdated(message);
builder = message.toBuilder();
builder.clear();
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesCleared(message);
}
diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
index 7e984040..1fa3cbdb 100644
--- a/java/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -78,6 +78,16 @@ public class MapForProto2Test extends TestCase {
builder.getMutableStringToInt32Field().put("3", 33);
}
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
private void assertMapValuesSet(TestMap message) {
assertEquals(3, message.getInt32ToInt32Field().size());
assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
@@ -310,26 +320,36 @@ public class MapForProto2Test extends TestCase {
assertMapValuesCleared(message);
}
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ 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());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesUpdated(message);
builder = message.toBuilder();
builder.clear();
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesCleared(message);
}
diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java
index 0509be15..0e5c1284 100644
--- a/java/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/src/test/java/com/google/protobuf/MapTest.java
@@ -79,6 +79,16 @@ public class MapTest extends TestCase {
builder.getMutableStringToInt32Field().put("3", 33);
}
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
private void assertMapValuesSet(TestMap message) {
assertEquals(3, message.getInt32ToInt32Field().size());
assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
@@ -311,26 +321,52 @@ public class MapTest extends TestCase {
assertMapValuesCleared(message);
}
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
+ public void testPutAllForUnknownEnumValues() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(0, 0);
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(1, 1);
+ sourceBuilder.getMutableInt32ToEnumFieldValue().put(2, 1000); // unknown value.
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destinationBuilder = TestMap.newBuilder();
+ destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue());
+ TestMap destination = destinationBuilder.build();
+
+ assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
+ assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
+ assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
+ }
+
public void testSerializeAndParse() throws Exception {
TestMap.Builder builder = TestMap.newBuilder();
setMapValues(builder);
TestMap message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ 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());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesUpdated(message);
builder = message.toBuilder();
builder.clear();
message = builder.build();
assertEquals(message.getSerializedSize(), message.toByteString().size());
- message = TestMap.PARSER.parseFrom(message.toByteString());
+ message = TestMap.parser().parseFrom(message.toByteString());
assertMapValuesCleared(message);
}
diff --git a/java/src/test/java/com/google/protobuf/ParserTest.java b/java/src/test/java/com/google/protobuf/ParserTest.java
index b11d8cb9..5a92bacf 100644
--- a/java/src/test/java/com/google/protobuf/ParserTest.java
+++ b/java/src/test/java/com/google/protobuf/ParserTest.java
@@ -58,8 +58,7 @@ import java.io.InputStream;
public class ParserTest extends TestCase {
public void testGeneratedMessageParserSingleton() throws Exception {
for (int i = 0; i < 10; i++) {
- assertEquals(TestAllTypes.PARSER,
- TestUtil.getAllSet().getParserForType());
+ assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType());
}
}
@@ -125,8 +124,7 @@ public class ParserTest extends TestCase {
public void testParsePartial() throws Exception {
- assertParsePartial(TestRequired.PARSER,
- TestRequired.newBuilder().setA(1).buildPartial());
+ assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
}
private <T extends MessageLite> void assertParsePartial(
@@ -216,8 +214,8 @@ public class ParserTest extends TestCase {
public void testParseUnknownFields() throws Exception {
// All fields will be treated as unknown fields in emptyMessage.
- TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom(
- TestUtil.getAllSet().toByteString());
+ TestEmptyMessage emptyMessage =
+ TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString());
assertEquals(
TestUtil.getAllSet().toByteString(),
emptyMessage.toByteString());
@@ -298,8 +296,7 @@ public class ParserTest extends TestCase {
// Parse TestParsingMerge.
ExtensionRegistry registry = ExtensionRegistry.newInstance();
UnittestProto.registerAllExtensions(registry);
- TestParsingMerge parsingMerge =
- TestParsingMerge.PARSER.parseFrom(data, registry);
+ TestParsingMerge parsingMerge = TestParsingMerge.parser().parseFrom(data, registry);
// Required and optional fields should be merged.
assertMessageMerged(parsingMerge.getRequiredAllTypes());
@@ -361,8 +358,7 @@ public class ParserTest extends TestCase {
// Parse TestParsingMergeLite.
ExtensionRegistry registry = ExtensionRegistry.newInstance();
UnittestLite.registerAllExtensions(registry);
- TestParsingMergeLite parsingMerge =
- TestParsingMergeLite.PARSER.parseFrom(data, registry);
+ TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry);
// Required and optional fields should be merged.
assertMessageMerged(parsingMerge.getRequiredAllTypes());
diff --git a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
index bd0d15e3..4ec3a409 100644
--- a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
+++ b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -119,7 +119,7 @@ public class RopeByteStringTest extends LiteralByteStringTest {
}
@Override
- public void testCharsetToString() throws UnsupportedEncodingException {
+ public void testCharsetToString() {
String sourceString = "I love unicode \u1234\u5678 characters";
ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
int copies = 250;
@@ -145,14 +145,15 @@ public class RopeByteStringTest extends LiteralByteStringTest {
}
@Override
- public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException {
+ public void testToString_returnsCanonicalEmptyString() {
RopeByteString ropeByteString =
RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
assertSame(classUnderTest + " must be the same string references",
ByteString.EMPTY.toString(Internal.UTF_8), ropeByteString.toString(Internal.UTF_8));
}
- public void testToString_raisesException() throws UnsupportedEncodingException{
+ @Override
+ public void testToString_raisesException() {
try {
ByteString byteString =
RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
@@ -172,6 +173,7 @@ public class RopeByteStringTest extends LiteralByteStringTest {
}
}
+ @Override
public void testJavaSerialization() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
diff --git a/java/src/test/java/com/google/protobuf/TestUtil.java b/java/src/test/java/com/google/protobuf/TestUtil.java
index 19a96d0e..792e8665 100644
--- a/java/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/src/test/java/com/google/protobuf/TestUtil.java
@@ -732,6 +732,7 @@ public final class TestUtil {
Assert.assertEquals("424", message.getDefaultStringPiece());
Assert.assertEquals("425", message.getDefaultCord());
+ Assert.assertEquals(TestAllTypes.OneofFieldCase.ONEOF_BYTES, message.getOneofFieldCase());
Assert.assertFalse(message.hasOneofUint32());
Assert.assertFalse(message.hasOneofNestedMessage());
Assert.assertFalse(message.hasOneofString());
diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java
index 5d846646..8294b865 100644
--- a/java/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -32,7 +32,6 @@ package com.google.protobuf;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
-import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
import protobuf_unittest.UnittestProto.OneString;
@@ -41,6 +40,7 @@ import protobuf_unittest.UnittestProto.TestAllTypes;
import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
import protobuf_unittest.UnittestProto.TestEmptyMessage;
import protobuf_unittest.UnittestProto.TestOneof2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
import junit.framework.TestCase;
diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
index 93a5ee22..8c9dcafe 100644
--- a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
+++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
@@ -461,7 +461,7 @@ public class UnknownFieldSetTest extends TestCase {
TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet();
ByteString allExtensionsData = allExtensions.toByteString();
UnittestLite.TestEmptyMessageLite emptyMessageLite =
- UnittestLite.TestEmptyMessageLite.PARSER.parseFrom(allExtensionsData);
+ UnittestLite.TestEmptyMessageLite.parser().parseFrom(allExtensionsData);
ByteString data = emptyMessageLite.toByteString();
TestAllExtensions message =
TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
diff --git a/java/src/test/java/com/google/protobuf/WireFormatTest.java b/java/src/test/java/com/google/protobuf/WireFormatTest.java
index 6858524e..0175005d 100644
--- a/java/src/test/java/com/google/protobuf/WireFormatTest.java
+++ b/java/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -44,10 +44,10 @@ import protobuf_unittest.UnittestProto.TestOneof2;
import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible;
import protobuf_unittest.UnittestProto.TestPackedExtensions;
import protobuf_unittest.UnittestProto.TestPackedTypes;
-import protobuf_unittest.UnittestMset.TestMessageSet;
import protobuf_unittest.UnittestMset.RawMessageSet;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
index 72c2fa01..9c8275eb 100755
--- a/python/google/protobuf/internal/containers.py
+++ b/python/google/protobuf/internal/containers.py
@@ -41,6 +41,7 @@ are:
__author__ = 'petar@google.com (Petar Petrov)'
+import collections
import sys
if sys.version_info[0] < 3:
@@ -63,7 +64,6 @@ if sys.version_info[0] < 3:
# Note: deriving from object is critical. It is the only thing that makes
# this a true type, allowing us to derive from it in C++ cleanly and making
# __slots__ properly disallow arbitrary element assignment.
- from collections import Mapping as _Mapping
class Mapping(object):
__slots__ = ()
@@ -106,7 +106,7 @@ if sys.version_info[0] < 3:
__hash__ = None
def __eq__(self, other):
- if not isinstance(other, _Mapping):
+ if not isinstance(other, collections.Mapping):
return NotImplemented
return dict(self.items()) == dict(other.items())
@@ -173,12 +173,13 @@ if sys.version_info[0] < 3:
self[key] = default
return default
- _Mapping.register(Mapping)
+ collections.Mapping.register(Mapping)
+ collections.MutableMapping.register(MutableMapping)
else:
# In Python 3 we can just use MutableMapping directly, because it defines
# __slots__.
- from collections import MutableMapping
+ MutableMapping = collections.MutableMapping
class BaseContainer(object):
@@ -336,6 +337,8 @@ class RepeatedScalarFieldContainer(BaseContainer):
# We are presumably comparing against some other sequence type.
return other == self._values
+collections.MutableSequence.register(BaseContainer)
+
class RepeatedCompositeFieldContainer(BaseContainer):
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index 5c07cbe6..c30f633d 100755
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -47,6 +47,7 @@ from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_import_pb2
from google.protobuf import unittest_import_public_pb2
from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_mset_wire_format_pb2
from google.protobuf import unittest_no_generic_services_pb2
from google.protobuf import unittest_pb2
from google.protobuf import service
@@ -142,7 +143,7 @@ class GeneratorTest(unittest.TestCase):
self.assertTrue(not non_extension_descriptor.is_extension)
def testOptions(self):
- proto = unittest_mset_pb2.TestMessageSet()
+ proto = unittest_mset_wire_format_pb2.TestMessageSet()
self.assertTrue(proto.DESCRIPTOR.GetOptions().message_set_wire_format)
def testMessageWithCustomOptions(self):
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 320ff0d2..62abf1be 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -43,6 +43,7 @@ abstract interface.
__author__ = 'gps@google.com (Gregory P. Smith)'
+import collections
import copy
import math
import operator
@@ -56,6 +57,7 @@ from google.protobuf import map_unittest_pb2
from google.protobuf import unittest_pb2
from google.protobuf import unittest_proto3_arena_pb2
from google.protobuf.internal import api_implementation
+from google.protobuf.internal import packed_field_test_pb2
from google.protobuf.internal import test_util
from google.protobuf import message
@@ -421,6 +423,31 @@ class MessageTest(unittest.TestCase):
self.assertEqual(message.repeated_nested_message[4].bb, 5)
self.assertEqual(message.repeated_nested_message[5].bb, 6)
+ def testSortingRepeatedCompositeFieldsStable(self, message_module):
+ """Check passing a custom comparator to sort a repeated composite field."""
+ message = message_module.TestAllTypes()
+
+ message.repeated_nested_message.add().bb = 21
+ message.repeated_nested_message.add().bb = 20
+ message.repeated_nested_message.add().bb = 13
+ message.repeated_nested_message.add().bb = 33
+ message.repeated_nested_message.add().bb = 11
+ message.repeated_nested_message.add().bb = 24
+ message.repeated_nested_message.add().bb = 10
+ message.repeated_nested_message.sort(key=lambda z: z.bb // 10)
+ self.assertEquals(
+ [13, 11, 10, 21, 20, 24, 33],
+ [n.bb for n in message.repeated_nested_message])
+
+ # Make sure that for the C++ implementation, the underlying fields
+ # are actually reordered.
+ pb = message.SerializeToString()
+ message.Clear()
+ message.MergeFromString(pb)
+ self.assertEquals(
+ [13, 11, 10, 21, 20, 24, 33],
+ [n.bb for n in message.repeated_nested_message])
+
def testRepeatedCompositeFieldSortArguments(self, message_module):
"""Check sorting a repeated composite field using list.sort() arguments."""
message = message_module.TestAllTypes()
@@ -514,6 +541,12 @@ class MessageTest(unittest.TestCase):
# TODO(anuraag): Implement extensiondict comparison in C++ and then add test
+ def testRepeatedFieldsAreSequences(self, message_module):
+ m = message_module.TestAllTypes()
+ self.assertIsInstance(m.repeated_int32, collections.MutableSequence)
+ self.assertIsInstance(m.repeated_nested_message,
+ collections.MutableSequence)
+
def ensureNestedMessageExists(self, msg, attribute):
"""Make sure that a nested message object exists.
@@ -556,6 +589,18 @@ class MessageTest(unittest.TestCase):
self.assertFalse(m.HasField('oneof_uint32'))
self.assertTrue(m.HasField('oneof_string'))
+ # Read nested message accessor without accessing submessage.
+ m.oneof_nested_message
+ self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+ self.assertTrue(m.HasField('oneof_string'))
+ self.assertFalse(m.HasField('oneof_nested_message'))
+
+ # Read accessor of nested message without accessing submessage.
+ m.oneof_nested_message.bb
+ self.assertEqual('oneof_string', m.WhichOneof('oneof_field'))
+ self.assertTrue(m.HasField('oneof_string'))
+ self.assertFalse(m.HasField('oneof_nested_message'))
+
m.oneof_nested_message.bb = 11
self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field'))
self.assertFalse(m.HasField('oneof_string'))
@@ -1583,6 +1628,21 @@ class Proto3Test(unittest.TestCase):
del msg.map_int32_int32[4]
self.assertEqual(0, len(msg.map_int32_int32))
+ def testMapsAreMapping(self):
+ msg = map_unittest_pb2.TestMap()
+ self.assertIsInstance(msg.map_int32_int32, collections.Mapping)
+ self.assertIsInstance(msg.map_int32_int32, collections.MutableMapping)
+ self.assertIsInstance(msg.map_int32_foreign_message, collections.Mapping)
+ self.assertIsInstance(msg.map_int32_foreign_message,
+ collections.MutableMapping)
+
+ def testMapFindInitializationErrorsSmokeTest(self):
+ msg = map_unittest_pb2.TestMap()
+ msg.map_string_string['abc'] = '123'
+ msg.map_int32_int32[35] = 64
+ msg.map_string_foreign_message['foo'].c = 5
+ self.assertEqual(0, len(msg.FindInitializationErrors()))
+
class ValidTypeNamesTest(unittest.TestCase):
@@ -1606,6 +1666,61 @@ class ValidTypeNamesTest(unittest.TestCase):
self.assertImportFromName(pb.repeated_int32, 'Scalar')
self.assertImportFromName(pb.repeated_nested_message, 'Composite')
+class PackedFieldTest(unittest.TestCase):
+
+ def setMessage(self, message):
+ message.repeated_int32.append(1)
+ message.repeated_int64.append(1)
+ message.repeated_uint32.append(1)
+ message.repeated_uint64.append(1)
+ message.repeated_sint32.append(1)
+ message.repeated_sint64.append(1)
+ message.repeated_fixed32.append(1)
+ message.repeated_fixed64.append(1)
+ message.repeated_sfixed32.append(1)
+ message.repeated_sfixed64.append(1)
+ message.repeated_float.append(1.0)
+ message.repeated_double.append(1.0)
+ message.repeated_bool.append(True)
+ message.repeated_nested_enum.append(1)
+
+ def testPackedFields(self):
+ message = packed_field_test_pb2.TestPackedTypes()
+ self.setMessage(message)
+ golden_data = (b'\x0A\x01\x01'
+ b'\x12\x01\x01'
+ b'\x1A\x01\x01'
+ b'\x22\x01\x01'
+ b'\x2A\x01\x02'
+ b'\x32\x01\x02'
+ b'\x3A\x04\x01\x00\x00\x00'
+ b'\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x4A\x04\x01\x00\x00\x00'
+ b'\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x5A\x04\x00\x00\x80\x3f'
+ b'\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f'
+ b'\x6A\x01\x01'
+ b'\x72\x01\x01')
+ self.assertEqual(golden_data, message.SerializeToString())
+
+ def testUnpackedFields(self):
+ message = packed_field_test_pb2.TestUnpackedTypes()
+ self.setMessage(message)
+ golden_data = (b'\x08\x01'
+ b'\x10\x01'
+ b'\x18\x01'
+ b'\x20\x01'
+ b'\x28\x02'
+ b'\x30\x02'
+ b'\x3D\x01\x00\x00\x00'
+ b'\x41\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x4D\x01\x00\x00\x00'
+ b'\x51\x01\x00\x00\x00\x00\x00\x00\x00'
+ b'\x5D\x00\x00\x80\x3f'
+ b'\x61\x00\x00\x00\x00\x00\x00\xf0\x3f'
+ b'\x68\x01'
+ b'\x70\x01')
+ self.assertEqual(golden_data, message.SerializeToString())
if __name__ == '__main__':
unittest.main()
diff --git a/python/google/protobuf/internal/packed_field_test.proto b/python/google/protobuf/internal/packed_field_test.proto
index e69de29b..0dfdc10a 100644
--- a/python/google/protobuf/internal/packed_field_test.proto
+++ b/python/google/protobuf/internal/packed_field_test.proto
@@ -0,0 +1,73 @@
+// 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.python.internal;
+
+message TestPackedTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+
+ repeated int32 repeated_int32 = 1;
+ repeated int64 repeated_int64 = 2;
+ repeated uint32 repeated_uint32 = 3;
+ repeated uint64 repeated_uint64 = 4;
+ repeated sint32 repeated_sint32 = 5;
+ repeated sint64 repeated_sint64 = 6;
+ repeated fixed32 repeated_fixed32 = 7;
+ repeated fixed64 repeated_fixed64 = 8;
+ repeated sfixed32 repeated_sfixed32 = 9;
+ repeated sfixed64 repeated_sfixed64 = 10;
+ repeated float repeated_float = 11;
+ repeated double repeated_double = 12;
+ repeated bool repeated_bool = 13;
+ repeated NestedEnum repeated_nested_enum = 14;
+}
+
+message TestUnpackedTypes {
+ repeated int32 repeated_int32 = 1 [packed = false];
+ repeated int64 repeated_int64 = 2 [packed = false];
+ repeated uint32 repeated_uint32 = 3 [packed = false];
+ repeated uint64 repeated_uint64 = 4 [packed = false];
+ repeated sint32 repeated_sint32 = 5 [packed = false];
+ repeated sint64 repeated_sint64 = 6 [packed = false];
+ repeated fixed32 repeated_fixed32 = 7 [packed = false];
+ repeated fixed64 repeated_fixed64 = 8 [packed = false];
+ repeated sfixed32 repeated_sfixed32 = 9 [packed = false];
+ repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+ repeated float repeated_float = 11 [packed = false];
+ repeated double repeated_double = 12 [packed = false];
+ repeated bool repeated_bool = 13 [packed = false];
+ repeated TestPackedTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index ca9f7675..a3e98467 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -85,34 +85,108 @@ from google.protobuf import text_format
_FieldDescriptor = descriptor_mod.FieldDescriptor
-def NewMessage(bases, descriptor, dictionary):
- _AddClassAttributesForNestedExtensions(descriptor, dictionary)
- _AddSlots(descriptor, dictionary)
- return bases
-
-
-def InitMessage(descriptor, cls):
- cls._decoders_by_tag = {}
- cls._extensions_by_name = {}
- cls._extensions_by_number = {}
- if (descriptor.has_options and
- descriptor.GetOptions().message_set_wire_format):
- cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
- decoder.MessageSetItemDecoder(cls._extensions_by_number), None)
-
- # Attach stuff to each FieldDescriptor for quick lookup later on.
- for field in descriptor.fields:
- _AttachFieldHelpers(cls, field)
+class GeneratedProtocolMessageType(type):
+
+ """Metaclass for protocol message classes created at runtime from Descriptors.
+
+ We add implementations for all methods described in the Message class. We
+ also create properties to allow getting/setting all fields in the protocol
+ message. Finally, we create slots to prevent users from accidentally
+ "setting" nonexistent fields in the protocol message, which then wouldn't get
+ serialized / deserialized properly.
+
+ The protocol compiler currently uses this metaclass to create protocol
+ message classes at runtime. Clients can also manually create their own
+ classes at runtime, as in this example:
+
+ mydescriptor = Descriptor(.....)
+ class MyProtoClass(Message):
+ __metaclass__ = GeneratedProtocolMessageType
+ DESCRIPTOR = mydescriptor
+ myproto_instance = MyProtoClass()
+ myproto.foo_field = 23
+ ...
+
+ The above example will not work for nested types. If you wish to include them,
+ use reflection.MakeClass() instead of manually instantiating the class in
+ order to create the appropriate class structure.
+ """
+
+ # Must be consistent with the protocol-compiler code in
+ # proto2/compiler/internal/generator.*.
+ _DESCRIPTOR_KEY = 'DESCRIPTOR'
+
+ def __new__(cls, name, bases, dictionary):
+ """Custom allocation for runtime-generated class types.
+
+ We override __new__ because this is apparently the only place
+ where we can meaningfully set __slots__ on the class we're creating(?).
+ (The interplay between metaclasses and slots is not very well-documented).
+
+ Args:
+ name: Name of the class (ignored, but required by the
+ metaclass protocol).
+ bases: Base classes of the class we're constructing.
+ (Should be message.Message). We ignore this field, but
+ it's required by the metaclass protocol
+ dictionary: The class dictionary of the class we're
+ constructing. dictionary[_DESCRIPTOR_KEY] must contain
+ a Descriptor object describing this protocol message
+ type.
+
+ Returns:
+ Newly-allocated class.
+ """
+ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
+ _AddClassAttributesForNestedExtensions(descriptor, dictionary)
+ _AddSlots(descriptor, dictionary)
+
+ superclass = super(GeneratedProtocolMessageType, cls)
+ new_class = superclass.__new__(cls, name, bases, dictionary)
+ return new_class
+
+ def __init__(cls, name, bases, dictionary):
+ """Here we perform the majority of our work on the class.
+ We add enum getters, an __init__ method, implementations
+ of all Message methods, and properties for all fields
+ in the protocol type.
- descriptor._concrete_class = cls # pylint: disable=protected-access
- _AddEnumValues(descriptor, cls)
- _AddInitMethod(descriptor, cls)
- _AddPropertiesForFields(descriptor, cls)
- _AddPropertiesForExtensions(descriptor, cls)
- _AddStaticMethods(cls)
- _AddMessageMethods(descriptor, cls)
- _AddPrivateHelperMethods(descriptor, cls)
- copyreg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
+ Args:
+ name: Name of the class (ignored, but required by the
+ metaclass protocol).
+ bases: Base classes of the class we're constructing.
+ (Should be message.Message). We ignore this field, but
+ it's required by the metaclass protocol
+ dictionary: The class dictionary of the class we're
+ constructing. dictionary[_DESCRIPTOR_KEY] must contain
+ a Descriptor object describing this protocol message
+ type.
+ """
+ descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
+ cls._decoders_by_tag = {}
+ cls._extensions_by_name = {}
+ cls._extensions_by_number = {}
+ if (descriptor.has_options and
+ descriptor.GetOptions().message_set_wire_format):
+ cls._decoders_by_tag[decoder.MESSAGE_SET_ITEM_TAG] = (
+ decoder.MessageSetItemDecoder(cls._extensions_by_number), None)
+
+ # Attach stuff to each FieldDescriptor for quick lookup later on.
+ for field in descriptor.fields:
+ _AttachFieldHelpers(cls, field)
+
+ descriptor._concrete_class = cls # pylint: disable=protected-access
+ _AddEnumValues(descriptor, cls)
+ _AddInitMethod(descriptor, cls)
+ _AddPropertiesForFields(descriptor, cls)
+ _AddPropertiesForExtensions(descriptor, cls)
+ _AddStaticMethods(cls)
+ _AddMessageMethods(descriptor, cls)
+ _AddPrivateHelperMethods(descriptor, cls)
+ copyreg.pickle(cls, lambda obj: (cls, (), obj.__getstate__()))
+
+ superclass = super(GeneratedProtocolMessageType, cls)
+ superclass.__init__(name, bases, dictionary)
# Stateless helpers for GeneratedProtocolMessageType below.
@@ -362,9 +436,10 @@ def _DefaultValueConstructorForField(field):
message_type = field.message_type
def MakeSubMessageDefault(message):
result = message_type._concrete_class()
- result._SetListener(message._listener_for_children)
- if field.containing_oneof:
- message._UpdateOneofState(field)
+ result._SetListener(
+ _OneofListener(message, field)
+ if field.containing_oneof is not None
+ else message._listener_for_children)
return result
return MakeSubMessageDefault
@@ -634,21 +709,11 @@ def _AddPropertiesForNonRepeatedCompositeField(field, cls):
proto_field_name = field.name
property_name = _PropertyName(proto_field_name)
- # TODO(komarek): Can anyone explain to me why we cache the message_type this
- # way, instead of referring to field.message_type inside of getter(self)?
- # What if someone sets message_type later on (which makes for simpler
- # dyanmic proto descriptor and class creation code).
- message_type = field.message_type
-
def getter(self):
field_value = self._fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
- field_value = message_type._concrete_class() # use field.message_type?
- field_value._SetListener(
- _OneofListener(self, field)
- if field.containing_oneof is not None
- else self._listener_for_children)
+ field_value = field._default_constructor(self)
# Atomically check if another thread has preempted us and, if not, swap
# in the new object we just created. If someone has preempted us, we
@@ -1121,7 +1186,7 @@ def _AddIsInitializedMethod(message_descriptor, cls):
if _IsMessageMapField(field):
for key in value:
element = value[key]
- prefix = "%s[%d]." % (name, key)
+ prefix = "%s[%s]." % (name, key)
sub_errors = element.FindInitializationErrors()
errors += [prefix + error for error in sub_errors]
else:
@@ -1173,8 +1238,6 @@ 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
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 4eca4989..ef1ced4e 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -52,6 +52,7 @@ from google.protobuf import text_format
from google.protobuf.internal import api_implementation
from google.protobuf.internal import more_extensions_pb2
from google.protobuf.internal import more_messages_pb2
+from google.protobuf.internal import message_set_extensions_pb2
from google.protobuf.internal import wire_format
from google.protobuf.internal import test_util
from google.protobuf.internal import decoder
@@ -1682,8 +1683,8 @@ class ReflectionTest(unittest.TestCase):
proto.optional_string = 'abc'
def testStringUTF8Serialization(self):
- proto = unittest_mset_pb2.TestMessageSet()
- extension_message = unittest_mset_pb2.TestMessageSetExtension2
+ proto = message_set_extensions_pb2.TestMessageSet()
+ extension_message = message_set_extensions_pb2.TestMessageSetExtension2
extension = extension_message.message_set_extension
test_utf8 = u'Тест'
@@ -1703,15 +1704,14 @@ class ReflectionTest(unittest.TestCase):
bytes_read = raw.MergeFromString(serialized)
self.assertEqual(len(serialized), bytes_read)
- message2 = unittest_mset_pb2.TestMessageSetExtension2()
+ message2 = message_set_extensions_pb2.TestMessageSetExtension2()
self.assertEqual(1, len(raw.item))
# Check that the type_id is the same as the tag ID in the .proto file.
- self.assertEqual(raw.item[0].type_id, 1547769)
+ self.assertEqual(raw.item[0].type_id, 98418634)
# Check the actual bytes on the wire.
- self.assertTrue(
- raw.item[0].message.endswith(test_utf8_bytes))
+ self.assertTrue(raw.item[0].message.endswith(test_utf8_bytes))
bytes_read = message2.MergeFromString(raw.item[0].message)
self.assertEqual(len(raw.item[0].message), bytes_read)
@@ -2395,9 +2395,9 @@ class SerializationTest(unittest.TestCase):
self.assertEqual(42, second_proto.optional_nested_message.bb)
def testMessageSetWireFormat(self):
- proto = unittest_mset_pb2.TestMessageSet()
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
- extension_message2 = unittest_mset_pb2.TestMessageSetExtension2
+ proto = message_set_extensions_pb2.TestMessageSet()
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+ extension_message2 = message_set_extensions_pb2.TestMessageSetExtension2
extension1 = extension_message1.message_set_extension
extension2 = extension_message2.message_set_extension
proto.Extensions[extension1].i = 123
@@ -2415,20 +2415,20 @@ class SerializationTest(unittest.TestCase):
raw.MergeFromString(serialized))
self.assertEqual(2, len(raw.item))
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ message1 = message_set_extensions_pb2.TestMessageSetExtension1()
self.assertEqual(
len(raw.item[0].message),
message1.MergeFromString(raw.item[0].message))
self.assertEqual(123, message1.i)
- message2 = unittest_mset_pb2.TestMessageSetExtension2()
+ message2 = message_set_extensions_pb2.TestMessageSetExtension2()
self.assertEqual(
len(raw.item[1].message),
message2.MergeFromString(raw.item[1].message))
self.assertEqual('foo', message2.str)
# Deserialize using the MessageSet wire format.
- proto2 = unittest_mset_pb2.TestMessageSet()
+ proto2 = message_set_extensions_pb2.TestMessageSet()
self.assertEqual(
len(serialized),
proto2.MergeFromString(serialized))
@@ -2446,37 +2446,37 @@ class SerializationTest(unittest.TestCase):
# Add an item.
item = raw.item.add()
- item.type_id = 1545008
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ item.type_id = 98418603
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+ message1 = message_set_extensions_pb2.TestMessageSetExtension1()
message1.i = 12345
item.message = message1.SerializeToString()
# Add a second, unknown extension.
item = raw.item.add()
- item.type_id = 1545009
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ item.type_id = 98418604
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
+ message1 = message_set_extensions_pb2.TestMessageSetExtension1()
message1.i = 12346
item.message = message1.SerializeToString()
# Add another unknown extension.
item = raw.item.add()
- item.type_id = 1545010
- message1 = unittest_mset_pb2.TestMessageSetExtension2()
+ item.type_id = 98418605
+ message1 = message_set_extensions_pb2.TestMessageSetExtension2()
message1.str = 'foo'
item.message = message1.SerializeToString()
serialized = raw.SerializeToString()
# Parse message using the message set wire format.
- proto = unittest_mset_pb2.TestMessageSet()
+ proto = message_set_extensions_pb2.TestMessageSet()
self.assertEqual(
len(serialized),
proto.MergeFromString(serialized))
# Check that the message parsed well.
- extension_message1 = unittest_mset_pb2.TestMessageSetExtension1
+ extension_message1 = message_set_extensions_pb2.TestMessageSetExtension1
extension1 = extension_message1.message_set_extension
self.assertEquals(12345, proto.Extensions[extension1].i)
@@ -2805,7 +2805,7 @@ class SerializationTest(unittest.TestCase):
class OptionsTest(unittest.TestCase):
def testMessageOptions(self):
- proto = unittest_mset_pb2.TestMessageSet()
+ proto = message_set_extensions_pb2.TestMessageSet()
self.assertEqual(True,
proto.DESCRIPTOR.GetOptions().message_set_wire_format)
proto = unittest_pb2.TestAllTypes()
@@ -2824,7 +2824,7 @@ class OptionsTest(unittest.TestCase):
proto.packed_double.append(3.0)
for field_descriptor, _ in proto.ListFields():
self.assertEqual(True, field_descriptor.GetOptions().packed)
- self.assertEqual(reflection._FieldDescriptor.LABEL_REPEATED,
+ self.assertEqual(descriptor.FieldDescriptor.LABEL_REPEATED,
field_descriptor.label)
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index fec65382..ac88fa81 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -604,7 +604,8 @@ def GoldenFile(filename):
# Search internally.
path = '.'
- full_path = os.path.join(path, 'third_party/py/google/protobuf/testdata', filename)
+ full_path = os.path.join(path, 'third_party/py/google/protobuf/testdata',
+ filename)
if os.path.exists(full_path):
# Found it. Load the golden file from the testdata directory.
return open(full_path, 'rb')
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 06bd1ee5..00e67654 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -35,6 +35,7 @@
__author__ = 'kenton@google.com (Kenton Varda)'
import re
+import string
import unittest
import unittest
@@ -497,6 +498,36 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase):
' }\n'
'}\n')
+ def testMapOrderEnforcement(self):
+ message = map_unittest_pb2.TestMap()
+ for letter in string.ascii_uppercase[13:26]:
+ message.map_string_string[letter] = 'dummy'
+ for letter in reversed(string.ascii_uppercase[0:13]):
+ message.map_string_string[letter] = 'dummy'
+ golden = ''.join((
+ 'map_string_string {\n key: "%c"\n value: "dummy"\n}\n' % (letter,)
+ for letter in string.ascii_uppercase))
+ self.CompareToGoldenText(text_format.MessageToString(message), golden)
+
+ def testMapOrderSemantics(self):
+ golden_lines = self.ReadGolden('map_test_data.txt')
+ # The C++ implementation emits defaulted-value fields, while the Python
+ # implementation does not. Adjusting for this is awkward, but it is
+ # valuable to test against a common golden file.
+ line_blacklist = (' key: 0\n',
+ ' value: 0\n',
+ ' key: false\n',
+ ' value: false\n')
+ golden_lines = [line for line in golden_lines if line not in line_blacklist]
+
+ message = map_unittest_pb2.TestMap()
+ text_format.ParseLines(golden_lines, message)
+ candidate = text_format.MessageToString(message)
+ # The Python implementation emits "1.0" for the double value that the C++
+ # implementation emits as "1".
+ candidate = candidate.replace('1.0', '1', 2)
+ self.assertMultiLineEqual(candidate, ''.join(golden_lines))
+
# Tests of proto2-only features (MessageSet, extensions, etc.).
class Proto2Tests(TextFormatBase):
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index 1b81ae79..0dda805b 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -41,11 +41,18 @@ 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 message_set_extensions_pb2
from google.protobuf.internal import missing_enum_values_pb2
from google.protobuf.internal import test_util
from google.protobuf.internal import type_checkers
+def SkipIfCppImplementation(func):
+ return unittest.skipIf(
+ api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
+ 'C++ implementation does not expose unknown fields to Python')(func)
+
+
class UnknownFieldsTest(unittest.TestCase):
def setUp(self):
@@ -83,15 +90,15 @@ class UnknownFieldsTest(unittest.TestCase):
# Add an unknown extension.
item = raw.item.add()
- item.type_id = 1545009
- message1 = unittest_mset_pb2.TestMessageSetExtension1()
+ item.type_id = 98418603
+ message1 = message_set_extensions_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 = message_set_extensions_pb2.TestMessageSet()
proto.MergeFromString(serialized)
# Verify that the unknown extension is serialized unchanged
@@ -100,13 +107,6 @@ class UnknownFieldsTest(unittest.TestCase):
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.
- @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)
@@ -117,9 +117,6 @@ class UnknownFieldsTest(unittest.TestCase):
self.assertNotEqual(self.empty_message, message)
-@unittest.skipIf(
- api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
- 'C++ implementation does not expose unknown fields to Python')
class UnknownFieldsAccessorsTest(unittest.TestCase):
def setUp(self):
@@ -129,7 +126,14 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
self.all_fields_data = self.all_fields.SerializeToString()
self.empty_message = unittest_pb2.TestEmptyMessage()
self.empty_message.ParseFromString(self.all_fields_data)
- self.unknown_fields = self.empty_message._unknown_fields
+ if api_implementation.Type() != 'cpp':
+ # _unknown_fields is an implementation detail.
+ self.unknown_fields = self.empty_message._unknown_fields
+
+ # All the tests that use GetField() check an implementation detail of the
+ # Python implementation, which stores unknown fields as serialized strings.
+ # These tests are skipped by the C++ implementation: it's enough to check that
+ # the message is correctly serialized.
def GetField(self, name):
field_descriptor = self.descriptor.fields_by_name[name]
@@ -142,30 +146,37 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
decoder(value, 0, len(value), self.all_fields, result_dict)
return result_dict[field_descriptor]
+ @SkipIfCppImplementation
def testEnum(self):
value = self.GetField('optional_nested_enum')
self.assertEqual(self.all_fields.optional_nested_enum, value)
+ @SkipIfCppImplementation
def testRepeatedEnum(self):
value = self.GetField('repeated_nested_enum')
self.assertEqual(self.all_fields.repeated_nested_enum, value)
+ @SkipIfCppImplementation
def testVarint(self):
value = self.GetField('optional_int32')
self.assertEqual(self.all_fields.optional_int32, value)
+ @SkipIfCppImplementation
def testFixed32(self):
value = self.GetField('optional_fixed32')
self.assertEqual(self.all_fields.optional_fixed32, value)
+ @SkipIfCppImplementation
def testFixed64(self):
value = self.GetField('optional_fixed64')
self.assertEqual(self.all_fields.optional_fixed64, value)
+ @SkipIfCppImplementation
def testLengthDelimited(self):
value = self.GetField('optional_string')
self.assertEqual(self.all_fields.optional_string, value)
+ @SkipIfCppImplementation
def testGroup(self):
value = self.GetField('optionalgroup')
self.assertEqual(self.all_fields.optionalgroup, value)
@@ -173,7 +184,7 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
def testCopyFrom(self):
message = unittest_pb2.TestEmptyMessage()
message.CopyFrom(self.empty_message)
- self.assertEqual(self.unknown_fields, message._unknown_fields)
+ self.assertEqual(message.SerializeToString(), self.all_fields_data)
def testMergeFrom(self):
message = unittest_pb2.TestAllTypes()
@@ -187,27 +198,26 @@ class UnknownFieldsAccessorsTest(unittest.TestCase):
message.optional_uint32 = 4
destination = unittest_pb2.TestEmptyMessage()
destination.ParseFromString(message.SerializeToString())
- unknown_fields = destination._unknown_fields[:]
destination.MergeFrom(source)
- self.assertEqual(unknown_fields + source._unknown_fields,
- destination._unknown_fields)
+ # Check that the fields where correctly merged, even stored in the unknown
+ # fields set.
+ message.ParseFromString(destination.SerializeToString())
+ self.assertEqual(message.optional_int32, 1)
+ self.assertEqual(message.optional_uint32, 2)
+ self.assertEqual(message.optional_int64, 3)
def testClear(self):
self.empty_message.Clear()
- self.assertEqual(0, len(self.empty_message._unknown_fields))
+ # All cleared, even unknown fields.
+ self.assertEqual(self.empty_message.SerializeToString(), b'')
def testUnknownExtensions(self):
message = unittest_pb2.TestEmptyMessageWithExtensions()
message.ParseFromString(self.all_fields_data)
- self.assertEqual(self.empty_message._unknown_fields,
- message._unknown_fields)
-
+ self.assertEqual(message.SerializeToString(), self.all_fields_data)
-@unittest.skipIf(
- api_implementation.Type() == 'cpp' and api_implementation.Version() == 2,
- 'C++ implementation does not expose unknown fields to Python')
class UnknownEnumValuesTest(unittest.TestCase):
def setUp(self):
@@ -227,7 +237,14 @@ class UnknownEnumValuesTest(unittest.TestCase):
self.message_data = self.message.SerializeToString()
self.missing_message = missing_enum_values_pb2.TestMissingEnumValues()
self.missing_message.ParseFromString(self.message_data)
- self.unknown_fields = self.missing_message._unknown_fields
+ if api_implementation.Type() != 'cpp':
+ # _unknown_fields is an implementation detail.
+ self.unknown_fields = self.missing_message._unknown_fields
+
+ # All the tests that use GetField() check an implementation detail of the
+ # Python implementation, which stores unknown fields as serialized strings.
+ # These tests are skipped by the C++ implementation: it's enough to check that
+ # the message is correctly serialized.
def GetField(self, name):
field_descriptor = self.descriptor.fields_by_name[name]
@@ -241,15 +258,18 @@ class UnknownEnumValuesTest(unittest.TestCase):
decoder(value, 0, len(value), self.message, result_dict)
return result_dict[field_descriptor]
+ @SkipIfCppImplementation
def testUnknownEnumValue(self):
self.assertFalse(self.missing_message.HasField('optional_nested_enum'))
value = self.GetField('optional_nested_enum')
self.assertEqual(self.message.optional_nested_enum, value)
+ @SkipIfCppImplementation
def testUnknownRepeatedEnumValue(self):
value = self.GetField('repeated_nested_enum')
self.assertEqual(self.message.repeated_nested_enum, value)
+ @SkipIfCppImplementation
def testUnknownPackedEnumValue(self):
value = self.GetField('packed_nested_enum')
self.assertEqual(self.message.packed_nested_enum, value)
diff --git a/python/google/protobuf/pyext/cpp_message.py b/python/google/protobuf/pyext/cpp_message.py
index 037bb72c..b215211e 100644
--- a/python/google/protobuf/pyext/cpp_message.py
+++ b/python/google/protobuf/pyext/cpp_message.py
@@ -37,21 +37,29 @@ Descriptor objects at runtime backed by the protocol buffer C++ API.
__author__ = 'tibell@google.com (Johan Tibell)'
from google.protobuf.pyext import _message
-from google.protobuf import message
-def NewMessage(bases, message_descriptor, dictionary):
- """Creates a new protocol message *class*."""
- new_bases = []
- for base in bases:
- if base is message.Message:
- # _message.Message must come before message.Message as it
- # overrides methods in that class.
- new_bases.append(_message.Message)
- new_bases.append(base)
- return tuple(new_bases)
+class GeneratedProtocolMessageType(_message.MessageMeta):
+ """Metaclass for protocol message classes created at runtime from Descriptors.
-def InitMessage(message_descriptor, cls):
- """Finalizes the creation of a message class."""
- cls.AddDescriptors(message_descriptor)
+ The protocol compiler currently uses this metaclass to create protocol
+ message classes at runtime. Clients can also manually create their own
+ classes at runtime, as in this example:
+
+ mydescriptor = Descriptor(.....)
+ class MyProtoClass(Message):
+ __metaclass__ = GeneratedProtocolMessageType
+ DESCRIPTOR = mydescriptor
+ myproto_instance = MyProtoClass()
+ myproto.foo_field = 23
+ ...
+
+ The above example will not work for nested types. If you wish to include them,
+ use reflection.MakeClass() instead of manually instantiating the class in
+ order to create the appropriate class structure.
+ """
+
+ # Must be consistent with the protocol-compiler code in
+ # proto2/compiler/internal/generator.*.
+ _DESCRIPTOR_KEY = 'DESCRIPTOR'
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 2160757b..8581f529 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -193,7 +193,7 @@ static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) {
io::CodedInputStream input(
reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
input.SetExtensionRegistry(GetDescriptorPool()->pool,
- cmessage::GetMessageFactory());
+ GetDescriptorPool()->message_factory);
bool success = cmsg->message->MergePartialFromCodedStream(&input);
if (!success) {
PyErr_Format(PyExc_ValueError, "Error parsing Options message");
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index ecd90847..d5ba2b6f 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -33,6 +33,7 @@
#include <Python.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/pyext/descriptor_pool.h>
#include <google/protobuf/pyext/descriptor.h>
#include <google/protobuf/pyext/message.h>
@@ -67,6 +68,11 @@ PyDescriptorPool* NewDescriptorPool() {
// as underlay.
cdescriptor_pool->pool = new DescriptorPool(DescriptorPool::generated_pool());
+ DynamicMessageFactory* message_factory = new DynamicMessageFactory();
+ // This option might be the default some day.
+ message_factory->SetDelegateToGeneratedFactory(true);
+ cdescriptor_pool->message_factory = message_factory;
+
// TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same
// storage.
cdescriptor_pool->classes_by_descriptor =
@@ -93,6 +99,7 @@ static void Dealloc(PyDescriptorPool* self) {
Py_DECREF(it->second);
}
delete self->descriptor_options;
+ delete self->message_factory;
Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
}
diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h
index efb1abeb..6f6c5cdb 100644
--- a/python/google/protobuf/pyext/descriptor_pool.h
+++ b/python/google/protobuf/pyext/descriptor_pool.h
@@ -38,6 +38,8 @@
namespace google {
namespace protobuf {
+class MessageFactory;
+
namespace python {
// Wraps operations to the global DescriptorPool which contains information
@@ -55,6 +57,14 @@ typedef struct PyDescriptorPool {
DescriptorPool* pool;
+ // DynamicMessageFactory used to create C++ instances of messages.
+ // This object cache the descriptors that were used, so the DescriptorPool
+ // needs to get rid of it before it can delete itself.
+ //
+ // Note: A C++ MessageFactory is different from the Python MessageFactory.
+ // The C++ one creates messages, when the Python one creates classes.
+ MessageFactory* message_factory;
+
// Make our own mapping to retrieve Python classes from C++ descriptors.
//
// Descriptor pointers stored here are owned by the DescriptorPool above.
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index b8d18f8d..8ebbb27c 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -33,6 +33,7 @@
#include <google/protobuf/pyext/extension_dict.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
@@ -183,7 +184,8 @@ PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) {
return NULL;
}
}
- if (cmessage::ClearFieldByDescriptor(self->parent, descriptor) == NULL) {
+ if (ScopedPyObjectPtr(cmessage::ClearFieldByDescriptor(
+ self->parent, descriptor)) == NULL) {
return NULL;
}
if (PyDict_DelItem(self->values, extension) < 0) {
@@ -268,7 +270,7 @@ PyTypeObject ExtensionDict_Type = {
0, // tp_as_number
0, // tp_as_sequence
&extension_dict::MpMethods, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index a4843e8d..aa3ab97a 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -49,9 +49,10 @@
#endif
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/util/message_differencer.h>
#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/pyext/descriptor.h>
@@ -88,12 +89,308 @@ namespace google {
namespace protobuf {
namespace python {
+static PyObject* kDESCRIPTOR;
+static PyObject* k_extensions_by_name;
+static PyObject* k_extensions_by_number;
+PyObject* EnumTypeWrapper_class;
+static PyObject* PythonMessage_class;
+static PyObject* kEmptyWeakref;
+
+// Defines the Metaclass of all Message classes.
+// It allows us to cache some C++ pointers in the class object itself, they are
+// faster to extract than from the type's dictionary.
+
+struct PyMessageMeta {
+ // This is how CPython subclasses C structures: the base structure must be
+ // the first member of the object.
+ PyHeapTypeObject super;
+
+ // C++ descriptor of this message.
+ const Descriptor* message_descriptor;
+ // Owned reference, used to keep the pointer above alive.
+ PyObject* py_message_descriptor;
+};
+
+namespace message_meta {
+
+static int InsertEmptyWeakref(PyTypeObject* base);
+
+// 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 int AddDescriptors(PyObject* cls, PyObject* descriptor) {
+ const Descriptor* message_descriptor =
+ cdescriptor_pool::RegisterMessageClass(
+ GetDescriptorPool(), cls, descriptor);
+ if (message_descriptor == NULL) {
+ return -1;
+ }
+
+ // If there are extension_ranges, the message is "extendable", and extension
+ // classes will register themselves in this class.
+ if (message_descriptor->extension_range_count() > 0) {
+ ScopedPyObjectPtr by_name(PyDict_New());
+ if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
+ return -1;
+ }
+ ScopedPyObjectPtr by_number(PyDict_New());
+ if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
+ return -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 -1;
+ }
+ }
+
+ // 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_FromDescriptor(enum_descriptor));
+ if (enum_type == NULL) {
+ return -1;
+ }
+ // Add wrapped enum type to message class.
+ ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs(
+ EnumTypeWrapper_class, enum_type.get(), NULL));
+ if (wrapped == NULL) {
+ return -1;
+ }
+ if (PyObject_SetAttrString(
+ cls, enum_descriptor->name().c_str(), wrapped) == -1) {
+ return -1;
+ }
+
+ // 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 -1;
+ }
+ if (PyObject_SetAttrString(
+ cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
+ return -1;
+ }
+ }
+ }
+
+ // 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_FromDescriptor(field));
+ if (extension_field == NULL) {
+ return -1;
+ }
+
+ // Add the extension field to the message class.
+ if (PyObject_SetAttrString(
+ cls, field->name().c_str(), extension_field) == -1) {
+ return -1;
+ }
+
+ // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
+ if (!AddFieldNumberToClass(cls, field)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static PyObject* New(PyTypeObject* type,
+ PyObject* args, PyObject* kwargs) {
+ static char *kwlist[] = {"name", "bases", "dict", 0};
+ PyObject *bases, *dict;
+ const char* name;
+
+ // Check arguments: (name, bases, dict)
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", kwlist,
+ &name,
+ &PyTuple_Type, &bases,
+ &PyDict_Type, &dict)) {
+ return NULL;
+ }
+
+ // Check bases: only (), or (message.Message,) are allowed
+ if (!(PyTuple_GET_SIZE(bases) == 0 ||
+ (PyTuple_GET_SIZE(bases) == 1 &&
+ PyTuple_GET_ITEM(bases, 0) == PythonMessage_class))) {
+ PyErr_SetString(PyExc_TypeError,
+ "A Message class can only inherit from Message");
+ return NULL;
+ }
+
+ // Check dict['DESCRIPTOR']
+ PyObject* descriptor = PyDict_GetItem(dict, kDESCRIPTOR);
+ if (descriptor == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR");
+ return NULL;
+ }
+ if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
+ PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
+ descriptor->ob_type->tp_name);
+ return NULL;
+ }
+
+ // Build the arguments to the base metaclass.
+ // We change the __bases__ classes.
+ ScopedPyObjectPtr new_args(Py_BuildValue(
+ "s(OO)O", name, &CMessage_Type, PythonMessage_class, dict));
+ if (new_args == NULL) {
+ return NULL;
+ }
+ // Call the base metaclass.
+ ScopedPyObjectPtr result(PyType_Type.tp_new(type, new_args, NULL));
+ if (result == NULL) {
+ return NULL;
+ }
+ PyMessageMeta* newtype = reinterpret_cast<PyMessageMeta*>(result.get());
+
+ // Insert the empty weakref into the base classes.
+ if (InsertEmptyWeakref(
+ reinterpret_cast<PyTypeObject*>(PythonMessage_class)) < 0 ||
+ InsertEmptyWeakref(&CMessage_Type) < 0) {
+ return NULL;
+ }
+
+ // Cache the descriptor, both as Python object and as C++ pointer.
+ const Descriptor* message_descriptor =
+ PyMessageDescriptor_AsDescriptor(descriptor);
+ if (message_descriptor == NULL) {
+ return NULL;
+ }
+ Py_INCREF(descriptor);
+ newtype->py_message_descriptor = descriptor;
+ newtype->message_descriptor = message_descriptor;
+
+ // Continue with type initialization: add other descriptors, enum values...
+ if (AddDescriptors(result, descriptor) < 0) {
+ return NULL;
+ }
+ return result.release();
+}
+
+static void Dealloc(PyMessageMeta *self) {
+ Py_DECREF(self->py_message_descriptor);
+ Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
+}
+
+static PyObject* GetDescriptor(PyMessageMeta *self, void *closure) {
+ Py_INCREF(self->py_message_descriptor);
+ return self->py_message_descriptor;
+}
+
+
+// This function inserts and empty weakref at the end of the list of
+// subclasses for the main protocol buffer Message class.
+//
+// This eliminates a O(n^2) behaviour in the internal add_subclass
+// routine.
+static int InsertEmptyWeakref(PyTypeObject *base_type) {
+#if PY_MAJOR_VERSION >= 3
+ // Python 3.4 has already included the fix for the issue that this
+ // hack addresses. For further background and the fix please see
+ // https://bugs.python.org/issue17936.
+ return 0;
+#else
+ PyObject *subclasses = base_type->tp_subclasses;
+ if (subclasses && PyList_CheckExact(subclasses)) {
+ return PyList_Append(subclasses, kEmptyWeakref);
+ }
+ return 0;
+#endif // PY_MAJOR_VERSION >= 3
+}
+
+} // namespace message_meta
+
+PyTypeObject PyMessageMeta_Type {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ FULL_MODULE_NAME ".MessageMeta", // tp_name
+ sizeof(PyMessageMeta), // tp_basicsize
+ 0, // tp_itemsize
+ (destructor)message_meta::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 | Py_TPFLAGS_BASETYPE, // tp_flags
+ "The metaclass of ProtocolMessages", // 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
+ 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
+ message_meta::New, // tp_new
+};
+
+static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) {
+ if (!PyObject_TypeCheck(cls, &PyMessageMeta_Type)) {
+ PyErr_Format(PyExc_TypeError, "Class %s is not a Message", cls->tp_name);
+ return NULL;
+ }
+ return reinterpret_cast<PyMessageMeta*>(cls)->message_descriptor;
+}
+
// Forward declarations
namespace cmessage {
-static const FieldDescriptor* GetFieldDescriptor(
- CMessage* self, PyObject* name);
-static const Descriptor* GetMessageDescriptor(PyTypeObject* cls);
-static string GetMessageName(CMessage* self);
int InternalReleaseFieldByDescriptor(
CMessage* self,
const FieldDescriptor* field_descriptor,
@@ -180,7 +477,7 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
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));
+ GetMessageDescriptor(Py_TYPE(self));
while (PyDict_Next(self->composite_fields, &pos, &key, &field)) {
Py_ssize_t key_str_size;
char *key_str_data;
@@ -213,8 +510,6 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) {
// ---------------------------------------------------------------------
-static DynamicMessageFactory* message_factory;
-
// Constants used for integer type range checking.
PyObject* kPythonZero;
PyObject* kint32min_py;
@@ -224,17 +519,13 @@ PyObject* kint64min_py;
PyObject* kint64max_py;
PyObject* kuint64max_py;
-PyObject* EnumTypeWrapper_class;
PyObject* EncodeError_class;
PyObject* DecodeError_class;
PyObject* PickleError_class;
// Constant PyString values used for GetAttr/GetItem.
-static PyObject* kDESCRIPTOR;
static PyObject* k_cdescriptor;
static PyObject* kfull_name;
-static PyObject* k_extensions_by_name;
-static PyObject* k_extensions_by_number;
/* Is 64bit */
void FormatTypeError(PyObject* arg, char* expected_types) {
@@ -432,10 +723,6 @@ bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor,
namespace cmessage {
-DynamicMessageFactory* GetMessageFactory() {
- return message_factory;
-}
-
static int MaybeReleaseOverlappingOneofField(
CMessage* cmessage,
const FieldDescriptor* field) {
@@ -486,7 +773,7 @@ static Message* GetMutableMessage(
return NULL;
}
return reflection->MutableMessage(
- parent_message, parent_field, message_factory);
+ parent_message, parent_field, GetDescriptorPool()->message_factory);
}
struct FixupMessageReference : public ChildVisitor {
@@ -527,8 +814,9 @@ 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 = message_factory->GetPrototype(
- self->message->GetDescriptor());
+ const Message* prototype =
+ GetDescriptorPool()->message_factory->GetPrototype(
+ self->message->GetDescriptor());
self->message = prototype->New();
self->owner.reset(self->message);
// Cascade the new owner to eventual children: even if this message is
@@ -567,23 +855,6 @@ int AssureWritable(CMessage* self) {
// --- Globals:
-// Retrieve the C++ Descriptor of a message class.
-// On error, returns NULL with an exception set.
-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;
- }
- if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) {
- PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s",
- descriptor->ob_type->tp_name);
- return NULL;
- }
- 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
@@ -846,9 +1117,9 @@ int InitAttributes(CMessage* self, PyObject* kwargs) {
return -1;
}
} else {
- if (repeated_scalar_container::Extend(
+ if (ScopedPyObjectPtr(repeated_scalar_container::Extend(
reinterpret_cast<RepeatedScalarContainer*>(container.get()),
- value) ==
+ value)) ==
NULL) {
return -1;
}
@@ -927,7 +1198,7 @@ static PyObject* New(PyTypeObject* type,
return NULL;
}
const Message* default_message =
- message_factory->GetPrototype(message_descriptor);
+ GetDescriptorPool()->message_factory->GetPrototype(message_descriptor);
if (default_message == NULL) {
PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str());
return NULL;
@@ -1257,6 +1528,7 @@ int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner) {
Message* ReleaseMessage(CMessage* self,
const Descriptor* descriptor,
const FieldDescriptor* field_descriptor) {
+ MessageFactory* message_factory = GetDescriptorPool()->message_factory;
Message* released_message = self->message->GetReflection()->ReleaseMessage(
self->message, field_descriptor, message_factory);
// ReleaseMessage will return NULL which differs from
@@ -1492,34 +1764,35 @@ static PyObject* SerializePartialToString(CMessage* self) {
// appropriate.
class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter {
public:
- PythonFieldValuePrinter() : float_holder_(PyFloat_FromDouble(0)) {}
-
// Python has some differences from C++ when printing floating point numbers.
//
// 1) Trailing .0 is always printed.
- // 2) Outputted is rounded to 12 digits.
+ // 2) (Python2) Output is rounded to 12 digits.
+ // 3) (Python3) The full precision of the double is preserved (and Python uses
+ // David M. Gay's dtoa(), when the C++ code uses SimpleDtoa. There are some
+ // differences, but they rarely happen)
//
// We override floating point printing with the C-API function for printing
// Python floats to ensure consistency.
string PrintFloat(float value) const { return PrintDouble(value); }
string PrintDouble(double value) const {
- reinterpret_cast<PyFloatObject*>(float_holder_.get())->ob_fval = value;
- ScopedPyObjectPtr s(PyObject_Str(float_holder_.get()));
- if (s == NULL) return string();
+ // Same as float.__str__()
+ char* buf = PyOS_double_to_string(
+ value,
#if PY_MAJOR_VERSION < 3
- char *cstr = PyBytes_AS_STRING(static_cast<PyObject*>(s));
+ 'g', PyFloat_STR_PRECISION, // Output is rounded to 12 digits.
#else
- char *cstr = PyUnicode_AsUTF8(s);
+ 'r', 0,
#endif
- return string(cstr);
+ Py_DTSF_ADD_DOT_0, // Trailing .0 is always printed.
+ NULL);
+ if (!buf) {
+ return string();
+ }
+ string result(buf);
+ PyMem_Free(buf);
+ return result;
}
-
- private:
- // Holder for a python float object which we use to allow us to use
- // the Python API for printing doubles. We initialize once and then
- // directly modify it for every float printed to save on allocations
- // and refcounting.
- ScopedPyObjectPtr float_holder_;
};
static PyObject* ToStr(CMessage* self) {
@@ -1590,7 +1863,7 @@ static PyObject* CopyFrom(CMessage* self, PyObject* arg) {
// CopyFrom on the message will not clean up self->composite_fields,
// which can leave us in an inconsistent state, so clear it out here.
- Clear(self);
+ (void)ScopedPyObjectPtr(Clear(self));
self->message->CopyFrom(*other_message->message);
@@ -1607,7 +1880,8 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
AssureWritable(self);
io::CodedInputStream input(
reinterpret_cast<const uint8*>(data), data_length);
- input.SetExtensionRegistry(GetDescriptorPool()->pool, message_factory);
+ input.SetExtensionRegistry(GetDescriptorPool()->pool,
+ GetDescriptorPool()->message_factory);
bool success = self->message->MergePartialFromCodedStream(&input);
if (success) {
return PyInt_FromLong(input.CurrentPosition());
@@ -1618,7 +1892,7 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
}
static PyObject* ParseFromString(CMessage* self, PyObject* arg) {
- if (Clear(self) == NULL) {
+ if (ScopedPyObjectPtr(Clear(self)) == NULL) {
return NULL;
}
return MergeFromString(self, arg);
@@ -1790,6 +2064,7 @@ static PyObject* ListFields(CMessage* self) {
// Steals reference to 'extension'
PyTuple_SET_ITEM(t.get(), 1, extension);
} else {
+ // Normal field
const string& field_name = fields[i]->name();
ScopedPyObjectPtr py_field_name(PyString_FromStringAndSize(
field_name.c_str(), field_name.length()));
@@ -1841,28 +2116,34 @@ PyObject* FindInitializationErrors(CMessage* self) {
}
static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) {
- if (!PyObject_TypeCheck(other, &CMessage_Type)) {
- if (opid == Py_EQ) {
- Py_RETURN_FALSE;
- } else if (opid == Py_NE) {
- Py_RETURN_TRUE;
- }
- }
- if (opid == Py_EQ || opid == Py_NE) {
- ScopedPyObjectPtr self_fields(ListFields(self));
- if (!self_fields) {
- return NULL;
- }
- ScopedPyObjectPtr other_fields(ListFields(
- reinterpret_cast<CMessage*>(other)));
- if (!other_fields) {
- return NULL;
- }
- return PyObject_RichCompare(self_fields, other_fields, opid);
- } else {
+ // Only equality comparisons are implemented.
+ if (opid != Py_EQ && opid != Py_NE) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
+ bool equals = true;
+ // If other is not a message, it cannot be equal.
+ if (!PyObject_TypeCheck(other, &CMessage_Type)) {
+ equals = false;
+ }
+ const google::protobuf::Message* other_message =
+ reinterpret_cast<CMessage*>(other)->message;
+ // If messages don't have the same descriptors, they are not equal.
+ if (equals &&
+ self->message->GetDescriptor() != other_message->GetDescriptor()) {
+ equals = false;
+ }
+ // Check the message contents.
+ if (equals && !google::protobuf::util::MessageDifferencer::Equals(
+ *self->message,
+ *reinterpret_cast<CMessage*>(other)->message)) {
+ equals = false;
+ }
+ if (equals ^ (opid == Py_EQ)) {
+ Py_RETURN_FALSE;
+ } else {
+ Py_RETURN_TRUE;
+ }
}
PyObject* InternalGetScalar(const Message* message,
@@ -1950,7 +2231,7 @@ PyObject* InternalGetSubMessage(
CMessage* self, const FieldDescriptor* field_descriptor) {
const Reflection* reflection = self->message->GetReflection();
const Message& sub_message = reflection->GetMessage(
- *self->message, field_descriptor, message_factory);
+ *self->message, field_descriptor, GetDescriptorPool()->message_factory);
PyObject *message_class = cdescriptor_pool::GetMessageClass(
GetDescriptorPool(), field_descriptor->message_type());
@@ -2085,125 +2366,6 @@ 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(PyObject* cls, PyObject* descriptor) {
- const Descriptor* message_descriptor =
- cdescriptor_pool::RegisterMessageClass(
- GetDescriptorPool(), cls, descriptor);
- if (message_descriptor == NULL) {
- return NULL;
- }
-
- // If there are extension_ranges, the message is "extendable", and extension
- // classes will register themselves in this class.
- if (message_descriptor->extension_range_count() > 0) {
- ScopedPyObjectPtr by_name(PyDict_New());
- if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) {
- return NULL;
- }
- ScopedPyObjectPtr by_number(PyDict_New());
- if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) {
- return NULL;
- }
- }
-
- // 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;
- }
- }
-
- // 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_FromDescriptor(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;
- }
- if (PyObject_SetAttrString(
- cls, enum_descriptor->name().c_str(), wrapped) == -1) {
- return NULL;
- }
-
- // 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_SetAttrString(
- cls, enum_value_descriptor->name().c_str(), value_number) == -1) {
- return 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_FromDescriptor(field));
- if (extension_field == NULL) {
- return NULL;
- }
-
- // Add the extension field to the message class.
- if (PyObject_SetAttrString(
- cls, field->name().c_str(), extension_field) == -1) {
- return NULL;
- }
-
- // For each extension set cls.<extension name>_FIELD_NUMBER = <number>.
- if (!AddFieldNumberToClass(cls, field)) {
- return NULL;
- }
- }
-
- Py_RETURN_NONE;
-}
-
PyObject* DeepCopy(CMessage* self, PyObject* arg) {
PyObject* clone = PyObject_CallObject(
reinterpret_cast<PyObject*>(Py_TYPE(self)), NULL);
@@ -2214,8 +2376,9 @@ PyObject* DeepCopy(CMessage* self, PyObject* arg) {
Py_DECREF(clone);
return NULL;
}
- if (MergeFrom(reinterpret_cast<CMessage*>(clone),
- reinterpret_cast<PyObject*>(self)) == NULL) {
+ if (ScopedPyObjectPtr(MergeFrom(
+ reinterpret_cast<CMessage*>(clone),
+ reinterpret_cast<PyObject*>(self))) == NULL) {
Py_DECREF(clone);
return NULL;
}
@@ -2281,7 +2444,7 @@ PyObject* SetState(CMessage* self, PyObject* state) {
if (serialized == NULL) {
return NULL;
}
- if (ParseFromString(self, serialized) == NULL) {
+ if (ScopedPyObjectPtr(ParseFromString(self, serialized)) == NULL) {
return NULL;
}
Py_RETURN_NONE;
@@ -2314,8 +2477,6 @@ static PyMethodDef Methods[] = {
"Inputs picklable representation of the message." },
{ "__unicode__", (PyCFunction)ToUnicode, METH_NOARGS,
"Outputs a unicode representation of the message." },
- { "AddDescriptors", (PyCFunction)AddDescriptors, METH_O | METH_CLASS,
- "Adds field descriptors to the class" },
{ "ByteSize", (PyCFunction)ByteSize, METH_NOARGS,
"Returns the size of the message in bytes." },
{ "Clear", (PyCFunction)Clear, METH_NOARGS,
@@ -2441,6 +2602,9 @@ PyObject* GetAttr(CMessage* self, PyObject* name) {
if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
PyObject* sub_message = InternalGetSubMessage(self, field_descriptor);
+ if (sub_message == NULL) {
+ return NULL;
+ }
if (!SetCompositeField(self, name, sub_message)) {
Py_DECREF(sub_message);
return NULL;
@@ -2484,7 +2648,7 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) {
} // namespace cmessage
PyTypeObject CMessage_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ PyVarObject_HEAD_INIT(&PyMessageMeta_Type, 0)
FULL_MODULE_NAME ".CMessage", // tp_name
sizeof(CMessage), // tp_basicsize
0, // tp_itemsize
@@ -2497,7 +2661,7 @@ PyTypeObject CMessage_Type = {
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
(reprfunc)cmessage::ToStr, // tp_str
(getattrofunc)cmessage::GetAttr, // tp_getattro
@@ -2580,8 +2744,9 @@ void InitGlobals() {
k_extensions_by_name = PyString_FromString("_extensions_by_name");
k_extensions_by_number = PyString_FromString("_extensions_by_number");
- message_factory = new DynamicMessageFactory();
- message_factory->SetDelegateToGeneratedFactory(true);
+ PyObject *dummy_obj = PySet_New(NULL);
+ kEmptyWeakref = PyWeakref_NewRef(dummy_obj, NULL);
+ Py_DECREF(dummy_obj);
}
bool InitProto2MessageModule(PyObject *m) {
@@ -2598,7 +2763,13 @@ bool InitProto2MessageModule(PyObject *m) {
// Initialize constants defined in this file.
InitGlobals();
- CMessage_Type.tp_hash = PyObject_HashNotImplemented;
+ PyMessageMeta_Type.tp_base = &PyType_Type;
+ if (PyType_Ready(&PyMessageMeta_Type) < 0) {
+ return false;
+ }
+ PyModule_AddObject(m, "MessageMeta",
+ reinterpret_cast<PyObject*>(&PyMessageMeta_Type));
+
if (PyType_Ready(&CMessage_Type) < 0) {
return false;
}
@@ -2628,86 +2799,106 @@ bool InitProto2MessageModule(PyObject *m) {
PyModule_AddObject(m, "Message", reinterpret_cast<PyObject*>(&CMessage_Type));
- RepeatedScalarContainer_Type.tp_hash =
- PyObject_HashNotImplemented;
- if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
- return false;
- }
+ // Initialize Repeated container types.
+ {
+ if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(m, "RepeatedScalarContainer",
- reinterpret_cast<PyObject*>(
- &RepeatedScalarContainer_Type));
+ PyModule_AddObject(m, "RepeatedScalarContainer",
+ reinterpret_cast<PyObject*>(
+ &RepeatedScalarContainer_Type));
- RepeatedCompositeContainer_Type.tp_hash = PyObject_HashNotImplemented;
- if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
- return false;
- }
+ if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(
- m, "RepeatedCompositeContainer",
- reinterpret_cast<PyObject*>(
- &RepeatedCompositeContainer_Type));
-
- // ScalarMapContainer_Type derives from our MutableMapping type.
- PyObject* containers =
- PyImport_ImportModule("google.protobuf.internal.containers");
- if (containers == NULL) {
- return false;
+ PyModule_AddObject(
+ m, "RepeatedCompositeContainer",
+ reinterpret_cast<PyObject*>(
+ &RepeatedCompositeContainer_Type));
+
+ // Register them as collections.Sequence
+ ScopedPyObjectPtr collections(PyImport_ImportModule("collections"));
+ if (collections == NULL) {
+ return false;
+ }
+ ScopedPyObjectPtr mutable_sequence(PyObject_GetAttrString(
+ collections, "MutableSequence"));
+ if (mutable_sequence == NULL) {
+ return false;
+ }
+ if (ScopedPyObjectPtr(PyObject_CallMethod(mutable_sequence, "register", "O",
+ &RepeatedScalarContainer_Type))
+ == NULL) {
+ return false;
+ }
+ if (ScopedPyObjectPtr(PyObject_CallMethod(mutable_sequence, "register", "O",
+ &RepeatedCompositeContainer_Type))
+ == NULL) {
+ return false;
+ }
}
- PyObject* mutable_mapping =
- PyObject_GetAttrString(containers, "MutableMapping");
- Py_DECREF(containers);
+ // Initialize Map container types.
+ {
+ // ScalarMapContainer_Type derives from our MutableMapping type.
+ ScopedPyObjectPtr containers(PyImport_ImportModule(
+ "google.protobuf.internal.containers"));
+ if (containers == NULL) {
+ return false;
+ }
- if (mutable_mapping == NULL) {
- return false;
- }
+ ScopedPyObjectPtr mutable_mapping(
+ PyObject_GetAttrString(containers, "MutableMapping"));
+ if (mutable_mapping == NULL) {
+ return false;
+ }
- if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) {
- Py_DECREF(mutable_mapping);
- return false;
- }
+ if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) {
+ return false;
+ }
- ScalarMapContainer_Type.tp_base =
- reinterpret_cast<PyTypeObject*>(mutable_mapping);
+ Py_INCREF(mutable_mapping);
+ ScalarMapContainer_Type.tp_base =
+ reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
- if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
- return false;
- }
+ if (PyType_Ready(&ScalarMapContainer_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(m, "ScalarMapContainer",
- reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
+ PyModule_AddObject(m, "ScalarMapContainer",
+ reinterpret_cast<PyObject*>(&ScalarMapContainer_Type));
- if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
- return false;
- }
+ if (PyType_Ready(&ScalarMapIterator_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(m, "ScalarMapIterator",
- reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
+ PyModule_AddObject(m, "ScalarMapIterator",
+ reinterpret_cast<PyObject*>(&ScalarMapIterator_Type));
- Py_INCREF(mutable_mapping);
- MessageMapContainer_Type.tp_base =
- reinterpret_cast<PyTypeObject*>(mutable_mapping);
+ Py_INCREF(mutable_mapping);
+ MessageMapContainer_Type.tp_base =
+ reinterpret_cast<PyTypeObject*>(mutable_mapping.get());
- if (PyType_Ready(&MessageMapContainer_Type) < 0) {
- return false;
- }
+ if (PyType_Ready(&MessageMapContainer_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(m, "MessageMapContainer",
- reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
+ PyModule_AddObject(m, "MessageMapContainer",
+ reinterpret_cast<PyObject*>(&MessageMapContainer_Type));
- if (PyType_Ready(&MessageMapIterator_Type) < 0) {
- return false;
- }
+ if (PyType_Ready(&MessageMapIterator_Type) < 0) {
+ return false;
+ }
- PyModule_AddObject(m, "MessageMapIterator",
- reinterpret_cast<PyObject*>(&MessageMapIterator_Type));
+ PyModule_AddObject(m, "MessageMapIterator",
+ reinterpret_cast<PyObject*>(&MessageMapIterator_Type));
+ }
- ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented;
if (PyType_Ready(&ExtensionDict_Type) < 0) {
return false;
}
-
PyModule_AddObject(
m, "ExtensionDict",
reinterpret_cast<PyObject*>(&ExtensionDict_Type));
@@ -2751,6 +2942,7 @@ bool InitProto2MessageModule(PyObject *m) {
}
EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError");
DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError");
+ PythonMessage_class = PyObject_GetAttrString(message_module, "Message");
Py_DECREF(message_module);
PyObject* pickle_module = PyImport_ImportModule("pickle");
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 7360b207..f147d433 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -49,7 +49,6 @@ class Message;
class Reflection;
class FieldDescriptor;
class Descriptor;
-class DynamicMessageFactory;
using internal::shared_ptr;
@@ -221,9 +220,6 @@ PyObject* FindInitializationErrors(CMessage* self);
int SetOwner(CMessage* self, const shared_ptr<Message>& new_owner);
int AssureWritable(CMessage* self);
-
-DynamicMessageFactory* GetMessageFactory();
-
} // namespace cmessage
diff --git a/python/google/protobuf/pyext/message_map_container.cc b/python/google/protobuf/pyext/message_map_container.cc
index ab8d8fb9..a4a7fbfe 100644
--- a/python/google/protobuf/pyext/message_map_container.cc
+++ b/python/google/protobuf/pyext/message_map_container.cc
@@ -32,6 +32,7 @@
#include <google/protobuf/pyext/message_map_container.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/message.h>
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 86b75d0f..fe2e600b 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -38,11 +38,13 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#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/scoped_pyobject_ptr.h>
@@ -74,125 +76,6 @@ namespace repeated_composite_container {
GOOGLE_CHECK((self)->parent == NULL); \
} while (0);
-// Returns a new reference.
-static PyObject* GetKey(PyObject* x) {
- // Just the identity function.
- Py_INCREF(x);
- return x;
-}
-
-#define GET_KEY(keyfunc, value) \
- ((keyfunc) == NULL ? \
- GetKey((value)) : \
- PyObject_CallFunctionObjArgs((keyfunc), (value), NULL))
-
-// Converts a comparison function that returns -1, 0, or 1 into a
-// less-than predicate.
-//
-// Returns -1 on error, 1 if x < y, 0 if x >= y.
-static int islt(PyObject *x, PyObject *y, PyObject *compare) {
- if (compare == NULL)
- return PyObject_RichCompareBool(x, y, Py_LT);
-
- ScopedPyObjectPtr res(PyObject_CallFunctionObjArgs(compare, x, y, NULL));
- if (res == NULL)
- return -1;
- if (!PyInt_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "comparison function must return int, not %.200s",
- Py_TYPE(res)->tp_name);
- return -1;
- }
- return PyInt_AsLong(res) < 0;
-}
-
-// Copied from uarrsort.c but swaps memcpy swaps with protobuf/python swaps
-// TODO(anuraag): Is there a better way to do this then reinventing the wheel?
-static int InternalQuickSort(RepeatedCompositeContainer* self,
- Py_ssize_t start,
- Py_ssize_t limit,
- PyObject* cmp,
- PyObject* keyfunc) {
- if (limit - start <= 1)
- return 0; // Nothing to sort.
-
- GOOGLE_CHECK_ATTACHED(self);
-
- Message* message = self->message;
- const Reflection* reflection = message->GetReflection();
- const FieldDescriptor* descriptor = self->parent_field_descriptor;
- Py_ssize_t left;
- Py_ssize_t right;
-
- PyObject* children = self->child_messages;
-
- do {
- left = start;
- right = limit;
- ScopedPyObjectPtr mid(
- GET_KEY(keyfunc, PyList_GET_ITEM(children, (start + limit) / 2)));
- do {
- ScopedPyObjectPtr key(GET_KEY(keyfunc, PyList_GET_ITEM(children, left)));
- int is_lt = islt(key, mid, cmp);
- if (is_lt == -1)
- return -1;
- /* array[left]<x */
- while (is_lt) {
- ++left;
- ScopedPyObjectPtr key(GET_KEY(keyfunc,
- PyList_GET_ITEM(children, left)));
- is_lt = islt(key, mid, cmp);
- if (is_lt == -1)
- return -1;
- }
- key.reset(GET_KEY(keyfunc, PyList_GET_ITEM(children, right - 1)));
- is_lt = islt(mid, key, cmp);
- if (is_lt == -1)
- return -1;
- while (is_lt) {
- --right;
- ScopedPyObjectPtr key(GET_KEY(keyfunc,
- PyList_GET_ITEM(children, right - 1)));
- is_lt = islt(mid, key, cmp);
- if (is_lt == -1)
- return -1;
- }
- if (left < right) {
- --right;
- if (left < right) {
- reflection->SwapElements(message, descriptor, left, right);
- PyObject* tmp = PyList_GET_ITEM(children, left);
- PyList_SET_ITEM(children, left, PyList_GET_ITEM(children, right));
- PyList_SET_ITEM(children, right, tmp);
- }
- ++left;
- }
- } while (left < right);
-
- if ((right - start) < (limit - left)) {
- /* sort [start..right[ */
- if (start < (right - 1)) {
- InternalQuickSort(self, start, right, cmp, keyfunc);
- }
-
- /* sort [left..limit[ */
- start = left;
- } else {
- /* sort [left..limit[ */
- if (left < (limit - 1)) {
- InternalQuickSort(self, left, limit, cmp, keyfunc);
- }
-
- /* sort [start..right[ */
- limit = right;
- }
- } while (start < (limit - 1));
-
- return 0;
-}
-
-#undef GET_KEY
-
// ---------------------------------------------------------------------
// len()
@@ -329,7 +212,7 @@ PyObject* Extend(RepeatedCompositeContainer* self, PyObject* value) {
return NULL;
}
CMessage* new_cmessage = reinterpret_cast<CMessage*>(new_message.get());
- if (cmessage::MergeFrom(new_cmessage, next) == NULL) {
+ if (ScopedPyObjectPtr(cmessage::MergeFrom(new_cmessage, next)) == NULL) {
return NULL;
}
}
@@ -455,58 +338,39 @@ static PyObject* RichCompare(RepeatedCompositeContainer* self,
// ---------------------------------------------------------------------
// sort()
-static PyObject* SortAttached(RepeatedCompositeContainer* self,
- PyObject* args,
- PyObject* kwds) {
- // Sort the underlying Message array.
- PyObject *compare = NULL;
- int reverse = 0;
- PyObject *keyfunc = NULL;
- static char *kwlist[] = {"cmp", "key", "reverse", 0};
-
- if (args != NULL) {
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:sort",
- kwlist, &compare, &keyfunc, &reverse))
- return NULL;
- }
- if (compare == Py_None)
- compare = NULL;
- if (keyfunc == Py_None)
- keyfunc = NULL;
-
+static void ReorderAttached(RepeatedCompositeContainer* self) {
+ Message* message = self->message;
+ const Reflection* reflection = message->GetReflection();
+ const FieldDescriptor* descriptor = self->parent_field_descriptor;
const Py_ssize_t length = Length(self);
- if (InternalQuickSort(self, 0, length, compare, keyfunc) < 0)
- return NULL;
-
- // Finally reverse the result if requested.
- if (reverse) {
- 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)
- reflection->SwapElements(message, descriptor, i, length - i - 1);
+ // Since Python protobuf objects are never arena-allocated, adding and
+ // removing message pointers to the underlying array is just updating
+ // pointers.
+ for (Py_ssize_t i = 0; i < length; ++i)
+ reflection->ReleaseLast(message, descriptor);
- // Reverse the Python list.
- ScopedPyObjectPtr res(PyObject_CallMethod(self->child_messages,
- "reverse", NULL));
- if (res == NULL)
- return NULL;
+ for (Py_ssize_t i = 0; i < length; ++i) {
+ CMessage* py_cmsg = reinterpret_cast<CMessage*>(
+ PyList_GET_ITEM(self->child_messages, i));
+ reflection->AddAllocatedMessage(message, descriptor, py_cmsg->message);
}
-
- Py_RETURN_NONE;
}
-static PyObject* SortReleased(RepeatedCompositeContainer* self,
- PyObject* args,
- PyObject* kwds) {
+// Returns 0 if successful; returns -1 and sets an exception if
+// unsuccessful.
+static int SortPythonMessages(RepeatedCompositeContainer* self,
+ PyObject* args,
+ PyObject* kwds) {
ScopedPyObjectPtr m(PyObject_GetAttrString(self->child_messages, "sort"));
if (m == NULL)
- return NULL;
+ return -1;
if (PyObject_Call(m, args, kwds) == NULL)
- return NULL;
- Py_RETURN_NONE;
+ return -1;
+ if (self->message != NULL) {
+ ReorderAttached(self);
+ }
+ return 0;
}
static PyObject* Sort(RepeatedCompositeContainer* self,
@@ -527,11 +391,10 @@ static PyObject* Sort(RepeatedCompositeContainer* self,
if (UpdateChildMessages(self) < 0) {
return NULL;
}
- if (self->message == NULL) {
- return SortReleased(self, args, kwds);
- } else {
- return SortAttached(self, args, kwds);
+ if (SortPythonMessages(self, args, kwds) < 0) {
+ return NULL;
}
+ Py_RETURN_NONE;
}
// ---------------------------------------------------------------------
@@ -584,18 +447,6 @@ void ReleaseLastTo(CMessage* parent,
parent->message->GetReflection()->ReleaseLast(parent->message, field));
// TODO(tibell): Deal with proto1.
- // ReleaseMessage will return NULL which differs from
- // child_cmessage->message, if the field does not exist. In this case,
- // the latter points to the default instance via a const_cast<>, so we
- // have to reset it to a new mutable object since we are taking ownership.
- if (released_message.get() == NULL) {
- const Message* prototype =
- cmessage::GetMessageFactory()->GetPrototype(
- target->message->GetDescriptor());
- GOOGLE_CHECK_NOTNULL(prototype);
- released_message.reset(prototype->New());
- }
-
target->parent = NULL;
target->parent_field_descriptor = NULL;
target->message = released_message.get();
@@ -732,7 +583,7 @@ PyTypeObject RepeatedCompositeContainer_Type = {
0, // tp_as_number
&repeated_composite_container::SqMethods, // tp_as_sequence
&repeated_composite_container::MpMethods, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index fd196836..7565c6fd 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -39,10 +39,12 @@
#endif
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/descriptor.h>
#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/scoped_pyobject_ptr.h>
@@ -68,7 +70,7 @@ static int InternalAssignRepeatedField(
self->parent_field_descriptor);
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(list); ++i) {
PyObject* value = PyList_GET_ITEM(list, i);
- if (Append(self, value) == NULL) {
+ if (ScopedPyObjectPtr(Append(self, value)) == NULL) {
return -1;
}
}
@@ -510,7 +512,7 @@ PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) {
}
ScopedPyObjectPtr next;
while ((next.reset(PyIter_Next(iter))) != NULL) {
- if (Append(self, next) == NULL) {
+ if (ScopedPyObjectPtr(Append(self, next)) == NULL) {
return NULL;
}
}
@@ -690,8 +692,7 @@ static int InitializeAndCopyToParentContainer(
if (values == NULL) {
return -1;
}
- Message* new_message = cmessage::GetMessageFactory()->GetPrototype(
- from->message->GetDescriptor())->New();
+ Message* new_message = from->message->New();
to->parent = NULL;
to->parent_field_descriptor = from->parent_field_descriptor;
to->message = new_message;
@@ -781,7 +782,7 @@ PyTypeObject RepeatedScalarContainer_Type = {
0, // tp_as_number
&repeated_scalar_container::SqMethods, // tp_as_sequence
&repeated_scalar_container::MpMethods, // tp_as_mapping
- 0, // tp_hash
+ PyObject_HashNotImplemented, // tp_hash
0, // tp_call
0, // tp_str
0, // tp_getattro
diff --git a/python/google/protobuf/pyext/scalar_map_container.cc b/python/google/protobuf/pyext/scalar_map_container.cc
index 6f731d27..80d29425 100644
--- a/python/google/protobuf/pyext/scalar_map_container.cc
+++ b/python/google/protobuf/pyext/scalar_map_container.cc
@@ -32,6 +32,7 @@
#include <google/protobuf/pyext/scalar_map_container.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/pyext/message.h>
diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
index 18ddd5cd..9979b83b 100644
--- a/python/google/protobuf/pyext/scoped_pyobject_ptr.h
+++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
@@ -51,16 +51,22 @@ class ScopedPyObjectPtr {
// Reset. Deletes the current owned object, if any.
// Then takes ownership of a new object, if given.
- // this->reset(this->get()) works.
+ // This function must be called with a reference that you own.
+ // this->reset(this->get()) is wrong!
+ // this->reset(this->release()) is OK.
PyObject* reset(PyObject* p = NULL) {
- if (p != ptr_) {
- Py_XDECREF(ptr_);
- ptr_ = p;
- }
+ Py_XDECREF(ptr_);
+ ptr_ = p;
return ptr_;
}
+ // ScopedPyObjectPtr should not be copied.
+ // We explicitly list and delete this overload to avoid automatic conversion
+ // to PyObject*, which is wrong in this case.
+ PyObject* reset(const ScopedPyObjectPtr& other) = delete;
+
// Releases ownership of the object.
+ // The caller now owns the returned reference.
PyObject* release() {
PyObject* p = ptr_;
ptr_ = NULL;
diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py
index 82fca661..0c757264 100755
--- a/python/google/protobuf/reflection.py
+++ b/python/google/protobuf/reflection.py
@@ -49,101 +49,23 @@ __author__ = 'robinson@google.com (Will Robinson)'
from google.protobuf.internal import api_implementation
-from google.protobuf import descriptor as descriptor_mod
from google.protobuf import message
-_FieldDescriptor = descriptor_mod.FieldDescriptor
-
if api_implementation.Type() == 'cpp':
from google.protobuf.pyext import cpp_message as message_impl
else:
from google.protobuf.internal import python_message as message_impl
-_NewMessage = message_impl.NewMessage
-_InitMessage = message_impl.InitMessage
-
-
-class GeneratedProtocolMessageType(type):
-
- """Metaclass for protocol message classes created at runtime from Descriptors.
-
- We add implementations for all methods described in the Message class. We
- also create properties to allow getting/setting all fields in the protocol
- message. Finally, we create slots to prevent users from accidentally
- "setting" nonexistent fields in the protocol message, which then wouldn't get
- serialized / deserialized properly.
-
- The protocol compiler currently uses this metaclass to create protocol
- message classes at runtime. Clients can also manually create their own
- classes at runtime, as in this example:
-
- mydescriptor = Descriptor(.....)
- class MyProtoClass(Message):
- __metaclass__ = GeneratedProtocolMessageType
- DESCRIPTOR = mydescriptor
- myproto_instance = MyProtoClass()
- myproto.foo_field = 23
- ...
-
- The above example will not work for nested types. If you wish to include them,
- use reflection.MakeClass() instead of manually instantiating the class in
- order to create the appropriate class structure.
- """
-
- # Must be consistent with the protocol-compiler code in
- # proto2/compiler/internal/generator.*.
- _DESCRIPTOR_KEY = 'DESCRIPTOR'
-
- def __new__(cls, name, bases, dictionary):
- """Custom allocation for runtime-generated class types.
-
- We override __new__ because this is apparently the only place
- where we can meaningfully set __slots__ on the class we're creating(?).
- (The interplay between metaclasses and slots is not very well-documented).
-
- Args:
- name: Name of the class (ignored, but required by the
- metaclass protocol).
- bases: Base classes of the class we're constructing.
- (Should be message.Message). We ignore this field, but
- it's required by the metaclass protocol
- dictionary: The class dictionary of the class we're
- constructing. dictionary[_DESCRIPTOR_KEY] must contain
- a Descriptor object describing this protocol message
- type.
-
- Returns:
- Newly-allocated class.
- """
- descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
- bases = _NewMessage(bases, descriptor, dictionary)
- superclass = super(GeneratedProtocolMessageType, cls)
-
- new_class = superclass.__new__(cls, name, bases, dictionary)
- return new_class
-
- def __init__(cls, name, bases, dictionary):
- """Here we perform the majority of our work on the class.
- We add enum getters, an __init__ method, implementations
- of all Message methods, and properties for all fields
- in the protocol type.
-
- Args:
- name: Name of the class (ignored, but required by the
- metaclass protocol).
- bases: Base classes of the class we're constructing.
- (Should be message.Message). We ignore this field, but
- it's required by the metaclass protocol
- dictionary: The class dictionary of the class we're
- constructing. dictionary[_DESCRIPTOR_KEY] must contain
- a Descriptor object describing this protocol message
- type.
- """
- descriptor = dictionary[GeneratedProtocolMessageType._DESCRIPTOR_KEY]
- _InitMessage(descriptor, cls)
- superclass = super(GeneratedProtocolMessageType, cls)
- superclass.__init__(name, bases, dictionary)
+# The type of all Message classes.
+# Part of the public interface.
+#
+# Used by generated files, but clients can also use it at runtime:
+# mydescriptor = pool.FindDescriptor(.....)
+# class MyProtoClass(Message):
+# __metaclass__ = GeneratedProtocolMessageType
+# DESCRIPTOR = mydescriptor
+GeneratedProtocolMessageType = message_impl.GeneratedProtocolMessageType
def ParseMessage(descriptor, byte_str):
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index 8cbd6822..82133765 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -113,7 +113,7 @@ def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False,
fields.sort(key=lambda x: x[0].index)
for field, value in fields:
if _IsMapEntry(field):
- for key in value:
+ for key in sorted(value):
# This is slow for maps with submessage entires because it copies the
# entire tree. Unfortunately this would take significant refactoring
# of this file to work around.
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
index c66fdfad..c6ed37ae 100644
--- a/src/google/protobuf/any.cc
+++ b/src/google/protobuf/any.cc
@@ -50,7 +50,7 @@ AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value)
void AnyMetadata::PackFrom(const Message& message) {
type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
- GetTypeUrl(message.GetDescriptor()));
+ GetTypeUrl(message.GetDescriptor()));
message.SerializeToString(value_->MutableNoArena(
&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
}
@@ -76,7 +76,7 @@ bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
type_url.size() - prefix_len);
return true;
}
- return true;
+ return false;
}
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
index f681eceb..7eeb6b70 100644
--- a/src/google/protobuf/any.h
+++ b/src/google/protobuf/any.h
@@ -34,9 +34,9 @@
#include <string>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arenastring.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
+#include <google/protobuf/arenastring.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index ed1c5ef2..907a6a20 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -66,8 +66,12 @@ void Arena::Init() {
first_block->size = options_.initial_block_size;
first_block->pos = kHeaderSize;
first_block->next = NULL;
- first_block->owner = &first_block->owner;
- AddBlock(first_block);
+ // Thread which calls Init() owns the first block. This allows the
+ // single-threaded case to allocate on the first block without taking any
+ // locks.
+ first_block->owner = &thread_cache();
+ SetThreadCacheBlock(first_block);
+ AddBlockInternal(first_block);
owns_first_block_ = false;
}
@@ -80,7 +84,7 @@ void Arena::Init() {
}
Arena::~Arena() {
- uint64 space_allocated = Reset();
+ uint64 space_allocated = ResetInternal();
// Call the destruction hook
if (options_.on_arena_destruction != NULL) {
@@ -89,10 +93,14 @@ Arena::~Arena() {
}
uint64 Arena::Reset() {
- CleanupList();
- uint64 space_allocated = FreeBlocks();
// Invalidate any ThreadCaches pointing to any blocks we just destroyed.
lifecycle_id_ = lifecycle_id_generator_.GetNext();
+ return ResetInternal();
+}
+
+uint64 Arena::ResetInternal() {
+ CleanupList();
+ uint64 space_allocated = FreeBlocks();
// Call the reset hook
if (options_.on_arena_reset != NULL) {
@@ -137,6 +145,10 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
void Arena::AddBlock(Block* b) {
MutexLock l(&blocks_lock_);
+ AddBlockInternal(b);
+}
+
+void Arena::AddBlockInternal(Block* b) {
b->next = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
if (b->avail() != 0) {
@@ -181,16 +193,6 @@ void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) {
void* me = &thread_cache();
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
if (!b || b->owner != me || b->avail() < n) {
- // If the next block to allocate from is the first block, try to claim it
- // for this thread.
- if (!owns_first_block_ && b->next == NULL) {
- MutexLock l(&blocks_lock_);
- if (b->owner == &b->owner && b->avail() >= n) {
- b->owner = me;
- SetThreadCacheBlock(b);
- return AllocFromBlock(b, n);
- }
- }
return SlowAlloc(n);
}
return AllocFromBlock(b, n);
@@ -267,8 +269,12 @@ uint64 Arena::FreeBlocks() {
// Make the first block that was passed in through ArenaOptions
// available for reuse.
first_block->pos = kHeaderSize;
- first_block->owner = &first_block->owner;
- AddBlock(first_block);
+ // Thread which calls Reset() owns the first block. This allows the
+ // single-threaded case to allocate on the first block without taking any
+ // locks.
+ first_block->owner = &thread_cache();
+ SetThreadCacheBlock(first_block);
+ AddBlockInternal(first_block);
}
return space_allocated;
}
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 51149bae..f06be4a3 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -31,6 +31,7 @@
#ifndef GOOGLE_PROTOBUF_ARENA_H__
#define GOOGLE_PROTOBUF_ARENA_H__
+#include <limits>
#if __cplusplus >= 201103L
#include <google/protobuf/stubs/type_traits.h>
#endif
@@ -39,7 +40,8 @@
#include <google/protobuf/stubs/atomic_sequence_num.h>
#include <google/protobuf/stubs/atomicops.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/platform_macros.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/type_traits.h>
namespace google {
@@ -414,6 +416,9 @@ class LIBPROTOBUF_EXPORT Arena {
// trivially destructible.
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) {
+ GOOGLE_CHECK_LE(num_elements,
+ std::numeric_limits<size_t>::max() / sizeof(T))
+ << "Requested size is too large to fit into size_t.";
if (arena == NULL) {
return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
} else {
@@ -425,16 +430,16 @@ 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;
+ GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceAllocated() const;
// As above, but does not include any free space in underlying blocks.
- uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE;
+ GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const;
// Frees all storage allocated by this arena after calling destructors
// registered with OwnDestructor() and freeing objects registered with Own().
// Any objects allocated on this arena are unusable after this call. It also
// returns the total space used by the arena which is the sums of the sizes
// of the allocated blocks. This method is not thread-safe.
- uint64 Reset() GOOGLE_ATTRIBUTE_NOINLINE;
+ GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset();
// Adds |object| to a list of heap-allocated objects to be freed with |delete|
// when the arena is destroyed or reset.
@@ -459,8 +464,8 @@ class LIBPROTOBUF_EXPORT Arena {
// will be manually called when the arena is destroyed or reset. This differs
// from OwnDestructor() in that any member function may be specified, not only
// the class destructor.
- void OwnCustomDestructor(void* object, void (*destruct)(void*))
- GOOGLE_ATTRIBUTE_NOINLINE {
+ GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object,
+ void (*destruct)(void*)) {
AddListNode(object, destruct);
}
@@ -469,7 +474,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(const T* value) {
+ static ::google::protobuf::Arena* GetArena(const T* value) {
return GetArenaInternal(value, static_cast<T*>(0));
}
@@ -507,7 +512,7 @@ class LIBPROTOBUF_EXPORT Arena {
// aligned at a multiple of 8 bytes.
size_t pos;
size_t size; // total size of the block.
- size_t avail() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE { return size - pos; }
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
// data follows
};
@@ -555,6 +560,33 @@ class LIBPROTOBUF_EXPORT Arena {
return google::protobuf::internal::has_trivial_destructor<T>::value;
}
+ // Helper typetrait that indicates whether the desctructor of type T should be
+ // called when arena is destroyed at compile time. This is only to allow
+ // construction of higher-level templated utilities.
+ // is_destructor_skippable<T>::value is an instance of google::protobuf::internal::true_type if the
+ // destructor of the message type T should not be called when arena is
+ // destroyed or google::protobuf::internal::has_trivial_destructor<T>::value == true, and
+ // google::protobuf::internal::false_type otherwise.
+ //
+ // This is inside Arena because only Arena has the friend relationships
+ // necessary to see the underlying generated code traits.
+ template<typename T>
+ struct is_destructor_skippable {
+ template<typename U>
+ static char DestructorSkippable(
+ const typename U::DestructorSkippable_*);
+ template<typename U>
+ static double DestructorSkippable(...);
+
+ // This will resolve to either google::protobuf::internal::true_type or google::protobuf::internal::false_type.
+ typedef google::protobuf::internal::integral_constant<bool,
+ sizeof(DestructorSkippable<const T>(static_cast<const T*>(0))) ==
+ sizeof(char) || google::protobuf::internal::has_trivial_destructor<T>::value == true>
+ type;
+ static const type value;
+ };
+
+
// CreateMessage<T> requires that T supports arenas, but this private method
// works whether or not T supports arenas. These are not exposed to user code
// as it can cause confusing API usages, and end up having double free in
@@ -574,14 +606,16 @@ class LIBPROTOBUF_EXPORT Arena {
// Just allocate the required size for the given type assuming the
// type has a trivial constructor.
template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternalRawArray(size_t num_elements) {
+ T* CreateInternalRawArray(size_t num_elements) {
+ GOOGLE_CHECK_LE(num_elements,
+ std::numeric_limits<size_t>::max() / sizeof(T))
+ << "Requested size is too large to fit into size_t.";
return static_cast<T*>(
AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
}
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternal(
- bool skip_explicit_ownership) {
+ T* CreateInternal(bool skip_explicit_ownership) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
@@ -590,8 +624,7 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternal(
- bool skip_explicit_ownership, const Arg& arg) {
+ T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
if (!skip_explicit_ownership) {
AddListNode(t, &internal::arena_destruct_object<T>);
@@ -600,7 +633,7 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateInternal(
+ T* CreateInternal(
bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
if (!skip_explicit_ownership) {
@@ -610,10 +643,10 @@ class LIBPROTOBUF_EXPORT Arena {
}
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) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3);
if (!skip_explicit_ownership) {
@@ -624,11 +657,11 @@ class LIBPROTOBUF_EXPORT Arena {
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) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4);
if (!skip_explicit_ownership) {
@@ -639,12 +672,12 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5);
if (!skip_explicit_ownership) {
@@ -655,13 +688,13 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5,
- const Arg6& arg6) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5, arg6);
if (!skip_explicit_ownership) {
@@ -672,14 +705,14 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5,
- const Arg6& arg6,
- const Arg7& arg7) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
if (!skip_explicit_ownership) {
@@ -691,15 +724,15 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4, typename Arg5, typename Arg6, typename Arg7,
typename Arg8>
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership,
- const Arg1& arg1,
- const Arg2& arg2,
- const Arg3& arg3,
- const Arg4& arg4,
- const Arg5& arg5,
- const Arg6& arg6,
- const Arg7& arg7,
- const Arg8& arg8) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+ const Arg1& arg1,
+ const Arg2& arg2,
+ const Arg3& arg3,
+ const Arg4& arg4,
+ const Arg5& arg5,
+ const Arg6& arg6,
+ const Arg7& arg7,
+ const Arg8& arg8) {
T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
if (!skip_explicit_ownership) {
@@ -709,21 +742,21 @@ class LIBPROTOBUF_EXPORT Arena {
}
template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
+ T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
this);
}
template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
- const Arg& arg) {
+ T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg& arg) {
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
this, arg);
}
template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
- inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
- const Arg1& arg1, const Arg2& arg2) {
+ T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
+ const Arg1& arg1, const Arg2& arg2) {
return CreateInternal<T, Arena*>(SkipDeleteList<T>(static_cast<T*>(0)),
this, arg1, arg2);
}
@@ -734,19 +767,29 @@ class LIBPROTOBUF_EXPORT Arena {
template <typename T>
static void CreateInArenaStorage(T* ptr, Arena* arena) {
CreateInArenaStorageInternal(ptr, arena, is_arena_constructable<T>::value);
+ RegisterDestructorInternal(ptr, arena, is_destructor_skippable<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;
}
+ template <typename T>
+ static void RegisterDestructorInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::true_type) {}
+ template <typename T>
+ static void RegisterDestructorInternal(
+ T* ptr, Arena* arena, google::protobuf::internal::false_type) {
+ arena->OwnDestructor(ptr);
+ }
+
// 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
@@ -769,13 +812,13 @@ 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(const T* value,
- typename T::InternalArenaConstructable_*) {
+ static ::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(const T* value, ...) {
+ static ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) {
return NULL;
}
@@ -785,7 +828,7 @@ class LIBPROTOBUF_EXPORT Arena {
void* AllocateAligned(const std::type_info* allocated, size_t n);
// Allocate an internal allocation, avoiding optional typed monitoring.
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline void* AllocateAligned(size_t n) {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* AllocateAligned(size_t n) {
return AllocateAligned(NULL, n);
}
@@ -803,6 +846,7 @@ class LIBPROTOBUF_EXPORT Arena {
void AddListNode(void* elem, void (*cleanup)(void*));
// Delete or Destruct all objects owned by the arena.
void CleanupList();
+ uint64 ResetInternal();
inline void SetThreadCacheBlock(Block* block) {
thread_cache().last_block_used_ = block;
@@ -829,6 +873,9 @@ class LIBPROTOBUF_EXPORT Arena {
Mutex blocks_lock_;
void AddBlock(Block* b);
+ // Access must be synchronized, either by blocks_lock_ or by being called from
+ // Init()/Reset().
+ void AddBlockInternal(Block* b);
void* SlowAlloc(size_t n);
Block* FindBlock(void* me);
Block* NewBlock(void* me, Block* my_last_block, size_t n,
@@ -854,6 +901,11 @@ const typename Arena::is_arena_constructable<T>::type
Arena::is_arena_constructable<T>::value =
typename Arena::is_arena_constructable<T>::type();
+template<typename T>
+const typename Arena::is_destructor_skippable<T>::type
+ Arena::is_destructor_skippable<T>::value =
+ typename Arena::is_destructor_skippable<T>::type();
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc
index 21f55c6e..df9c5bd6 100644
--- a/src/google/protobuf/arena_test_util.cc
+++ b/src/google/protobuf/arena_test_util.cc
@@ -28,6 +28,7 @@
// (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/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena_test_util.h>
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 6c185695..c9ca1fd1 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -40,7 +40,9 @@
#include <typeinfo>
#include <vector>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
@@ -619,8 +621,6 @@ TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) {
}
}
-// N.B.: no reflection version of this test because all the arena-specific code
-// is in RepeatedPtrField, and the reflection works implicitly based on that.
TEST(ArenaTest, AddAllocatedToRepeatedField) {
// Heap->arena case.
Arena arena1;
@@ -680,6 +680,55 @@ TEST(ArenaTest, AddAllocatedToRepeatedField) {
}
}
+TEST(ArenaTest, AddAllocatedToRepeatedFieldViaReflection) {
+ // Heap->arena case.
+ Arena arena1;
+ TestAllTypes* arena1_message = Arena::CreateMessage<TestAllTypes>(&arena1);
+ const Reflection* r = arena1_message->GetReflection();
+ const Descriptor* d = arena1_message->GetDescriptor();
+ const FieldDescriptor* fd =
+ d->FindFieldByName("repeated_nested_message");
+ for (int i = 0; i < 10; i++) {
+ TestAllTypes::NestedMessage* heap_submessage =
+ new TestAllTypes::NestedMessage;
+ heap_submessage->set_bb(42);
+ r->AddAllocatedMessage(arena1_message, fd, heap_submessage);
+ // Should not copy object -- will use arena_->Own().
+ EXPECT_EQ(heap_submessage,
+ &arena1_message->repeated_nested_message(i));
+ EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+ }
+
+ // Arena1->Arena2 case.
+ arena1_message->Clear();
+ for (int i = 0; i < 10; i++) {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ r->AddAllocatedMessage(arena1_message, fd, arena2_submessage);
+ // Should copy object.
+ EXPECT_NE(arena2_submessage,
+ &arena1_message->repeated_nested_message(i));
+ EXPECT_EQ(42, arena1_message->repeated_nested_message(i).bb());
+ }
+
+ // Arena->heap case.
+ TestAllTypes* heap_message = new TestAllTypes;
+ for (int i = 0; i < 10; i++) {
+ Arena arena2;
+ TestAllTypes::NestedMessage* arena2_submessage =
+ Arena::CreateMessage<TestAllTypes::NestedMessage>(&arena2);
+ arena2_submessage->set_bb(42);
+ r->AddAllocatedMessage(heap_message, fd, arena2_submessage);
+ // Should copy object.
+ EXPECT_NE(arena2_submessage,
+ &heap_message->repeated_nested_message(i));
+ EXPECT_EQ(42, heap_message->repeated_nested_message(i).bb());
+ }
+ delete heap_message;
+}
+
TEST(ArenaTest, ReleaseLastRepeatedField) {
// Release from arena-allocated repeated field and ensure that returned object
// is heap-allocated.
@@ -1230,7 +1279,7 @@ TEST(ArenaTest, ArenaHooksSanity) {
EXPECT_EQ(1, ArenaHooksTestUtil::num_init);
EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations);
::google::protobuf::Arena::Create<uint64>(&arena);
- if (::google::protobuf::internal::has_trivial_destructor<uint64>::value) {
+ if (google::protobuf::internal::has_trivial_destructor<uint64>::value) {
EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations);
} else {
EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations);
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index d829ed91..1dacdc68 100755
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -33,6 +33,7 @@
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/fastmem.h>
@@ -145,7 +146,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
// Swaps internal pointers. Arena-safety semantics: this is guarded by the
// logic in Swap()/UnsafeArenaSwap() at the message level, so this method is
// 'unsafe' if called directly.
- inline void Swap(ArenaStringPtr* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(ArenaStringPtr* other) {
std::swap(ptr_, other->ptr_);
}
@@ -283,9 +284,8 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
private:
::std::string* ptr_;
- inline void CreateInstance(::google::protobuf::Arena* arena,
- const ::std::string* initial_value)
- GOOGLE_ATTRIBUTE_NOINLINE {
+ GOOGLE_ATTRIBUTE_NOINLINE void CreateInstance(::google::protobuf::Arena* arena,
+ const ::std::string* initial_value) {
// Assumes ptr_ is not NULL.
if (initial_value != NULL) {
ptr_ = new ::std::string(*initial_value);
@@ -296,8 +296,7 @@ struct LIBPROTOBUF_EXPORT ArenaStringPtr {
arena->Own(ptr_);
}
}
- inline void CreateInstanceNoArena(const ::std::string* initial_value)
- GOOGLE_ATTRIBUTE_NOINLINE {
+ GOOGLE_ATTRIBUTE_NOINLINE void CreateInstanceNoArena(const ::std::string* initial_value) {
if (initial_value != NULL) {
ptr_ = new ::std::string(*initial_value);
} else {
diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
index 8ebd4b9c..3fb582be 100644
--- a/src/google/protobuf/arenastring_unittest.cc
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -42,6 +42,7 @@
#endif
#include <cstdlib>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 0039b00a..473eb4e6 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index e8871861..26a4f0b0 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -70,6 +70,7 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/map_util.h>
@@ -1657,7 +1658,11 @@ bool CommandLineInterface::WriteDescriptorSet(
&already_seen, file_set.mutable_file());
}
} else {
+ set<const FileDescriptor*> already_seen;
for (int i = 0; i < parsed_files.size(); i++) {
+ if (!already_seen.insert(parsed_files[i]).second) {
+ continue;
+ }
FileDescriptorProto* file_proto = file_set.add_file();
parsed_files[i]->CopyTo(file_proto);
if (source_info_in_descriptor_set_) {
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index e5b77c33..46ea5c4e 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -886,6 +886,39 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) {
EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
}
+TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithDuplicates) {
+ 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");
+ CreateTempFile("baz.proto",
+ "syntax = \"proto2\";\n"
+ "import \"foo.proto\";\n"
+ "message Baz {\n"
+ " optional Foo foo = 1;\n"
+ "}\n");
+
+ Run("protocol_compiler --descriptor_set_out=$tmpdir/descriptor_set "
+ "--proto_path=$tmpdir bar.proto foo.proto bar.proto baz.proto");
+
+ ExpectNoErrors();
+
+ FileDescriptorSet descriptor_set;
+ ReadDescriptorSet("descriptor_set", &descriptor_set);
+ if (HasFatalFailure()) return;
+ EXPECT_EQ(3, descriptor_set.file_size());
+ EXPECT_EQ("bar.proto", descriptor_set.file(0).name());
+ EXPECT_EQ("foo.proto", descriptor_set.file(1).name());
+ EXPECT_EQ("baz.proto", descriptor_set.file(2).name());
+ // Descriptor set should not have source code info.
+ EXPECT_FALSE(descriptor_set.file(0).has_source_code_info());
+}
+
TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) {
CreateTempFile("foo.proto",
"syntax = \"proto2\";\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 13ed0b64..c3e9fe74 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -133,8 +133,7 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) {
CppGenerator generator;
MockGeneratorContext context;
string error;
- string parameter;
- parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
+ string parameter = "dllexport_decl=LIBPROTOBUF_EXPORT";
ASSERT_TRUE(generator.Generate(proto_file, parameter,
&context, &error));
parameter = "dllexport_decl=LIBPROTOC_EXPORT";
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 70d3a600..de4d7cc7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -32,7 +32,6 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
-#include <set>
#include <map>
#include <google/protobuf/compiler/cpp/cpp_enum.h>
@@ -70,14 +69,11 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
EnumGenerator::~EnumGenerator() {}
-void EnumGenerator::GenerateForwardDeclaration(io::Printer* printer) {
+void EnumGenerator::FillForwardDeclaration(set<string>* enum_names) {
if (!options_.proto_h) {
return;
}
- map<string, string> vars;
- vars["classname"] = classname_;
- printer->Print(vars, "enum $classname$ : int;\n");
- printer->Print(vars, "bool $classname$_IsValid(int value);\n");
+ enum_names->insert(classname_);
}
void EnumGenerator::GenerateDefinition(io::Printer* printer) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
index 3e930856..f3aa72e4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -35,6 +35,7 @@
#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
+#include <set>
#include <string>
#include <google/protobuf/compiler/cpp/cpp_options.h>
#include <google/protobuf/descriptor.h>
@@ -60,11 +61,11 @@ class EnumGenerator {
// Header stuff.
- // Generate header code to forward-declare the enum. This is for use when
+ // Fills the name to use when declaring the enum. This is for use when
// generating other .proto.h files. This code should be placed within the
// enum's package namespace, but NOT within any class, even for nested
// enums.
- void GenerateForwardDeclaration(io::Printer* printer);
+ void FillForwardDeclaration(set<string>* enum_names);
// Generate header code defining the enum. This code should be placed
// within the enum's package namespace, but NOT within any class, even for
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 965327b1..824e2205 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -35,7 +35,6 @@
#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 43df1d88..8d47d4e0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -47,6 +47,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 1f0a8205..5dae4cdd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/compiler/cpp/cpp_file.h>
+#include <map>
#include <memory>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
@@ -93,22 +94,36 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
FileGenerator::~FileGenerator() {}
-void FileGenerator::GenerateHeader(io::Printer* printer) {
- GenerateTopHeaderGuard(printer);
+void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
+ if (!options_.proto_h) {
+ return;
+ }
+
+ string filename_identifier = FilenameIdentifier(file_->name());
+ GenerateTopHeaderGuard(printer, filename_identifier);
+
GenerateLibraryIncludes(printer);
- GenerateDependencyIncludes(printer);
+
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ const FileDescriptor* dep = file_->public_dependency(i);
+ const char* extension = ".proto.h";
+ string dependency = StripProto(dep->name()) + extension;
+ printer->Print(
+ "#include \"$dependency$\" // IWYU pragma: export\n",
+ "dependency", dependency);
+ }
printer->Print(
"// @@protoc_insertion_point(includes)\n");
+ GenerateForwardDeclarations(printer);
// Open namespace.
GenerateNamespaceOpeners(printer);
GenerateGlobalStateFunctionDeclarations(printer);
- GenerateMessageForwardDeclarations(printer);
printer->Print("\n");
@@ -133,6 +148,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
GenerateInlineFunctionDefinitions(printer);
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n"
+ "\n");
+
// Close up namespace.
GenerateNamespaceClosers(printer);
@@ -144,19 +164,89 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"// @@protoc_insertion_point(global_scope)\n"
"\n");
- GenerateBottomHeaderGuard(printer);
+ GenerateBottomHeaderGuard(printer, filename_identifier);
+}
+
+void FileGenerator::GeneratePBHeader(io::Printer* printer) {
+ string filename_identifier =
+ FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
+ GenerateTopHeaderGuard(printer, filename_identifier);
+
+ if (options_.proto_h) {
+ printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
+ "basename", StripProto(file_->name()));
+ } else {
+ GenerateLibraryIncludes(printer);
+ }
+ GenerateDependencyIncludes(printer);
+
+ printer->Print(
+ "// @@protoc_insertion_point(includes)\n");
+
+
+
+ // Open namespace.
+ GenerateNamespaceOpeners(printer);
+
+ if (!options_.proto_h) {
+ GenerateGlobalStateFunctionDeclarations(printer);
+ GenerateMessageForwardDeclarations(printer);
+
+ printer->Print("\n");
+
+ GenerateEnumDefinitions(printer);
+
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ GenerateMessageDefinitions(printer);
+
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ GenerateServiceDefinitions(printer);
+
+ GenerateExtensionIdentifiers(printer);
+
+ printer->Print("\n");
+ printer->Print(kThickSeparator);
+ printer->Print("\n");
+
+ GenerateInlineFunctionDefinitions(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(namespace_scope)\n");
+
+ // Close up namespace.
+ GenerateNamespaceClosers(printer);
+
+ if (!options_.proto_h) {
+ // We need to specialize some templates in the ::google::protobuf namespace:
+ GenerateProto2NamespaceEnumSpecializations(printer);
+ }
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(global_scope)\n"
+ "\n");
+
+ GenerateBottomHeaderGuard(printer, filename_identifier);
}
void FileGenerator::GenerateSource(io::Printer* printer) {
+ string header =
+ StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
"// source: $filename$\n"
"\n"
-
// The generated code calls accessors that might be deprecated. We don't
// want the compiler to warn in generated code.
"#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
- "#include \"$basename$.pb.h\"\n"
+ "#include \"$header$\"\n"
"\n"
"#include <algorithm>\n" // for swap()
"\n"
@@ -165,7 +255,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/io/coded_stream.h>\n"
"#include <google/protobuf/wire_format_lite_inl.h>\n",
"filename", file_->name(),
- "basename", StripProto(file_->name()));
+ "header", header);
// Unknown fields implementation in lite mode uses StringOutputStream
if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
@@ -181,6 +271,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"#include <google/protobuf/wire_format.h>\n");
}
+ if (options_.proto_h) {
+ // Use the smaller .proto.h files.
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ const FileDescriptor* dep = file_->dependency(i);
+ const char* extension = ".proto.h";
+ string dependency = StripProto(dep->name()) + extension;
+ printer->Print(
+ "#include \"$dependency$\"\n",
+ "dependency", dependency);
+ }
+ }
+
printer->Print(
"// @@protoc_insertion_point(includes)\n");
@@ -276,6 +378,59 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
"// @@protoc_insertion_point(global_scope)\n");
}
+class FileGenerator::ForwardDeclarations {
+ public:
+ ~ForwardDeclarations() {
+ for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
+ end = namespaces_.end();
+ it != end; ++it) {
+ delete it->second;
+ }
+ namespaces_.clear();
+ }
+
+ ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
+ ForwardDeclarations*& ns = namespaces_[ns_name];
+ if (ns == NULL) {
+ ns = new ForwardDeclarations;
+ }
+ return ns;
+ }
+
+ set<string>& classes() { return classes_; }
+ set<string>& enums() { return enums_; }
+
+ void Print(io::Printer* printer) const {
+ for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
+ it != end; ++it) {
+ printer->Print("enum $enumname$ : int;\n"
+ "bool $enumname$_IsValid(int value);\n",
+ "enumname", it->c_str());
+ }
+ for (set<string>::const_iterator it = classes_.begin(),
+ end = classes_.end();
+ it != end; ++it) {
+ printer->Print("class $classname$;\n", "classname", it->c_str());
+ }
+ for (map<string, ForwardDeclarations *>::const_iterator
+ it = namespaces_.begin(),
+ end = namespaces_.end();
+ it != end; ++it) {
+ printer->Print("namespace $nsname$ {\n",
+ "nsname", it->first);
+ it->second->Print(printer);
+ printer->Print("} // namespace $nsname$\n",
+ "nsname", it->first);
+ }
+ }
+
+
+ private:
+ map<string, ForwardDeclarations*> namespaces_;
+ set<string> classes_;
+ set<string> enums_;
+};
+
void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// AddDescriptors() is a file-level procedure which adds the encoded
// FileDescriptorProto for this .proto file to the global DescriptorPool for
@@ -434,12 +589,17 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
string file_data;
file_proto.SerializeToString(&file_data);
+#ifdef _MSC_VER
+ bool breakdown_large_file = true;
+#else
+ bool breakdown_large_file = false;
+#endif
// Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535
// bytes in length". Declare a static array of characters rather than use a
// string literal.
- if (file_data.size() > 65535) {
+ if (breakdown_large_file && file_data.size() > 65535) {
printer->Print(
- "static const char descriptor[] = {\n");
+ "static const char descriptor[] = {\n");
printer->Indent();
// Only write 25 bytes per line.
@@ -447,26 +607,25 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
for (int i = 0; i < file_data.size();) {
for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
printer->Print(
- "$char$, ",
- "char", SimpleItoa(file_data[i]));
+ "$char$, ",
+ "char", SimpleItoa(file_data[i]));
}
printer->Print(
- "\n");
+ "\n");
}
printer->Outdent();
printer->Print(
- "};\n");
+ "};\n");
printer->Print(
- "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
- "size", SimpleItoa(file_data.size()));
+ "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
+ "size", SimpleItoa(file_data.size()));
} else {
-
printer->Print(
"::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
-
+
// Only write 40 bytes per line.
static const int kBytesPerLine = 40;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
@@ -474,11 +633,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"data",
EscapeTrigraphs(
CEscape(file_data.substr(i, kBytesPerLine))));
- }
- printer->Print(
- ", $size$);\n",
+ }
+ printer->Print(
+ ", $size$);\n",
"size", SimpleItoa(file_data.size()));
-
}
// Call MessageFactory::InternalRegisterGeneratedFile().
@@ -548,8 +706,40 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
}
}
-void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) {
- string filename_identifier = FilenameIdentifier(file_->name());
+void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
+ ForwardDeclarations decls;
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ FileGenerator dependency(file_->dependency(i), options_);
+ dependency.FillForwardDeclarations(&decls);
+ }
+ FillForwardDeclarations(&decls);
+ decls.Print(printer);
+}
+
+void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
+ for (int i = 0; i < file_->public_dependency_count(); i++) {
+ FileGenerator dependency(file_->public_dependency(i), options_);
+ dependency.FillForwardDeclarations(decls);
+ }
+ for (int i = 0; i < package_parts_.size(); i++) {
+ decls = decls->AddOrGetNamespace(package_parts_[i]);
+ }
+ // Generate enum definitions.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
+ }
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ enum_generators_[i]->FillForwardDeclaration(&decls->enums());
+ }
+ // Generate forward declarations of classes.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->FillMessageForwardDeclarations(
+ &decls->classes());
+ }
+}
+
+void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
+ const string& filename_identifier) {
// Generate top of header.
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
@@ -564,8 +754,8 @@ void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) {
"filename_identifier", filename_identifier);
}
-void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer) {
- string filename_identifier = FilenameIdentifier(file_->name());
+void FileGenerator::GenerateBottomHeaderGuard(
+ io::Printer* printer, const string& filename_identifier) {
printer->Print(
"#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
"filename_identifier", filename_identifier);
@@ -696,9 +886,13 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(
}
void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
- // Generate forward declarations of classes.
+ set<string> classes;
for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ message_generators_[i]->FillMessageForwardDeclarations(&classes);
+ }
+ for (set<string>::const_iterator it = classes.begin(), end = classes.end();
+ it != end; ++it) {
+ printer->Print("class $classname$;\n", "classname", it->c_str());
}
}
@@ -804,10 +998,6 @@ void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
// Methods of the dependent base class must always be inline in the header.
message_generators_[i]->GenerateDependentInlineMethods(printer);
}
-
- printer->Print(
- "\n"
- "// @@protoc_insertion_point(namespace_scope)\n");
}
void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index e68f67bb..29cdaea5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -69,10 +69,14 @@ class FileGenerator {
const Options& options);
~FileGenerator();
- void GenerateHeader(io::Printer* printer);
+ void GenerateProtoHeader(io::Printer* printer);
+ void GeneratePBHeader(io::Printer* printer);
void GenerateSource(io::Printer* printer);
private:
+ // Internal type used by GenerateForwardDeclarations (defined in file.cc).
+ class ForwardDeclarations;
+
// Generate the BuildDescriptors() procedure, which builds all descriptors
// for types defined in the file.
void GenerateBuildDescriptors(io::Printer* printer);
@@ -80,9 +84,19 @@ class FileGenerator {
void GenerateNamespaceOpeners(io::Printer* printer);
void GenerateNamespaceClosers(io::Printer* printer);
+ // For other imports, generates their forward-declarations.
+ void GenerateForwardDeclarations(io::Printer* printer);
+
+ // Internal helper used by GenerateForwardDeclarations: fills 'decls'
+ // with all necessary forward-declarations for this file and its
+ // transient depednencies.
+ void FillForwardDeclarations(ForwardDeclarations* decls);
+
// Generates top or bottom of a header file.
- void GenerateTopHeaderGuard(io::Printer* printer);
- void GenerateBottomHeaderGuard(io::Printer* printer);
+ void GenerateTopHeaderGuard(io::Printer* printer,
+ const string& filename_identifier);
+ void GenerateBottomHeaderGuard(io::Printer* printer,
+ const string& filename_identifier);
// Generates #include directives.
void GenerateLibraryIncludes(io::Printer* printer);
@@ -92,10 +106,20 @@ class FileGenerator {
void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
// Generates types for classes.
- void GenerateMessageForwardDeclarations(io::Printer* printer);
void GenerateMessageDefinitions(io::Printer* printer);
+ // Generates forward-declarations for just this file's classes. This is
+ // used for .pb.h headers, but not in proto_h mode.
+ void GenerateMessageForwardDeclarations(io::Printer* printer);
+
+ // Fills in types for forward declarations. This is used internally, and
+ // also by other FileGenerators to determine imports' declarations.
+ void FillMessageForwardDeclarations(ForwardDeclarations* decls);
+ void FillMessageDefinitions(ForwardDeclarations* decls);
+
// Generates enum definitions.
+ void GenerateEnumForwardDeclarations(io::Printer* printer);
+ void FillEnumForwardDeclarations(ForwardDeclarations* decls);
void GenerateEnumDefinitions(io::Printer* printer);
// Generates generic service definitions.
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 99416372..781526b5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -100,16 +100,23 @@ bool CppGenerator::Generate(const FileDescriptor* file,
string basename = StripProto(file->name());
- basename.append(".pb");
FileGenerator file_generator(file, file_options);
- // Generate header.
+ // Generate header(s).
+ if (file_options.proto_h) {
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+ generator_context->Open(basename + ".proto.h"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateProtoHeader(&printer);
+ }
+
+ basename.append(".pb");
{
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
generator_context->Open(basename + ".h"));
io::Printer printer(output.get(), '$');
- file_generator.GenerateHeader(&printer);
+ file_generator.GeneratePBHeader(&printer);
}
// Generate cc file.
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 0f3688d0..678a995a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
@@ -68,7 +69,7 @@ const char* const kKeywordList[] = {
"constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
"double", "dynamic_cast", "else", "enum", "explicit", "extern", "false",
"float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
- "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or",
+ "namespace", "new", "noexcept", "not", "not_eq", "NULL", "operator", "or",
"or_eq", "private", "protected", "public", "register", "reinterpret_cast",
"return", "short", "signed", "sizeof", "static", "static_assert",
"static_cast", "struct", "switch", "template", "this", "thread_local",
@@ -174,6 +175,14 @@ string SuperClassName(const Descriptor* descriptor) {
"::google::protobuf::Message" : "::google::protobuf::MessageLite";
}
+string DependentBaseDownCast() {
+ return "reinterpret_cast<T*>(this)->";
+}
+
+string DependentBaseConstDownCast() {
+ return "reinterpret_cast<const T*>(this)->";
+}
+
string FieldName(const FieldDescriptor* field) {
string result = field->name();
LowerString(&result);
@@ -208,6 +217,19 @@ string FieldConstantName(const FieldDescriptor *field) {
}
bool IsFieldDependent(const FieldDescriptor* field) {
+ if (field->containing_oneof() != NULL &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ return true;
+ }
+ if (field->is_map()) {
+ const Descriptor* map_descriptor = field->message_type();
+ for (int i = 0; i < map_descriptor->field_count(); i++) {
+ if (IsFieldDependent(map_descriptor->field(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
return false;
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 4bbf8303..29c1f90b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -70,8 +70,15 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
// This is a class name, like "ProtoName_InternalBase".
string DependentBaseClassTemplateName(const Descriptor* descriptor);
+// Name of the base class: either the dependent base class (for use with
+// proto_h) or google::protobuf::Message.
string SuperClassName(const Descriptor* descriptor);
+// Returns a string that down-casts from the dependent base class to the
+// derived class.
+string DependentBaseDownCast();
+string DependentBaseConstDownCast();
+
// Get the (unqualified) name that should be used for this field in C++ code.
// The name is coerced to lower-case to emulate proto1 behavior. People
// should be using lowercase-with-underscores style for proto field names
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 0ff0d27c..a14d8986 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -100,8 +100,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
MapFieldGenerator::
MapFieldGenerator(const FieldDescriptor* descriptor,
- const Options& options)
- : descriptor_(descriptor) {
+ const Options& options)
+ : descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -152,7 +153,9 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MapFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Clear();\n");
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+ printer->Print(variables, "$this_message$$name$_.Clear();\n");
}
void MapFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
index d27d4851..5e205623 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -63,6 +63,7 @@ class MapFieldGenerator : public FieldGenerator {
private:
const FieldDescriptor* descriptor_;
+ const bool dependent_field_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index b0e38755..aa10b0bb 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -39,7 +39,6 @@
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
-#include <set>
#include <utility>
#include <vector>
#include <google/protobuf/compiler/cpp/cpp_message.h>
@@ -415,31 +414,34 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
use_dependent_base_ = true;
}
}
+ if (options.proto_h && descriptor->oneof_decl_count() > 0) {
+ // Always make oneofs dependent.
+ use_dependent_base_ = true;
+ }
}
MessageGenerator::~MessageGenerator() {}
void MessageGenerator::
-GenerateMessageForwardDeclaration(io::Printer* printer) {
- printer->Print("class $classname$;\n",
- "classname", classname_);
+FillMessageForwardDeclarations(set<string>* class_names) {
+ class_names->insert(classname_);
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// map entry message doesn't need forward declaration. Since map entry
// message cannot be a top level class, we just need to avoid calling
// GenerateForwardDeclaration here.
if (IsMapEntryMessage(descriptor_->nested_type(i))) continue;
- nested_generators_[i]->GenerateMessageForwardDeclaration(printer);
+ nested_generators_[i]->FillMessageForwardDeclarations(class_names);
}
}
void MessageGenerator::
-GenerateEnumForwardDeclaration(io::Printer* printer) {
+FillEnumForwardDeclarations(set<string>* enum_names) {
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
- nested_generators_[i]->GenerateEnumForwardDeclaration(printer);
+ nested_generators_[i]->FillEnumForwardDeclarations(enum_names);
}
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
- enum_generators_[i]->GenerateForwardDeclaration(printer);
+ enum_generators_[i]->FillForwardDeclaration(enum_names);
}
}
@@ -484,13 +486,6 @@ GenerateDependentFieldAccessorDeclarations(io::Printer* printer) {
field_generators_.get(field).GenerateDependentAccessorDeclarations(printer);
printer->Print("\n");
}
- for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
- PrintFieldComment(printer, oneof);
- printer->Print(
- "void clear_$oneof_name$();\n",
- "oneof_name", oneof->name());
- }
}
void MessageGenerator::
@@ -505,7 +500,9 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
vars["constant_name"] = FieldConstantName(field);
bool dependent_field = use_dependent_base_ && IsFieldDependent(field);
- if (dependent_field) {
+ if (dependent_field &&
+ field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !field->is_map()) {
// If this field is dependent, the dependent base class determines
// the message type from the derived class (which is a template
// parameter). This typedef is for that:
@@ -594,8 +591,8 @@ GenerateDependentFieldAccessorDefinitions(io::Printer* printer) {
vars["tmpl"] = "template<class T>\n";
vars["dependent_classname"] =
DependentBaseClassTemplateName(descriptor_) + "<T>";
- vars["this_message"] = "reinterpret_cast<T*>(this)->";
- vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ vars["this_message"] = DependentBaseDownCast();
+ vars["this_const_message"] = DependentBaseConstDownCast();
GenerateFieldClear(field, vars, printer);
}
@@ -721,13 +718,15 @@ GenerateFieldClear(const FieldDescriptor* field,
printer->Print(vars,
"if ($this_message$has_$name$()) {\n");
printer->Indent();
- field_generators_.get(field).GenerateClearingCode(printer);
+ field_generators_.get(field)
+ .GenerateClearingCode(printer);
printer->Print(vars,
"$this_message$clear_has_$oneof_name$();\n");
printer->Outdent();
printer->Print("}\n");
} else {
- field_generators_.get(field).GenerateClearingCode(printer);
+ field_generators_.get(field)
+ .GenerateClearingCode(printer);
if (HasFieldPresence(descriptor_->file())) {
if (!field->is_repeated()) {
printer->Print(vars,
@@ -752,6 +751,18 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
map<string, string> vars;
SetCommonFieldVariables(field, &vars, options_);
vars["inline"] = is_inline ? "inline " : "";
+ if (use_dependent_base_ && IsFieldDependent(field)) {
+ vars["tmpl"] = "template<class T>\n";
+ vars["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_) + "<T>";
+ vars["this_message"] = "reinterpret_cast<T*>(this)->";
+ vars["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ } else {
+ vars["tmpl"] = "";
+ vars["dependent_classname"] = vars["classname"];
+ vars["this_message"] = "";
+ vars["this_const_message"] = "";
+ }
// Generate has_$name$() or $name$_size().
if (field->is_repeated()) {
@@ -775,10 +786,6 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) {
}
if (!use_dependent_base_ || !IsFieldDependent(field)) {
- vars["tmpl"] = "";
- vars["dependent_classname"] = vars["classname"];
- vars["this_message"] = "";
- vars["this_const_message"] = "";
GenerateFieldClear(field, vars, printer);
}
@@ -915,15 +922,32 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"\n");
} else {
- printer->Print(
- "inline const ::std::string& unknown_fields() const {\n"
- " return _unknown_fields_;\n"
- "}\n"
- "\n"
- "inline ::std::string* mutable_unknown_fields() {\n"
- " return &_unknown_fields_;\n"
- "}\n"
- "\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "inline const ::std::string& unknown_fields() const {\n"
+ " return _unknown_fields_.Get(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+ "}\n"
+ "\n"
+ "inline ::std::string* mutable_unknown_fields() {\n"
+ " return _unknown_fields_.Mutable(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+ " GetArenaNoVirtual());\n"
+ "}\n"
+ "\n");
+ } else {
+ printer->Print(
+ "inline const ::std::string& unknown_fields() const {\n"
+ " return _unknown_fields_.GetNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+ "}\n"
+ "\n"
+ "inline ::std::string* mutable_unknown_fields() {\n"
+ " return _unknown_fields_.MutableNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"
+ "}\n"
+ "\n");
+ }
}
}
@@ -1068,6 +1092,10 @@ GenerateClassDefinition(io::Printer* printer) {
}
}
uses_string_ = false;
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file())) {
+ uses_string_ = true;
+ }
for (int i = 0; i < descriptors.size(); i++) {
const FieldDescriptor* field = descriptors[i];
if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
@@ -1201,18 +1229,11 @@ GenerateClassDefinition(io::Printer* printer) {
// Generate oneof function declarations
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
- if (use_dependent_base_) {
- printer->Print(
- "inline bool has_$oneof_name$() const;\n"
- "inline void clear_has_$oneof_name$();\n\n",
- "oneof_name", descriptor_->oneof_decl(i)->name());
- } else {
- printer->Print(
- "inline bool has_$oneof_name$() const;\n"
- "void clear_$oneof_name$();\n"
- "inline void clear_has_$oneof_name$();\n\n",
- "oneof_name", descriptor_->oneof_decl(i)->name());
- }
+ printer->Print(
+ "inline bool has_$oneof_name$() const;\n"
+ "void clear_$oneof_name$();\n"
+ "inline void clear_has_$oneof_name$();\n\n",
+ "oneof_name", descriptor_->oneof_decl(i)->name());
}
if (HasGeneratedMethods(descriptor_->file()) &&
@@ -1262,7 +1283,7 @@ GenerateClassDefinition(io::Printer* printer) {
"::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
} else {
printer->Print(
- "::std::string _unknown_fields_;\n"
+ "::google::protobuf::internal::ArenaStringPtr _unknown_fields_;\n"
"::google::protobuf::Arena* _arena_ptr_;\n"
"\n");
}
@@ -1919,6 +1940,13 @@ GenerateSharedConstructorCode(io::Printer* printer) {
uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "",
"_cached_size_ = 0;\n").c_str());
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "_unknown_fields_.UnsafeSetDefault(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+ }
+
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
field_generators_.get(descriptor_->field(i))
@@ -1955,6 +1983,22 @@ GenerateSharedDestructorCode(io::Printer* printer) {
"}\n"
"\n");
}
+
+ // Write the desctructor for _unknown_fields_ in lite runtime.
+ if (PreserveUnknownFields(descriptor_) &&
+ !UseUnknownFieldSet(descriptor_->file())) {
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "_unknown_fields_.Destroy(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(
+ "_unknown_fields_.DestroyNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+ }
+ }
+
// Write the destructors for each field except oneof members.
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
@@ -2463,8 +2507,16 @@ GenerateClear(io::Printer* printer) {
" mutable_unknown_fields()->Clear();\n"
"}\n");
} else {
- printer->Print(
- "mutable_unknown_fields()->clear();\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "_unknown_fields_.ClearToEmpty(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(
+ "_unknown_fields_.ClearToEmptyNoArena(\n"
+ " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n");
+ }
}
}
@@ -2481,33 +2533,22 @@ GenerateOneofClear(io::Printer* printer) {
oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name();
string message_class;
- if (use_dependent_base_) {
- oneof_vars["tmpl"] = "template<class T>\n";
- oneof_vars["inline"] = "inline ";
- oneof_vars["dependent_classname"] =
- DependentBaseClassTemplateName(descriptor_) + "<T>";
- oneof_vars["this_message"] = "reinterpret_cast<T*>(this)->";
- message_class = "T::";
- } else {
- oneof_vars["tmpl"] = "";
- oneof_vars["inline"] = "";
- oneof_vars["dependent_classname"] = classname_;
- oneof_vars["this_message"] = "";
- }
-
printer->Print(oneof_vars,
- "$tmpl$"
- "$inline$"
- "void $dependent_classname$::clear_$oneofname$() {\n");
+ "void $classname$::clear_$oneofname$() {\n");
printer->Indent();
+ // In .proto.h mode, fields with a dependent type will generate
+ // clearing code that down casts from the dependent base class.
+ // However, clear_oneof() methods are always in the .cc file, and thus
+ // must remain in the derived base. So, to make the clearing code work,
+ // we add a typedef so that the down cast works (it will be a no-op).
printer->Print(oneof_vars,
- "switch($this_message$$oneofname$_case()) {\n");
+ "typedef $classname$ T;\n"
+ "switch($oneofname$_case()) {\n");
printer->Indent();
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(
- "case $message_class$k$field_name$: {\n",
- "message_class", message_class,
+ "case k$field_name$: {\n",
"field_name", UnderscoresToCamelCase(field->name(), true));
printer->Indent();
// We clear only allocated objects in oneofs
@@ -2524,20 +2565,16 @@ GenerateOneofClear(io::Printer* printer) {
"}\n");
}
printer->Print(
- "case $message_class$$cap_oneof_name$_NOT_SET: {\n"
+ "case $cap_oneof_name$_NOT_SET: {\n"
" break;\n"
"}\n",
- "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
printer->Print(
"}\n"
- "$this_message$_oneof_case_[$oneof_index$] = "
- "$message_class$$cap_oneof_name$_NOT_SET;\n",
- "this_message", oneof_vars["this_message"],
+ "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n",
"oneof_index", SimpleItoa(i),
- "message_class", message_class,
"cap_oneof_name",
ToUpper(descriptor_->oneof_decl(i)->name()));
printer->Outdent();
@@ -2612,7 +2649,7 @@ GenerateSwap(io::Printer* printer) {
printer->Print(
"_internal_metadata_.Swap(&other->_internal_metadata_);\n");
} else {
- printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n");
+ printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
}
} else {
// Still swap internal_metadata as it may contain more than just
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 23dad10c..8e19a3f0 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -39,8 +39,8 @@
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <set>
#include <string>
-#include <vector>
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <google/protobuf/compiler/cpp/cpp_options.h>
@@ -66,9 +66,10 @@ class MessageGenerator {
// Header stuff.
- // Generate foward declarations for this class and all its nested types.
- void GenerateMessageForwardDeclaration(io::Printer* printer);
- void GenerateEnumForwardDeclaration(io::Printer* printer);
+ // Return names for foward declarations of this class and all its nested
+ // types.
+ void FillMessageForwardDeclarations(set<string>* class_names);
+ void FillEnumForwardDeclarations(set<string>* enum_names);
// Generate definitions of all nested enums (must come before class
// definitions because those classes use the enums definitions).
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index ba318d10..b4545892 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -63,6 +63,14 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
SafeFunctionName(descriptor->containing_type(),
descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
+ if (options.proto_h && IsFieldDependent(descriptor)) {
+ (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor);
+ (*variables)["dependent_typename"] =
+ "typename T::" + DependentTypeName(descriptor);
+ } else {
+ (*variables)["dependent_type"] = FieldMessageTypeName(descriptor);
+ (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor);
+ }
}
} // namespace
@@ -85,7 +93,21 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+}
+
+void MessageFieldGenerator::
GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
+ // Arena manipulation code is out-of-line in the derived message class.
+ printer->Print(variables_,
+ "$type$* mutable_$name$()$deprecation$;\n"
+ "$type$* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
}
void MessageFieldGenerator::
@@ -103,11 +125,13 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"$type$* _slow_$release_name$()$deprecation$;\n"
"public:\n");
}
- printer->Print(variables_,
- "const $type$& $name$() const$deprecation$;\n"
- "$type$* mutable_$name$()$deprecation$;\n"
- "$type$* $release_name$()$deprecation$;\n"
- "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ GenerateGetterDeclaration(printer);
+ if (!dependent_field_) {
+ printer->Print(variables_,
+ "$type$* mutable_$name$()$deprecation$;\n"
+ "$type$* $release_name$()$deprecation$;\n"
+ "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ }
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
"$type$* unsafe_arena_release_$name$()$deprecation$;\n"
@@ -123,12 +147,12 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
"void $classname$::_slow_mutable_$name$() {\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
} else {
printer->Print(variables_,
- " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
}
printer->Print(variables_,
"}\n"
@@ -151,7 +175,7 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
if (SupportsArenas(descriptor_->message_type())) {
// NOTE: the same logic is mirrored in weak_message_field.cc. Any
// arena-related semantics changes should be made in both places.
- printer->Print(variables_,
+ printer->Print(variables_,
"void $classname$::_slow_set_allocated_$name$(\n"
" ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
" if (message_arena != NULL && \n"
@@ -189,15 +213,139 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
void MessageFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
+
+ map<string, string> variables(variables_);
+ // For the CRTP base class, all mutation methods are dependent, and so
+ // they must be in the header.
+ variables["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = DependentBaseDownCast();
+ if (!variables["set_hasbit"].empty()) {
+ variables["set_hasbit"] =
+ variables["this_message"] + variables["set_hasbit"];
+ }
+ if (!variables["clear_hasbit"].empty()) {
+ variables["clear_hasbit"] =
+ variables["this_message"] + variables["clear_hasbit"];
+ }
+
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if ($name$_ == NULL) {\n"
+ " $this_message$_slow_mutable_$name$();\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::$release_name$() {\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $clear_hasbit$\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+ " return $this_message$_slow_$release_name$();\n"
+ " } else {\n"
+ " $dependent_typename$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ "}\n"
+ "template <class T>\n"
+ "inline void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if (message_arena == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " if ($name$ != NULL) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ // If we're on an arena and the incoming message is not, simply Own() it
+ // rather than copy to the arena -- either way we need a heap dealloc,
+ // so we might as well defer it. Otherwise, if incoming message is on a
+ // different ownership domain (specific arena, or the heap) than we are,
+ // copy to our arena (or heap, as the case may be).
+ printer->Print(variables,
+ " $this_message$_slow_set_allocated_$name$(message_arena, "
+ "&$name$);\n");
+ } else {
+ printer->Print(variables,
+ " if (message_arena != NULL) {\n"
+ " message_arena->Own($name$);\n"
+ " }\n");
+ }
+ printer->Print(variables,
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ // TODO(dlj): move insertion points to message class.
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ } else {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " if ($name$_ == NULL) {\n"
+ " $name$_ = new $dependent_typename$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " $dependent_typename$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n"
+ "template <class T>\n"
+ "inline void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
+ " delete $name$_;\n");
+
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables,
+ " if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)"
+ "->GetArena() != NULL) {\n"
+ " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ }
+
+ printer->Print(variables,
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ }
}
void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
+ "$inline$const $type$& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n");
PrintHandlingOptionalStaticInitializers(
@@ -206,19 +354,25 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
// Without.
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
+ printer->Print(variables, "}\n");
+
+ if (dependent_field_) {
+ return;
+ }
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
+ "$inline$"
+ "$type$* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" if ($name$_ == NULL) {\n"
- " _slow_mutable_$name$();"
+ " _slow_mutable_$name$();\n"
" }\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"
" return _slow_$release_name$();\n"
@@ -228,7 +382,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return temp;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\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"
@@ -260,8 +415,8 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n");
} else {
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"
@@ -269,13 +424,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@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())) {
@@ -301,15 +458,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
if (!HasFieldPresence(descriptor_->file())) {
// If we don't have has-bits, message presence is indicated only by ptr !=
// NULL. Thus on clear, we need to delete the object.
- printer->Print(variables_,
- "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) delete $name$_;\n"
- "$name$_ = NULL;\n");
+ printer->Print(variables,
+ "if ($this_message$GetArenaNoVirtual() == NULL && "
+ "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n"
+ "$this_message$$name$_ = NULL;\n");
} else {
- printer->Print(variables_,
- "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
+ printer->Print(variables,
+ "if ($this_message$$name$_ != NULL) $this_message$$name$_->"
+ "$dependent_type$::Clear();\n");
}
}
@@ -370,79 +531,149 @@ GenerateByteSize(io::Printer* printer) const {
MessageOneofFieldGenerator::
MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : MessageFieldGenerator(descriptor, options) {
+ : MessageFieldGenerator(descriptor, options),
+ dependent_base_(options.proto_h) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
+
+void MessageOneofFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ // Oneof field getters must be dependent as they call default_instance().
+ // Otherwise, the logic is the same as MessageFields.
+ if (!dependent_field_) {
+ return;
+ }
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+ MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateGetterDeclaration(io::Printer* printer) const {
+ // Oneof field getters must be dependent as they call default_instance().
+ // Unlike MessageField, this means there is no (non-dependent) getter to
+ // generate.
+ if (dependent_field_) {
+ return;
+ }
+ printer->Print(variables_,
+ "const $type$& $name$() const$deprecation$;\n");
+}
+
void MessageOneofFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ // For the CRTP base class, all mutation methods are dependent, and so
+ // they must be in the header.
+ if (!dependent_base_) {
+ return;
+ }
+ map<string, string> variables(variables_);
+ variables["inline"] = "inline ";
+ variables["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = "reinterpret_cast<T*>(this)->";
+ // Const message access is needed for the dependent getter.
+ variables["this_const_message"] = "reinterpret_cast<const T*>(this)->";
+ variables["tmpl"] = "template <class T>\n";
+ variables["field_member"] = variables["this_message"] +
+ variables["oneof_prefix"] + variables["name"] +
+ "_";
+ InternalGenerateInlineAccessorDefinitions(variables, printer);
}
void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
+ if (dependent_base_) {
+ return;
+ }
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
+ variables["dependent_classname"] = variables["classname"];
+ variables["this_message"] = "";
+ variables["this_const_message"] = "";
+ variables["tmpl"] = "";
+ variables["field_member"] =
+ variables["oneof_prefix"] + variables["name"] + "_";
+ variables["dependent_type"] = variables["type"];
+ InternalGenerateInlineAccessorDefinitions(variables, printer);
+}
+
+void MessageOneofFieldGenerator::
+GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["field_member"] =
+ variables["oneof_prefix"] + variables["name"] + "_";
+
+ //printer->Print(variables,
+}
+
+void MessageOneofFieldGenerator::
+InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
+ io::Printer* printer) const {
+ printer->Print(variables,
+ "$tmpl$"
+ "$inline$ "
+ "const $type$& $dependent_classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $this_const_message$has_$name$()\n"
+ " ? *$this_const_message$$oneof_prefix$$name$_\n"
+ " : $dependent_type$::default_instance();\n"
+ "}\n");
+
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return has_$name$() ? *$oneof_prefix$$name$_\n"
- " : $type$::default_instance();\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n");
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::mutable_$name$() {\n"
+ " if (!$this_message$has_$name$()) {\n"
+ " $this_message$clear_$oneof_name$();\n"
+ " $this_message$set_has_$name$();\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables,
- " $oneof_prefix$$name$_ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $field_member$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n");
} else {
printer->Print(variables,
- " $oneof_prefix$$name$_ = \n"
- " ::google::protobuf::Arena::Create< $type$ >(\n"
- " GetArenaNoVirtual());\n");
+ " $this_message$$oneof_prefix$$name$_ = \n"
+ " ::google::protobuf::Arena::Create< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n");
}
printer->Print(variables,
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $oneof_prefix$$name$_;\n"
+ " return $field_member$;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " if (GetArenaNoVirtual() != NULL) {\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::$release_name$() {\n"
+ " if ($this_message$has_$name$()) {\n"
+ " $this_message$clear_has_$oneof_name$();\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
// N.B.: safe to use the underlying field pointer here because we are sure
// that it is non-NULL (because has_$name$() returned true).
- " $type$* temp = new $type$;\n"
- " temp->MergeFrom(*$oneof_prefix$$name$_);\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ " $dependent_typename$* temp = new $dependent_typename$;\n"
+ " temp->MergeFrom(*$field_member$);\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" } else {\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ " $dependent_typename$* temp = $field_member$;\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" }\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
- " return temp;\n"
- " } else {\n"
- " return NULL;\n"
- " }\n"
- "}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " clear_$oneof_name$();\n"
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $this_message$clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
@@ -450,32 +681,42 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
// If incoming message is on the heap and we are on an arena, just Own()
// it (see above). If it's on a different arena than we are or one of us
// is on the heap, we make a copy to our arena/heap.
- " if (GetArenaNoVirtual() != NULL &&\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL &&\n"
" ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
- " } else if (GetArenaNoVirtual() !=\n"
+ " $this_message$GetArenaNoVirtual()->Own($name$);\n"
+ " } else if ($this_message$GetArenaNoVirtual() !=\n"
" ::google::protobuf::Arena::GetArena($name$)) {\n"
- " $type$* new_$name$ = \n"
- " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
- " GetArenaNoVirtual());\n"
+ " $dependent_typename$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
+ " $this_message$GetArenaNoVirtual());\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
} else {
printer->Print(variables,
- " if (GetArenaNoVirtual() != NULL) {\n"
- " GetArenaNoVirtual()->Own($name$);\n"
+ " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
+ " $this_message$GetArenaNoVirtual()->Own($name$);\n"
" }\n");
}
printer->Print(variables,
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
- "$type$* $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"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "$inline$ void $classname$::unsafe_arena_set_allocated_$name$"
+ "($type$* $name$) {\n"
// We rely on the oneof clear method to free the earlier contents of this
// oneof. We can directly use the pointer we're given to set the new
// value.
@@ -489,44 +730,47 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
"}\n");
} else {
printer->Print(variables,
- "$inline$ const $type$& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return has_$name$() ? *$oneof_prefix$$name$_\n"
- " : $type$::default_instance();\n"
- "}\n"
- "$inline$ $type$* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = new $type$;\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::mutable_$name$() {\n"
+ " if (!$this_message$has_$name$()) {\n"
+ " $this_message$clear_$oneof_name$();\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = new $dependent_typename$;\n"
" }\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $oneof_prefix$$name$_;\n"
+ " return $field_member$;\n"
"}\n"
- "$inline$ $type$* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
+ "$tmpl$"
+ "$inline$"
+ "$type$* $dependent_classname$::$release_name$() {\n"
+ " if ($this_message$has_$name$()) {\n"
+ " $this_message$clear_has_$oneof_name$();\n"
+ " $dependent_typename$* temp = $field_member$;\n"
+ " $field_member$ = NULL;\n"
" return temp;\n"
" } else {\n"
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " clear_$oneof_name$();\n"
+ "$tmpl$"
+ "$inline$"
+ "void $dependent_classname$::"
+ "set_allocated_$name$($type$* $name$) {\n"
+ " $this_message$clear_$oneof_name$();\n"
" if ($name$) {\n");
if (SupportsArenas(descriptor_->message_type())) {
printer->Print(variables,
- " if ($name$->GetArena() != NULL) {\n"
- " $type$* new_$name$ = new $type$;\n"
+ " if (static_cast< $dependent_typename$*>($name$)->"
+ "GetArena() != NULL) {\n"
+ " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
" new_$name$->CopyFrom(*$name$);\n"
" $name$ = new_$name$;\n"
" }\n");
}
printer->Print(variables,
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
+ " $this_message$set_has_$name$();\n"
+ " $field_member$ = $name$;\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
@@ -535,14 +779,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "if (GetArenaNoVirtual() == NULL) {\n"
- " delete $oneof_prefix$$name$_;\n"
+ printer->Print(variables,
+ "if ($this_message$GetArenaNoVirtual() == NULL) {\n"
+ " delete $this_message$$oneof_prefix$$name$_;\n"
"}\n");
} else {
- printer->Print(variables_,
- "delete $oneof_prefix$$name$_;\n");
+ printer->Print(variables,
+ "delete $this_message$$oneof_prefix$$name$_;\n");
}
}
@@ -562,7 +808,9 @@ GenerateConstructorCode(io::Printer* printer) const {
RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : descriptor_(descriptor) {
+ : descriptor_(descriptor),
+ dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
+ dependent_getter_(dependent_field_ && options.safe_boundary_check) {
SetMessageVariables(descriptor, &variables_, options);
}
@@ -575,60 +823,160 @@ GeneratePrivateMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
-GenerateDependentAccessorDeclarations(io::Printer* printer) const {
-}
-
-void RepeatedMessageFieldGenerator::
-GenerateAccessorDeclarations(io::Printer* printer) const {
+InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
- "const $type$& $name$(int index) const$deprecation$;\n"
"$type$* mutable_$name$(int index)$deprecation$;\n"
"$type$* add_$name$()$deprecation$;\n");
+ if (dependent_getter_) {
+ printer->Print(variables_,
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n");
+ }
printer->Print(variables_,
- "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- " $name$() const$deprecation$;\n"
"::google::protobuf::RepeatedPtrField< $type$ >*\n"
" mutable_$name$()$deprecation$;\n");
}
void RepeatedMessageFieldGenerator::
-GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+ if (dependent_getter_) {
+ printer->Print(variables_,
+ "const $type$& $name$(int index) const$deprecation$;\n");
+ }
+ if (dependent_field_) {
+ InternalGenerateTypeDependentAccessorDeclarations(printer);
+ }
}
void RepeatedMessageFieldGenerator::
-GenerateInlineAccessorDefinitions(io::Printer* printer,
- bool is_inline) const {
+GenerateAccessorDeclarations(io::Printer* printer) const {
+ if (!dependent_getter_) {
+ printer->Print(variables_,
+ "const $type$& $name$(int index) const$deprecation$;\n");
+ }
+ if (!dependent_field_) {
+ InternalGenerateTypeDependentAccessorDeclarations(printer);
+ }
+ if (!dependent_getter_) {
+ printer->Print(variables_,
+ "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ " $name$() const$deprecation$;\n");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
+ if (!dependent_field_) {
+ return;
+ }
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ // For the CRTP base class, all mutation methods are dependent, and so
+ // they must be in the header.
+ variables["dependent_classname"] =
+ DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
+ variables["this_message"] = DependentBaseDownCast();
+ variables["this_const_message"] = DependentBaseConstDownCast();
+
+ if (dependent_getter_) {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline const $type$& $dependent_classname$::$name$(int index) const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $this_const_message$$name$_.$cppget$(index);\n"
+ "}\n");
+ }
+
+ // Generate per-element accessors:
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"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n"
+ // TODO(dlj): move insertion points
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_.Mutable(index);\n"
+ " return $this_message$$name$_.Mutable(index);\n"
"}\n"
- "$inline$ $type$* $classname$::add_$name$() {\n"
+ "template <class T>\n"
+ "inline $type$* $dependent_classname$::add_$name$() {\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
- " return $name$_.Add();\n"
+ " return $this_message$$name$_.Add();\n"
"}\n");
+
+
+ if (dependent_getter_) {
+ printer->Print(variables,
+ "template <class T>\n"
+ "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+ "$dependent_classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_list:$full_name$)\n"
+ " return $this_const_message$$name$_;\n"
+ "}\n");
+ }
+
+ // Generate mutable access to the entire list:
printer->Print(variables,
- "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
- "$classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_list:$full_name$)\n"
- " return $name$_;\n"
- "}\n"
- "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n"
- "$classname$::mutable_$name$() {\n"
+ "template <class T>\n"
+ "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$dependent_classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
- " return &$name$_;\n"
+ " return &$this_message$$name$_;\n"
"}\n");
}
void RepeatedMessageFieldGenerator::
+GenerateInlineAccessorDefinitions(io::Printer* printer,
+ bool is_inline) const {
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline " : "";
+
+ if (!dependent_getter_) {
+ 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");
+ }
+
+ if (!dependent_field_) {
+ printer->Print(variables,
+ "$inline$"
+ "$type$* $classname$::mutable_$name$(int index) {\n"
+ // TODO(dlj): move insertion points
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_.Mutable(index);\n"
+ "}\n"
+ "$inline$"
+ "$type$* $classname$::add_$name$() {\n"
+ " // @@protoc_insertion_point(field_add:$full_name$)\n"
+ " return $name$_.Add();\n"
+ "}\n");
+ }
+
+
+ if (!dependent_field_) {
+ printer->Print(variables,
+ "$inline$"
+ "::google::protobuf::RepeatedPtrField< $type$ >*\n"
+ "$classname$::mutable_$name$() {\n"
+ " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
+ " return &$name$_;\n"
+ "}\n");
+ }
+ if (!dependent_getter_) {
+ 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");
+ }
+}
+
+void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Clear();\n");
+ map<string, string> variables(variables_);
+ variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
+ printer->Print(variables, "$this_message$$name$_.Clear();\n");
}
void RepeatedMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
index 9ddf9643..35efd0fa 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h
@@ -68,6 +68,11 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateByteSize(io::Printer* printer) const;
protected:
+ void GenerateArenaManipulationCode(const map<string, string>& variables,
+ io::Printer* printer) const;
+
+ virtual void GenerateGetterDeclaration(io::Printer* printer) const;
+
const FieldDescriptor* descriptor_;
const bool dependent_field_;
map<string, string> variables_;
@@ -83,15 +88,23 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
~MessageOneofFieldGenerator();
// implements FieldGenerator ---------------------------------------
+ void GenerateDependentAccessorDeclarations(io::Printer* printer) const;
void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const;
- void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {}
+ void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
+ protected:
+ void GenerateGetterDeclaration(io::Printer* printer) const;
+
private:
+ void InternalGenerateInlineAccessorDefinitions(
+ const map<string, string>& variables, io::Printer* printer) const;
+
+ const bool dependent_base_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
};
@@ -118,7 +131,12 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
void GenerateByteSize(io::Printer* printer) const;
private:
+ void InternalGenerateTypeDependentAccessorDeclarations(
+ io::Printer* printer) const;
+
const FieldDescriptor* descriptor_;
+ const bool dependent_field_;
+ const bool dependent_getter_;
map<string, string> variables_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 1a3896a1..d1af6dda 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -421,7 +421,8 @@ GenerateByteSize(io::Printer* printer) const {
StringOneofFieldGenerator::
StringOneofFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : StringFieldGenerator(descriptor, options) {
+ : StringFieldGenerator(descriptor, options),
+ dependent_field_(options.proto_h) {
SetCommonOneofFieldVariables(descriptor, &variables_);
}
@@ -604,13 +605,29 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
void StringOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ map<string, string> variables(variables_);
+ if (dependent_field_) {
+ variables["this_message"] = DependentBaseDownCast();
+ // This clearing code may be in the dependent base class. If the default
+ // value is an empty string, then the $default_variable$ is a global
+ // singleton. If the default is not empty, we need to down-cast to get the
+ // default value's global singleton instance. See SetStringVariables() for
+ // possible values of default_variable.
+ if (!descriptor_->default_value_string().empty()) {
+ variables["default_variable"] =
+ DependentBaseDownCast() + variables["default_variable"];
+ }
+ } else {
+ variables["this_message"] = "";
+ }
if (SupportsArenas(descriptor_)) {
- printer->Print(variables_,
- "$oneof_prefix$$name$_.Destroy($default_variable$,\n"
- " GetArenaNoVirtual());\n");
+ printer->Print(variables,
+ "$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n"
+ " $this_message$GetArenaNoVirtual());\n");
} else {
- printer->Print(variables_,
- "$oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n");
+ printer->Print(variables,
+ "$this_message$$oneof_prefix$$name$_."
+ "DestroyNoArena($default_variable$);\n");
}
}
@@ -664,7 +681,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
RepeatedStringFieldGenerator::
RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
const Options& options)
- : descriptor_(descriptor) {
+ : descriptor_(descriptor) {
SetStringVariables(descriptor, &variables_, options);
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index d1f19cd9..616e2067 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -93,6 +93,7 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
void GenerateMergeFromCodedStream(io::Printer* printer) const;
private:
+ const bool dependent_field_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
};
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index bd1c0fde..e5ef6ecd 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -67,7 +67,9 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index 43eb0ed5..33c9328f 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -44,6 +44,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 0353b607..8a09f3a8 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -181,8 +181,8 @@ void EnumGenerator::Generate(io::Printer* printer) {
" internalGetValueMap() {\n"
" return internalValueMap;\n"
"}\n"
- "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
- " internalValueMap =\n"
+ "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+ " $classname$> internalValueMap =\n"
" new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
" public $classname$ findValueByNumber(int number) {\n"
" return $classname$.valueOf(number);\n"
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 39318a19..558da968 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index 697a07a7..2c3608c2 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
index e69de29b..62186386 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -0,0 +1,226 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+bool EnumHasCustomOptions(const EnumDescriptor* descriptor) {
+ if (descriptor->options().unknown_fields().field_count() > 0) return true;
+ for (int i = 0; i < descriptor->value_count(); ++i) {
+ const EnumValueDescriptor* value = descriptor->value(i);
+ if (value->options().unknown_fields().field_count() > 0) return true;
+ }
+ return false;
+}
+} // namespace
+
+EnumLiteGenerator::EnumLiteGenerator(const EnumDescriptor* descriptor,
+ bool immutable_api,
+ Context* context)
+ : descriptor_(descriptor), immutable_api_(immutable_api),
+ name_resolver_(context->GetNameResolver()) {
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ canonical_values_.push_back(value);
+ } else {
+ Alias alias;
+ alias.value = value;
+ alias.canonical_value = canonical_value;
+ aliases_.push_back(alias);
+ }
+ }
+}
+
+EnumLiteGenerator::~EnumLiteGenerator() {}
+
+void EnumLiteGenerator::Generate(io::Printer* printer) {
+ WriteEnumDocComment(printer, descriptor_);
+ if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(
+ "public enum $classname$\n"
+ " implements com.google.protobuf.ProtocolMessageEnum {\n",
+ "classname", descriptor_->name());
+ } else {
+ printer->Print(
+ "public enum $classname$\n"
+ " implements com.google.protobuf.Internal.EnumLite {\n",
+ "classname", descriptor_->name());
+ }
+ printer->Indent();
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ map<string, string> vars;
+ vars["name"] = canonical_values_[i]->name();
+ vars["index"] = SimpleItoa(canonical_values_[i]->index());
+ vars["number"] = SimpleItoa(canonical_values_[i]->number());
+ WriteEnumValueDocComment(printer, canonical_values_[i]);
+ if (canonical_values_[i]->options().deprecated()) {
+ printer->Print("@java.lang.Deprecated\n");
+ }
+ printer->Print(vars,
+ "$name$($index$, $number$),\n");
+ }
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print("UNRECOGNIZED(-1, -1),\n");
+ }
+
+ printer->Print(
+ ";\n"
+ "\n");
+
+ // -----------------------------------------------------------------
+
+ for (int i = 0; i < aliases_.size(); i++) {
+ map<string, string> vars;
+ vars["classname"] = descriptor_->name();
+ vars["name"] = aliases_[i].value->name();
+ vars["canonical_name"] = aliases_[i].canonical_value->name();
+ WriteEnumValueDocComment(printer, aliases_[i].value);
+ printer->Print(vars,
+ "public static final $classname$ $name$ = $canonical_name$;\n");
+ }
+
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ map<string, string> vars;
+ vars["name"] = descriptor_->value(i)->name();
+ vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+ WriteEnumValueDocComment(printer, descriptor_->value(i));
+ printer->Print(vars,
+ "public static final int $name$_VALUE = $number$;\n");
+ }
+ printer->Print("\n");
+
+ // -----------------------------------------------------------------
+
+ printer->Print(
+ "\n"
+ "public final int getNumber() {\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ " if (index == -1) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Can't get the number of an unknown enum value.\");\n"
+ " }\n");
+ }
+ printer->Print(
+ " return value;\n"
+ "}\n"
+ "\n"
+ "public static $classname$ valueOf(int value) {\n"
+ " switch (value) {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ printer->Indent();
+
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ printer->Print(
+ "case $number$: return $name$;\n",
+ "name", canonical_values_[i]->name(),
+ "number", SimpleItoa(canonical_values_[i]->number()));
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " default: return null;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n"
+ " internalGetValueMap() {\n"
+ " return internalValueMap;\n"
+ "}\n"
+ "private static final com.google.protobuf.Internal.EnumLiteMap<\n"
+ " $classname$> internalValueMap =\n"
+ " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n"
+ " public $classname$ findValueByNumber(int number) {\n"
+ " return $classname$.valueOf(number);\n"
+ " }\n"
+ " };\n"
+ "\n",
+ "classname", descriptor_->name());
+
+ printer->Print(
+ "private final int value;\n\n"
+ "private $classname$(int index, int value) {\n",
+ "classname", descriptor_->name());
+ printer->Print(
+ " this.value = value;\n"
+ "}\n");
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
+ printer->Outdent();
+ printer->Print("}\n\n");
+}
+
+bool EnumLiteGenerator::CanUseEnumValues() {
+ if (canonical_values_.size() != descriptor_->value_count()) {
+ return false;
+ }
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ if (descriptor_->value(i)->name() != canonical_values_[i]->name()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.h b/src/google/protobuf/compiler/java/java_enum_lite.h
index e69de29b..ee2f5f7a 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.h
+++ b/src/google/protobuf/compiler/java/java_enum_lite.h
@@ -0,0 +1,99 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
+
+#include <string>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+ namespace compiler {
+ namespace java {
+ class Context; // context.h
+ class ClassNameResolver; // name_resolver.h
+ }
+ }
+ namespace io {
+ class Printer; // printer.h
+ }
+}
+
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class EnumLiteGenerator {
+ public:
+ explicit EnumLiteGenerator(const EnumDescriptor* descriptor,
+ bool immutable_api,
+ Context* context);
+ ~EnumLiteGenerator();
+
+ void Generate(io::Printer* printer);
+
+ private:
+ const EnumDescriptor* descriptor_;
+
+ // The proto language allows multiple enum constants to have the same numeric
+ // value. Java, however, does not allow multiple enum constants to be
+ // considered equivalent. We treat the first defined constant for any
+ // given numeric value as "canonical" and the rest as aliases of that
+ // canonical value.
+ vector<const EnumValueDescriptor*> canonical_values_;
+
+ struct Alias {
+ const EnumValueDescriptor* value;
+ const EnumValueDescriptor* canonical_value;
+ };
+ vector<Alias> aliases_;
+
+ bool immutable_api_;
+
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+
+ bool CanUseEnumValues();
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator);
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index 3f0fa11f..c5434767 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum_field.h>
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index 00f3c601..0e24da24 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -44,6 +44,7 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 96d2545f..99ba6a18 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -332,6 +332,10 @@ inline bool PreserveUnknownFields(const Descriptor* descriptor) {
return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
}
+inline bool IsAnyMessage(const Descriptor* descriptor) {
+ return descriptor->full_name() == "google.protobuf.Any";
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 44b86cd7..3e035c89 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -314,6 +314,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" internalGetMutable$capitalized_name$().getMutableMap(),\n"
" $name$ValueConverter);\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\n");
if (SupportUnknownEnumValue(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -331,6 +339,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
"getMutable$capitalized_name$Value() {\n"
" return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+ " getMutable$capitalized_name$Value().putAll(values);\n"
+ " return this;\n"
+ "}\n");
}
} else {
WriteFieldDocComment(printer, descriptor_);
@@ -346,6 +362,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
"getMutable$capitalized_name$() {\n"
" return internalGetMutable$capitalized_name$().getMutableMap();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$type_parameters$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\n");
}
}
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index cd1698f0..4fe656d3 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -303,6 +303,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" copyOnWrite();\n"
" return instance.getMutable$capitalized_name$();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\n");
if (SupportUnknownEnumValue(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(
@@ -321,6 +329,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" copyOnWrite();\n"
" return instance.getMutable$capitalized_name$Value();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+ " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
+ " getMutable$capitalized_name$Value().putAll(values);\n"
+ " return this;\n"
+ "}\n");
}
} else {
WriteFieldDocComment(printer, descriptor_);
@@ -337,6 +353,14 @@ GenerateBuilderMembers(io::Printer* printer) const {
" copyOnWrite();\n"
" return instance.getMutable$capitalized_name$();\n"
"}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public Builder putAll$capitalized_name$(\n"
+ " java.util.Map<$type_parameters$> values) {\n"
+ " getMutable$capitalized_name$().putAll(values);\n"
+ " return this;\n"
+ "}\n");
}
}
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 09b0fd94..80d6e9ad 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -255,6 +255,18 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
field_generators_.get(descriptor_->field(i))
.GenerateInterfaceMembers(printer);
}
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "\n"
+ "public $classname$.$oneof_capitalized_name$Case "
+ "get$oneof_capitalized_name$Case();\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name,
+ "classname",
+ context_->GetNameResolver()->GetImmutableClassName(
+ descriptor_));
+ }
printer->Outdent();
printer->Print("}\n");
@@ -292,8 +304,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
" com.google.protobuf.GeneratedMessage implements\n"
" $extra_interfaces$\n"
" $classname$OrBuilder {\n");
-
- builder_type = "com.google.protobuf.GeneratedMessage.Builder";
+ builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
}
printer->Indent();
// Using builder_type, instead of Builder, prevents the Builder class from
@@ -435,6 +446,10 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"\n");
}
+ if (IsAnyMessage(descriptor_)) {
+ GenerateAnyMethods(printer);
+ }
+
// Fields
for (int i = 0; i < descriptor_->field_count(); i++) {
printer->Print("public static final int $constant_name$ = $number$;\n",
@@ -578,9 +593,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
printer->Print(
"}\n"
"\n"
- "private int memoizedSerializedSize = -1;\n"
"public int getSerializedSize() {\n"
- " int size = memoizedSerializedSize;\n"
+ " int size = memoizedSize;\n"
" if (size != -1) return size;\n"
"\n"
" size = 0;\n");
@@ -612,7 +626,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
printer->Outdent();
printer->Print(
- " memoizedSerializedSize = size;\n"
+ " memoizedSize = size;\n"
" return size;\n"
"}\n"
"\n");
@@ -948,22 +962,58 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
printer->Print("boolean result = true;\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
- const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
- bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
- if (check_has_bits) {
+ if (field->containing_oneof() == NULL) {
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field);
+ if (check_has_bits) {
+ printer->Print(
+ "result = result && (has$name$() == other.has$name$());\n"
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ printer->Indent();
+ }
+ field_generators_.get(field).GenerateEqualsCode(printer);
+ if (check_has_bits) {
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+ }
+ }
+ }
+
+ // Compare oneofs.
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "result = result && get$oneof_capitalized_name$Case().equals(\n"
+ " other.get$oneof_capitalized_name$Case());\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name);
+ printer->Print(
+ "if (!result) return false;\n"
+ "switch ($oneof_name$Case_) {\n",
+ "oneof_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->name);
+ printer->Indent();
+ for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(
- "result = result && (has$name$() == other.has$name$());\n"
- "if (has$name$()) {\n",
- "name", info->capitalized_name);
+ "case $field_number$:\n",
+ "field_number",
+ SimpleItoa(field->number()));
printer->Indent();
- }
- field_generators_.get(field).GenerateEqualsCode(printer);
- if (check_has_bits) {
+ field_generators_.get(field).GenerateEqualsCode(printer);
+ printer->Print("break;\n");
printer->Outdent();
- printer->Print(
- "}\n");
}
+ printer->Print(
+ "case 0:\n"
+ "default:\n");
+ printer->Outdent();
+ printer->Print("}\n");
}
+
if (PreserveUnknownFields(descriptor_)) {
// Always consider unknown fields for equality. This will sometimes return
// false for non-canonical ordering when running in LITE_RUNTIME but it's
@@ -1198,7 +1248,7 @@ GenerateParsingConstructor(io::Printer* printer) {
// ===================================================================
void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
printer->Print(
- "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
+ "private static final com.google.protobuf.Parser<$classname$> PARSER =\n"
" new com.google.protobuf.AbstractParser<$classname$>() {\n",
"classname", descriptor_->name());
printer->Indent();
@@ -1250,6 +1300,10 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
"\n");
printer->Print(
+ "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+ " return PARSER;\n"
+ "}\n"
+ "\n"
"@java.lang.Override\n"
"public com.google.protobuf.Parser<$classname$> getParserForType() {\n"
" return PARSER;\n"
@@ -1269,6 +1323,50 @@ void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) {
}
+void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) {
+ printer->Print(
+ "private static String getTypeUrl(\n"
+ " com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
+ " return \"type.googleapis.com/\" + descriptor.getFullName();\n"
+ "}\n"
+ "\n"
+ "public static <T extends com.google.protobuf.Message> Any pack(\n"
+ " T message) {\n"
+ " return Any.newBuilder()\n"
+ " .setTypeUrl(getTypeUrl(message.getDescriptorForType()))\n"
+ " .setValue(message.toByteString())\n"
+ " .build();\n"
+ "}\n"
+ "\n"
+ "public <T extends com.google.protobuf.Message> boolean is(\n"
+ " java.lang.Class<T> clazz) {\n"
+ " T defaultInstance =\n"
+ " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+ " return getTypeUrl().equals(\n"
+ " getTypeUrl(defaultInstance.getDescriptorForType()));\n"
+ "}\n"
+ "\n"
+ "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
+ "\n"
+ "public <T extends com.google.protobuf.Message> T unpack(\n"
+ " java.lang.Class<T> clazz)\n"
+ " throws com.google.protobuf.InvalidProtocolBufferException {\n"
+ " if (!is(clazz)) {\n"
+ " throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+ " \"Type of the Any messsage does not match the given class.\");\n"
+ " }\n"
+ " if (cachedUnpackValue != null) {\n"
+ " return (T) cachedUnpackValue;\n"
+ " }\n"
+ " T defaultInstance =\n"
+ " com.google.protobuf.Internal.getDefaultInstance(clazz);\n"
+ " T result = (T) defaultInstance.getParserForType()\n"
+ " .parseFrom(getValue());\n"
+ " cachedUnpackValue = result;\n"
+ " return result;\n"
+ "}\n");
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index c3c37765..be5bfb07 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -122,6 +122,7 @@ class ImmutableMessageGenerator : public MessageGenerator {
void GenerateEqualsAndHashCode(io::Printer* printer);
void GenerateParser(io::Printer* printer);
void GenerateParsingConstructor(io::Printer* printer);
+ void GenerateAnyMethods(io::Printer* printer);
Context* context_;
ClassNameResolver* name_resolver_;
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index b180b4a7..b5f8e626 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -452,11 +452,11 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -736,11 +736,12 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$oneof_name$_ =\n"
+ " input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -1232,11 +1233,11 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry));\n");
} else {
printer->Print(variables_,
- "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
+ "$name$_.add(input.readMessage($type$.parser(), extensionRegistry));\n");
}
}
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index 8332202c..356520ec 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -310,11 +310,11 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$name$_ = input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -521,11 +521,12 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n"
+ "$oneof_name$_ = input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry);\n");
} else {
printer->Print(variables_,
- "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n");
+ "$oneof_name$_ =\n"
+ " input.readMessage($type$.parser(), extensionRegistry);\n");
}
printer->Print(variables_,
@@ -885,11 +886,12 @@ GenerateParsingCode(io::Printer* printer) const {
if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
- "$name$_.add(input.readGroup($number$, $type$.PARSER,\n"
+ "$name$_.add(input.readGroup($number$, $type$.parser(),\n"
" extensionRegistry));\n");
} else {
printer->Print(variables_,
- "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n");
+ "$name$_.add(\n"
+ " input.readMessage($type$.parser(), extensionRegistry));\n");
}
}
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 3accee92..8b6c75b8 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -45,7 +45,7 @@
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
-#include <google/protobuf/compiler/java/java_enum.h>
+#include <google/protobuf/compiler/java/java_enum_lite.h>
#include <google/protobuf/compiler/java/java_extension.h>
#include <google/protobuf/compiler/java/java_generator_factory.h>
#include <google/protobuf/compiler/java/java_helpers.h>
@@ -143,6 +143,17 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
field_generators_.get(descriptor_->field(i))
.GenerateInterfaceMembers(printer);
}
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ printer->Print(
+ "\n"
+ "public $classname$.$oneof_capitalized_name$Case "
+ "get$oneof_capitalized_name$Case();\n",
+ "oneof_capitalized_name",
+ context_->GetOneofGeneratorInfo(
+ descriptor_->oneof_decl(i))->capitalized_name,
+ "classname",
+ context_->GetNameResolver()->GetImmutableClassName(descriptor_));
+ }
printer->Outdent();
printer->Print("}\n");
@@ -190,7 +201,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
// Nested types
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
- EnumGenerator(descriptor_->enum_type(i), true, context_)
+ EnumLiteGenerator(descriptor_->enum_type(i), true, context_)
.Generate(printer);
}
@@ -321,12 +332,12 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Print(
"protected final Object dynamicMethod(\n"
" com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
- " Object... args) {\n"
+ " Object arg0, Object arg1) {\n"
" switch (method) {\n"
" case PARSE_PARTIAL_FROM: {\n"
" return new $classname$("
- " (com.google.protobuf.CodedInputStream) args[0],\n"
- " (com.google.protobuf.ExtensionRegistryLite) args[1]);\n"
+ " (com.google.protobuf.CodedInputStream) arg0,\n"
+ " (com.google.protobuf.ExtensionRegistryLite) arg1);\n"
" }\n"
" case NEW_INSTANCE: {\n"
" return new $classname$(\n"
@@ -370,7 +381,25 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
printer->Outdent();
printer->Print(
- "}\n");
+ "}\n"
+ "case GET_DEFAULT_INSTANCE: {\n"
+ " return DEFAULT_INSTANCE;\n"
+ "}\n"
+ "case GET_PARSER: {\n"
+ // Generally one would use the lazy initialization holder pattern for
+ // manipulating static fields but that has exceptional cost on Android as
+ // it will generate an extra class for every message. Instead, use the
+ // double-check locking pattern which works just as well.
+ " if (PARSER == null) {"
+ " synchronized ($classname$.class) {\n"
+ " if (PARSER == null) {\n"
+ " PARSER = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ " return PARSER;\n"
+ "}\n",
+ "classname", name_resolver_->GetImmutableClassName(descriptor_));
printer->Outdent();
printer->Outdent();
@@ -413,18 +442,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
GenerateParser(printer);
- // LITE_RUNTIME uses this to implement the *ForType methods at the
- // GeneratedMessageLite level.
- printer->Print(
- "static {\n"
- " com.google.protobuf.GeneratedMessageLite.onLoad(\n"
- " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n"
- " .PrototypeHolder<$classname$, Builder>(\n"
- " DEFAULT_INSTANCE, PARSER));"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-
// Extensions must be declared after the DEFAULT_INSTANCE is initialized
// because the DEFAULT_INSTANCE is used by the extension to lazily retrieve
// the outer class's FileDescriptor.
@@ -554,54 +571,54 @@ GenerateParseFromMethods(io::Printer* printer) {
"public static $classname$ parseFrom(\n"
" com.google.protobuf.ByteString data)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data);\n"
+ " return parser().parseFrom(data);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.ByteString data,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data, extensionRegistry);\n"
+ " return parser().parseFrom(data, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(byte[] data)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data);\n"
+ " return parser().parseFrom(data);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" byte[] data,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws com.google.protobuf.InvalidProtocolBufferException {\n"
- " return PARSER.parseFrom(data, extensionRegistry);\n"
+ " return parser().parseFrom(data, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input);\n"
+ " return parser().parseFrom(input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input, extensionRegistry);\n"
+ " return parser().parseFrom(input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseDelimitedFrom(input);\n"
+ " return parser().parseDelimitedFrom(input);\n"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n"
+ " return parser().parseDelimitedFrom(input, extensionRegistry);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input);\n"
+ " return parser().parseFrom(input);\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return PARSER.parseFrom(input, extensionRegistry);\n"
+ " return parser().parseFrom(input, extensionRegistry);\n"
"}\n"
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
@@ -652,7 +669,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
"if (isInitialized == 1) return DEFAULT_INSTANCE;\n"
"if (isInitialized == 0) return null;\n"
"\n"
- "boolean shouldMemoize = ((Boolean) args[0]).booleanValue();\n");
+ "boolean shouldMemoize = ((Boolean) arg0).booleanValue();\n");
// Check that all required fields in this message are set.
// TODO(kenton): We can optimize this when we switch to putting all the
@@ -778,7 +795,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
.GenerateDynamicMethodMakeImmutableCode(printer);
}
printer->Print(
- "return null;");
+ "return null;\n");
}
// ===================================================================
@@ -786,7 +803,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable(
void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder(
io::Printer* printer) {
printer->Print(
- "return new Builder();");
+ "return new Builder();\n");
}
// ===================================================================
@@ -796,9 +813,8 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom(
printer->Print(
// Optimization: If other is the default instance, we know none of its
// fields are set so we can skip the merge.
- "Object arg = args[0];\n"
- "if (arg == $classname$.getDefaultInstance()) return this;\n"
- "$classname$ other = ($classname$) arg;\n",
+ "if (arg0 == $classname$.getDefaultInstance()) return this;\n"
+ "$classname$ other = ($classname$) arg0;\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -1151,9 +1167,11 @@ GenerateParsingConstructor(io::Printer* printer) {
// ===================================================================
void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) {
printer->Print(
- "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
- " new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
- "\n",
+ "private static volatile com.google.protobuf.Parser<$classname$> PARSER;\n"
+ "\n"
+ "public static com.google.protobuf.Parser<$classname$> parser() {\n"
+ " return DEFAULT_INSTANCE.getParserForType();\n"
+ "}\n",
"classname", descriptor_->name());
}
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 7bebe12a..178bbe19 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 217ff9b6..392333b8 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -35,6 +35,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
index 7baead15..11bfc12d 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -39,7 +39,6 @@
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_name_resolver.h>
#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 68e863cc..47e04659 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -36,6 +36,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
@@ -77,6 +78,10 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
" if (value == null) {\n"
" throw new NullPointerException();\n"
" }\n";
+ (*variables)["writeString"] =
+ "com.google.protobuf.GeneratedMessage.writeString";
+ (*variables)["computeStringSize"] =
+ "com.google.protobuf.GeneratedMessage.computeStringSize";
// TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
// by the proto compiler
@@ -433,7 +438,7 @@ void ImmutableStringFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " $writeString$(output, $number$, $name$_);\n"
"}\n");
}
@@ -441,8 +446,7 @@ void ImmutableStringFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " size += $computeStringSize$($number$, $name$_);\n"
"}\n");
}
@@ -689,7 +693,7 @@ void ImmutableStringOneofFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " $writeString$(output, $number$, $oneof_name$_);\n"
"}\n");
}
@@ -697,8 +701,7 @@ void ImmutableStringOneofFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
- " size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " size += $computeStringSize$($number$, $oneof_name$_);\n"
"}\n");
}
@@ -1007,12 +1010,12 @@ GenerateSerializationCode(io::Printer* printer) const {
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
"}\n"
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ " writeStringNoTag(output, $name$_.getRaw(i));\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeBytes($number$, $name$_.getByteString(i));\n"
+ " $writeString$(output, $number$, $name$_.getRaw(i));\n"
"}\n");
}
}
@@ -1026,8 +1029,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " dataSize += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+ " dataSize += computeStringSizeNoTag($name$_.getRaw(i));\n"
"}\n");
printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index 51bb245c..032715b7 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -36,6 +36,7 @@
#include <map>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_doc_comment.h>
@@ -64,7 +65,8 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
map<string, string>* variables) {
SetCommonFieldVariables(descriptor, info, variables);
- (*variables)["empty_list"] = "emptyLazyStringArrayList()";
+ (*variables)["empty_list"] =
+ "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
(*variables)["default_init"] =
@@ -101,7 +103,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["clear_has_field_bit_message"] = "";
(*variables)["is_field_present_message"] =
- "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()";
+ "!get" + (*variables)["capitalized_name"] + ".isEmpty()";
}
// For repeated builders, the underlying list tracks mutability state.
@@ -144,8 +146,9 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
return 0;
}
-// A note about how strings are handled. This code used to just store a String
-// in the Message. This had two issues:
+// A note about how strings are handled. In the SPEED and CODE_SIZE runtimes,
+// strings are not stored as java.lang.String in the Message because of two
+// issues:
//
// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded
// strings, but rather fields that were raw bytes incorrectly marked
@@ -160,22 +163,14 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const {
// it many cases, the field is never even read by the application code. This
// avoids unnecessary conversions in the common use cases.
//
-// So now, the field for String is maintained as an Object reference which can
-// either store a String or a ByteString. The code uses an instanceof check
-// to see which one it has and converts to the other one if needed. It remembers
-// the last value requested (in a thread safe manner) as this is most likely
-// the one needed next. The thread safety is such that if two threads both
-// convert the field because the changes made by each thread were not visible to
-// the other, they may cause a conversion to happen more times than would
-// otherwise be necessary. This was deemed better than adding synchronization
-// overhead. It will not cause any corruption issues or affect the behavior of
-// the API. The instanceof check is also highly optimized in the JVM and we
-// decided it was better to reduce the memory overhead by not having two
-// separate fields but rather use dynamic type checking.
-//
-// For single fields, the logic for this is done inside the generated code. For
-// repeated fields, the logic is done in LazyStringArrayList and
-// UnmodifiableLazyStringList.
+// In the LITE_RUNTIME, we store strings as java.lang.String because we assume
+// that the users of this runtime are not subject to proto1 constraints and are
+// running code on devices that are user facing. That is, the developers are
+// properly incentivized to only fetch the data they need to read and wish to
+// reduce the number of allocations incurred when running on a user's device.
+
+// TODO(dweis): Consider dropping all of the *Bytes() methods. They really
+// shouldn't be necessary or used on devices.
void ImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
if (SupportFieldPresence(descriptor_->file())) {
@@ -195,7 +190,7 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void ImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.lang.Object $name$_;\n");
+ "private java.lang.String $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
if (SupportFieldPresence(descriptor_->file())) {
@@ -209,40 +204,13 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
- " java.lang.Object ref = $name$_;\n"
- " if (ref instanceof java.lang.String) {\n"
- " return (java.lang.String) ref;\n"
- " } else {\n"
- " com.google.protobuf.ByteString bs = \n"
- " (com.google.protobuf.ByteString) ref;\n"
- " java.lang.String s = bs.toStringUtf8();\n");
- if (CheckUtf8(descriptor_)) {
- printer->Print(variables_,
- " $name$_ = s;\n");
- } else {
- printer->Print(variables_,
- " if (bs.isValidUtf8()) {\n"
- " $name$_ = s;\n"
- " }\n");
- }
- printer->Print(variables_,
- " return s;\n"
- " }\n"
+ " return $name$_;\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public com.google.protobuf.ByteString\n"
" get$capitalized_name$Bytes() {\n"
- " java.lang.Object ref = $name$_;\n"
- " if (ref instanceof java.lang.String) {\n"
- " com.google.protobuf.ByteString b = \n"
- " com.google.protobuf.ByteString.copyFromUtf8(\n"
- " (java.lang.String) ref);\n"
- " $name$_ = b;\n"
- " return b;\n"
- " } else {\n"
- " return (com.google.protobuf.ByteString) ref;\n"
- " }\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -273,7 +241,7 @@ GenerateMembers(io::Printer* printer) const {
}
printer->Print(variables_,
" $set_has_field_bit_message$\n"
- " $name$_ = value;\n"
+ " $name$_ = value.toStringUtf8();\n"
"}\n");
}
@@ -368,7 +336,7 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_has_field_bit_message$\n"
"$name$_ = s;\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
+ } else {
// Lite runtime should attempt to reduce allocations by attempting to
// construct the string directly from the input stream buffer. This avoids
// spurious intermediary ByteString allocations, cutting overall allocations
@@ -377,11 +345,6 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readString();\n"
"$set_has_field_bit_message$\n"
"$name$_ = s;\n");
- } else {
- printer->Print(variables_,
- "com.google.protobuf.ByteString bs = input.readBytes();\n"
- "$set_has_field_bit_message$\n"
- "$name$_ = bs;\n");
}
}
@@ -392,18 +355,24 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void ImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by serializing the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " output.writeString($number$, get$capitalized_name$());\n"
"}\n");
}
void ImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by computing on the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " .computeStringSize($number$, get$capitalized_name$());\n"
"}\n");
}
@@ -458,51 +427,22 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.lang.String get$capitalized_name$() {\n"
- " java.lang.Object ref $default_init$;\n"
+ " java.lang.String ref $default_init$;\n"
" if ($has_oneof_case_message$) {\n"
- " ref = $oneof_name$_;\n"
- " }\n"
- " if (ref instanceof java.lang.String) {\n"
- " return (java.lang.String) ref;\n"
- " } else {\n"
- " com.google.protobuf.ByteString bs = \n"
- " (com.google.protobuf.ByteString) ref;\n"
- " java.lang.String s = bs.toStringUtf8();\n");
- if (CheckUtf8(descriptor_)) {
- printer->Print(variables_,
- " if ($has_oneof_case_message$) {\n"
- " $oneof_name$_ = s;\n"
- " }\n");
- } else {
- printer->Print(variables_,
- " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n"
- " $oneof_name$_ = s;\n"
- " }\n");
- }
- printer->Print(variables_,
- " return s;\n"
+ " ref = (java.lang.String) $oneof_name$_;\n"
" }\n"
+ " return ref;\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public com.google.protobuf.ByteString\n"
" get$capitalized_name$Bytes() {\n"
- " java.lang.Object ref $default_init$;\n"
+ " java.lang.String ref $default_init$;\n"
" if ($has_oneof_case_message$) {\n"
- " ref = $oneof_name$_;\n"
- " }\n"
- " if (ref instanceof java.lang.String) {\n"
- " com.google.protobuf.ByteString b = \n"
- " com.google.protobuf.ByteString.copyFromUtf8(\n"
- " (java.lang.String) ref);\n"
- " if ($has_oneof_case_message$) {\n"
- " $oneof_name$_ = b;\n"
- " }\n"
- " return b;\n"
- " } else {\n"
- " return (com.google.protobuf.ByteString) ref;\n"
+ " ref = (java.lang.String) $oneof_name$_;\n"
" }\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -533,7 +473,7 @@ GenerateMembers(io::Printer* printer) const {
}
printer->Print(variables_,
" $set_oneof_case_message$;\n"
- " $oneof_name$_ = value;\n"
+ " $oneof_name$_ = value.toStringUtf8();\n"
"}\n");
}
@@ -603,7 +543,7 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_oneof_case_message$;\n"
"$oneof_name$_ = s;\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
+ } else {
// Lite runtime should attempt to reduce allocations by attempting to
// construct the string directly from the input stream buffer. This avoids
// spurious intermediary ByteString allocations, cutting overall allocations
@@ -612,28 +552,29 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readString();\n"
"$set_oneof_case_message$;\n"
"$oneof_name$_ = s;\n");
- } else {
- printer->Print(variables_,
- "com.google.protobuf.ByteString bs = input.readBytes();\n"
- "$set_oneof_case_message$;\n"
- "$oneof_name$_ = bs;\n");
}
}
void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializationCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by serializing the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
- " output.writeBytes($number$, get$capitalized_name$Bytes());\n"
+ " output.writeString($number$, get$capitalized_name$());\n"
"}\n");
}
void ImmutableStringOneofFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by computing on the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSize($number$, get$capitalized_name$Bytes());\n"
+ " .computeStringSize($number$, get$capitalized_name$());\n"
"}\n");
}
@@ -667,7 +608,7 @@ void RepeatedImmutableStringFieldLiteGenerator::
GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$com.google.protobuf.ProtocolStringList\n"
+ "$deprecation$java.util.List<String>\n"
" get$capitalized_name$List();\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -685,12 +626,11 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void RepeatedImmutableStringFieldLiteGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private com.google.protobuf.LazyStringArrayList $name$_;\n");
+ "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$public com.google.protobuf.ProtocolStringList\n"
- " get$capitalized_name$List() {\n"
+ "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
" return $name$_;\n" // note: unmodifiable list
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -707,7 +647,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public com.google.protobuf.ByteString\n"
" get$capitalized_name$Bytes(int index) {\n"
- " return $name$_.getByteString(index);\n"
+ " return com.google.protobuf.ByteString.copyFromUtf8(\n"
+ " $name$_.get(index));\n"
"}\n");
if (descriptor_->options().packed() &&
@@ -719,7 +660,8 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$is_mutable$) {\n"
- " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n"
+ " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n"
+ " $name$_);\n"
" }\n"
"}\n");
@@ -764,7 +706,7 @@ GenerateMembers(io::Printer* printer) const {
}
printer->Print(variables_,
" ensure$capitalized_name$IsMutable();\n"
- " $name$_.add(value);\n"
+ " $name$_.add(value.toStringUtf8());\n"
"}\n");
}
@@ -772,10 +714,10 @@ void RepeatedImmutableStringFieldLiteGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
- "$deprecation$public com.google.protobuf.ProtocolStringList\n"
+ "$deprecation$public java.util.List<String>\n"
" get$capitalized_name$List() {\n"
- " return ((com.google.protobuf.LazyStringList)\n"
- " instance.get$capitalized_name$List()).getUnmodifiableView();\n"
+ " return java.util.Collections.unmodifiableList(\n"
+ " instance.get$capitalized_name$List());\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -875,20 +817,17 @@ GenerateParsingCode(io::Printer* printer) const {
if (CheckUtf8(descriptor_)) {
printer->Print(variables_,
"String s = input.readStringRequireUtf8();\n");
- } else if (!HasDescriptorMethods(descriptor_->file())) {
+ } else {
// Lite runtime should attempt to reduce allocations by attempting to
// construct the string directly from the input stream buffer. This avoids
// spurious intermediary ByteString allocations, cutting overall allocations
// in half.
printer->Print(variables_,
"String s = input.readString();\n");
- } else {
- printer->Print(variables_,
- "com.google.protobuf.ByteString bs = input.readBytes();\n");
}
printer->Print(variables_,
"if (!$is_mutable$) {\n"
- " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
"}\n");
if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
printer->Print(variables_,
@@ -905,7 +844,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const {
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
"if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n"
- " $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
+ " $name$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
"}\n"
"while (input.getBytesUntilLimit() > 0) {\n");
if (CheckUtf8(descriptor_)) {
@@ -932,6 +871,9 @@ GenerateParsingDoneCode(io::Printer* printer) const {
void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializationCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by serializing the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
if (descriptor_->options().packed()) {
printer->Print(variables_,
"if (get$capitalized_name$List().size() > 0) {\n"
@@ -939,18 +881,21 @@ GenerateSerializationCode(io::Printer* printer) const {
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
"}\n"
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.write$capitalized_type$NoTag($name$_.get(i));\n"
+ " output.writeStringNoTag($name$_.get(i));\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeBytes($number$, $name$_.getByteString(i));\n"
+ " output.writeString($number$, $name$_.get(i));\n"
"}\n");
}
}
void RepeatedImmutableStringFieldLiteGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
+ // Lite runtime should reduce allocations by computing on the string directly.
+ // This avoids spurious intermediary ByteString allocations, cutting overall
+ // allocations in half.
printer->Print(variables_,
"{\n"
" int dataSize = 0;\n");
@@ -959,7 +904,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
" dataSize += com.google.protobuf.CodedOutputStream\n"
- " .computeBytesSizeNoTag($name$_.getByteString(i));\n"
+ " .computeStringSizeNoTag($name$_.get(i));\n"
"}\n");
printer->Print(
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index a2eeee2d..895ff34a 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -44,6 +44,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/wire_format.h>
#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/map_util.h>
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index 16012e96..007b001c 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -323,7 +323,7 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& service_location,
const FileDescriptorProto* containing_file);
- // Parse one statement within a message, enum, or service block, inclunding
+ // Parse one statement within a message, enum, or service block, including
// final semicolon.
bool ParseMessageStatement(DescriptorProto* message,
const LocationRecorder& message_location,
@@ -364,7 +364,7 @@ class LIBPROTOBUF_EXPORT Parser {
const LocationRecorder& extensions_location,
const FileDescriptorProto* containing_file);
- // Parse an "reserved" declaration.
+ // Parse a "reserved" declaration.
bool ParseReserved(DescriptorProto* message,
const LocationRecorder& message_location);
bool ParseReservedNames(DescriptorProto* message,
@@ -415,7 +415,7 @@ class LIBPROTOBUF_EXPORT Parser {
Message* mutable_options);
// Parse "required", "optional", or "repeated" and fill in "label"
- // with the value. Returns true if shuch a label is consumed.
+ // with the value. Returns true if such a label is consumed.
bool ParseLabel(FieldDescriptorProto::Label* label,
const FileDescriptorProto* containing_file);
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index cdcaffde..2bebf1f3 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -48,6 +48,7 @@
#include <unistd.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/plugin.pb.h>
#include <google/protobuf/compiler/code_generator.h>
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index e7890fae..994bc392 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -629,28 +629,28 @@ int CodeGeneratorRequest::proto_file_size() const {
void CodeGeneratorRequest::clear_proto_file() {
proto_file_.Clear();
}
- const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+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) {
+::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() {
+::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 >*
+::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_;
}
+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_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -1535,28 +1535,28 @@ int CodeGeneratorResponse::file_size() const {
void CodeGeneratorResponse::clear_file() {
file_.Clear();
}
- const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
CodeGeneratorResponse::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
return &file_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 6fcaea2e..ab79bdae 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -144,10 +144,10 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_proto_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ proto_file() const;
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
private:
@@ -378,10 +378,10 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
mutable_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+ file() const;
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
private:
@@ -534,16 +534,16 @@ inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return proto_file_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-CodeGeneratorRequest::proto_file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
- return proto_file_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
CodeGeneratorRequest::mutable_proto_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
return &proto_file_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file)
+ return proto_file_;
+}
// -------------------------------------------------------------------
@@ -784,16 +784,16 @@ inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorRe
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file)
return file_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
-CodeGeneratorResponse::file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
- return file_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
CodeGeneratorResponse::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file)
return &file_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file)
+ return file_;
+}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 7b3b5fa3..4d500f90 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -58,6 +58,7 @@
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/io/printer.h>
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 2ddac601..aa0f5fce 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -38,6 +38,7 @@
#include <string>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index a3cff1f8..85429924 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -42,6 +42,7 @@
#include <signal.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/message.h>
#include <google/protobuf/stubs/substitute.h>
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 2855c377..5256b83c 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -53,6 +53,8 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/strutil.h>
@@ -1092,6 +1094,7 @@ const DescriptorPool* DescriptorPool::generated_pool() {
return generated_pool_;
}
+
DescriptorPool* DescriptorPool::internal_generated_pool() {
InitGeneratedPoolOnce();
return generated_pool_;
@@ -3699,6 +3702,14 @@ static bool ExistingFileMatchesProto(const FileDescriptor* existing_file,
const FileDescriptorProto& proto) {
FileDescriptorProto existing_proto;
existing_file->CopyTo(&existing_proto);
+ // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
+ // syntax="proto2".
+ if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
+ proto.has_syntax()) {
+ existing_proto.set_syntax(
+ existing_file->SyntaxName(existing_file->syntax()));
+ }
+
return existing_proto.SerializeAsString() == proto.SerializeAsString();
}
@@ -4649,7 +4660,7 @@ void DescriptorBuilder::CrossLinkMessage(
// safe.
if (oneof_decl->field_count() > 0 &&
message->field(i - 1)->containing_oneof() != oneof_decl) {
- AddWarning(
+ AddError(
message->full_name() + "." + message->field(i - 1)->name(),
proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER,
strings::Substitute(
@@ -5088,8 +5099,7 @@ void DescriptorBuilder::ValidateProto3Field(
field->containing_type()->full_name() +
"\" which is a proto3 message type.");
}
- bool allow_groups = false;
- if (field->type() == FieldDescriptor::TYPE_GROUP && !allow_groups) {
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
AddError(field->full_name(), proto,
DescriptorPool::ErrorCollector::TYPE,
"Groups are not supported in proto3 syntax.");
@@ -5307,6 +5317,14 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
// are added.
}
+ if (value->type() == FieldDescriptor::TYPE_ENUM) {
+ if (value->enum_type()->value(0)->number() != 0) {
+ AddError(
+ field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+ "Enum value in map must define 0 as the first value.");
+ }
+ }
+
return true;
}
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index ca87d634..2ab316a5 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -58,6 +58,7 @@
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
#ifdef TYPE_BOOL
@@ -860,7 +861,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor {
friend class FieldDescriptor;
friend class EnumValueDescriptor;
friend class FileDescriptor;
- friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
+ friend class internal::GeneratedMessageReflection;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
};
@@ -1332,6 +1333,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool {
// this pool. Do not add your own descriptors to this pool.
static const DescriptorPool* generated_pool();
+
// Find a FileDescriptor in the pool by file name. Returns NULL if not
// found.
const FileDescriptor* FindFileByName(const string& name) const;
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 5e7eeaa7..6f9905aa 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -755,9 +755,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"tion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004s"
"pan\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022"
"\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_de"
- "tached_comments\030\006 \003(\tB[\n\023com.google.prot"
+ "tached_comments\030\006 \003(\tB;\n\023com.google.prot"
"obufB\020DescriptorProtosH\001Z\ndescriptor\242\002\003G"
- "PB\252\002\032Google.Protobuf.Reflection\260\002\001", 4994);
+ "PB", 4962);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
@@ -1066,28 +1066,28 @@ int FileDescriptorSet::file_size() const {
void FileDescriptorSet::clear_file() {
file_.Clear();
}
- const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
FileDescriptorSet::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
return &file_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+ return file_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -2091,28 +2091,28 @@ int FileDescriptorProto::message_type_size() const {
void FileDescriptorProto::clear_message_type() {
message_type_.Clear();
}
- const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
FileDescriptorProto::mutable_message_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
return &message_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
int FileDescriptorProto::enum_type_size() const {
@@ -2121,28 +2121,28 @@ int FileDescriptorProto::enum_type_size() const {
void FileDescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
- const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
FileDescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
return &enum_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
int FileDescriptorProto::service_size() const {
@@ -2151,28 +2151,28 @@ int FileDescriptorProto::service_size() const {
void FileDescriptorProto::clear_service() {
service_.Clear();
}
- const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
FileDescriptorProto::mutable_service() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
return &service_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+ return service_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
int FileDescriptorProto::extension_size() const {
@@ -2181,28 +2181,28 @@ int FileDescriptorProto::extension_size() const {
void FileDescriptorProto::clear_extension() {
extension_.Clear();
}
- const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
FileDescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
return &extension_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+ return extension_;
+}
// optional .google.protobuf.FileOptions options = 8;
bool FileDescriptorProto::has_options() const {
@@ -2218,11 +2218,11 @@ void FileDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+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() {
+::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::FileOptions;
@@ -2230,13 +2230,13 @@ void FileDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options)
return options_;
}
- ::google::protobuf::FileOptions* FileDescriptorProto::release_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) {
+void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -2261,11 +2261,11 @@ 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 {
+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() {
+::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;
@@ -2273,13 +2273,13 @@ void FileDescriptorProto::clear_source_code_info() {
// @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info)
return source_code_info_;
}
- ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_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) {
+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) {
@@ -3720,28 +3720,28 @@ int DescriptorProto::field_size() const {
void DescriptorProto::clear_field() {
field_.Clear();
}
- const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_field() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
return &field_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+ return field_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
int DescriptorProto::extension_size() const {
@@ -3750,28 +3750,28 @@ int DescriptorProto::extension_size() const {
void DescriptorProto::clear_extension() {
extension_.Clear();
}
- const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
return &extension_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+ return extension_;
+}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
int DescriptorProto::nested_type_size() const {
@@ -3780,28 +3780,28 @@ int DescriptorProto::nested_type_size() const {
void DescriptorProto::clear_nested_type() {
nested_type_.Clear();
}
- const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
DescriptorProto::mutable_nested_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
return &nested_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
int DescriptorProto::enum_type_size() const {
@@ -3810,28 +3810,28 @@ int DescriptorProto::enum_type_size() const {
void DescriptorProto::clear_enum_type() {
enum_type_.Clear();
}
- const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
DescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
return &enum_type_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
int DescriptorProto::extension_range_size() const {
@@ -3840,28 +3840,28 @@ int DescriptorProto::extension_range_size() const {
void DescriptorProto::clear_extension_range() {
extension_range_.Clear();
}
- const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const {
+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) {
+::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() {
+::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 >*
+::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_;
}
+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_;
+}
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
int DescriptorProto::oneof_decl_size() const {
@@ -3870,28 +3870,28 @@ int DescriptorProto::oneof_decl_size() const {
void DescriptorProto::clear_oneof_decl() {
oneof_decl_.Clear();
}
- const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
DescriptorProto::mutable_oneof_decl() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
return &oneof_decl_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_;
+}
// optional .google.protobuf.MessageOptions options = 7;
bool DescriptorProto::has_options() const {
@@ -3907,11 +3907,11 @@ void DescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+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() {
+::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::MessageOptions;
@@ -3919,13 +3919,13 @@ void DescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options)
return options_;
}
- ::google::protobuf::MessageOptions* DescriptorProto::release_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) {
+void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -3943,28 +3943,28 @@ int DescriptorProto::reserved_range_size() const {
void DescriptorProto::clear_reserved_range() {
reserved_range_.Clear();
}
- const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
+const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Get(index);
}
- ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
+::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Mutable(index);
}
- ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
+::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Add();
}
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
-DescriptorProto::reserved_range() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
- return reserved_range_;
-}
- ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
DescriptorProto::mutable_reserved_range() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
return &reserved_range_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
// repeated string reserved_name = 10;
int DescriptorProto::reserved_name_size() const {
@@ -5062,11 +5062,11 @@ void FieldDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+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() {
+::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::FieldOptions;
@@ -5074,13 +5074,13 @@ void FieldDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options)
return options_;
}
- ::google::protobuf::FieldOptions* FieldDescriptorProto::release_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) {
+void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -5804,28 +5804,28 @@ int EnumDescriptorProto::value_size() const {
void EnumDescriptorProto::clear_value() {
value_.Clear();
}
- const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
EnumDescriptorProto::mutable_value() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
return &value_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+ return value_;
+}
// optional .google.protobuf.EnumOptions options = 3;
bool EnumDescriptorProto::has_options() const {
@@ -5841,11 +5841,11 @@ void EnumDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+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() {
+::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::EnumOptions;
@@ -5853,13 +5853,13 @@ void EnumDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options)
return options_;
}
- ::google::protobuf::EnumOptions* EnumDescriptorProto::release_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) {
+void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -6304,11 +6304,11 @@ void EnumValueDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+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() {
+::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::EnumValueOptions;
@@ -6316,13 +6316,13 @@ void EnumValueDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options)
return options_;
}
- ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_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) {
+void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -6740,28 +6740,28 @@ int ServiceDescriptorProto::method_size() const {
void ServiceDescriptorProto::clear_method() {
method_.Clear();
}
- const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
ServiceDescriptorProto::mutable_method() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
return &method_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+ return method_;
+}
// optional .google.protobuf.ServiceOptions options = 3;
bool ServiceDescriptorProto::has_options() const {
@@ -6777,11 +6777,11 @@ void ServiceDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+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() {
+::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::ServiceOptions;
@@ -6789,13 +6789,13 @@ void ServiceDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options)
return options_;
}
- ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_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) {
+void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -7480,11 +7480,11 @@ void MethodDescriptorProto::clear_options() {
if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear();
clear_has_options();
}
- const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+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() {
+::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
set_has_options();
if (options_ == NULL) {
options_ = new ::google::protobuf::MethodOptions;
@@ -7492,13 +7492,13 @@ void MethodDescriptorProto::clear_options() {
// @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options)
return options_;
}
- ::google::protobuf::MethodOptions* MethodDescriptorProto::release_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) {
+void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) {
delete options_;
options_ = options;
if (options) {
@@ -9025,28 +9025,28 @@ int FileOptions::uninterpreted_option_size() const {
void FileOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FileOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -9568,28 +9568,28 @@ int MessageOptions::uninterpreted_option_size() const {
void MessageOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MessageOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -10298,28 +10298,28 @@ int FieldOptions::uninterpreted_option_size() const {
void FieldOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FieldOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -10721,28 +10721,28 @@ int EnumOptions::uninterpreted_option_size() const {
void EnumOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -11070,28 +11070,28 @@ int EnumValueOptions::uninterpreted_option_size() const {
void EnumValueOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumValueOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -11419,28 +11419,28 @@ int ServiceOptions::uninterpreted_option_size() const {
void ServiceOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
ServiceOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -11768,28 +11768,28 @@ int MethodOptions::uninterpreted_option_size() const {
void MethodOptions::clear_uninterpreted_option() {
uninterpreted_option_.Clear();
}
- const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MethodOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
@@ -12710,28 +12710,28 @@ int UninterpretedOption::name_size() const {
void UninterpretedOption::clear_name() {
name_.Clear();
}
- const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
UninterpretedOption::mutable_name() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
return &name_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+ return name_;
+}
// optional string identifier_value = 3;
bool UninterpretedOption::has_identifier_value() const {
@@ -13916,28 +13916,28 @@ int SourceCodeInfo::location_size() const {
void SourceCodeInfo::clear_location() {
location_.Clear();
}
- const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const {
+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) {
+::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() {
+::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 >*
+::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
SourceCodeInfo::mutable_location() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
return &location_;
}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+ return location_;
+}
#endif // PROTOBUF_INLINE_NOT_IN_HEADERS
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 2aa076ae..931ff02d 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -38,28 +38,28 @@ void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(
void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto();
-class FileDescriptorSet;
-class FileDescriptorProto;
class DescriptorProto;
class DescriptorProto_ExtensionRange;
class DescriptorProto_ReservedRange;
-class FieldDescriptorProto;
-class OneofDescriptorProto;
class EnumDescriptorProto;
+class EnumOptions;
class EnumValueDescriptorProto;
-class ServiceDescriptorProto;
-class MethodDescriptorProto;
+class EnumValueOptions;
+class FieldDescriptorProto;
+class FieldOptions;
+class FileDescriptorProto;
+class FileDescriptorSet;
class FileOptions;
class MessageOptions;
-class FieldOptions;
-class EnumOptions;
-class EnumValueOptions;
-class ServiceOptions;
+class MethodDescriptorProto;
class MethodOptions;
-class UninterpretedOption;
-class UninterpretedOption_NamePart;
+class OneofDescriptorProto;
+class ServiceDescriptorProto;
+class ServiceOptions;
class SourceCodeInfo;
class SourceCodeInfo_Location;
+class UninterpretedOption;
+class UninterpretedOption_NamePart;
enum FieldDescriptorProto_Type {
FieldDescriptorProto_Type_TYPE_DOUBLE = 1,
@@ -249,10 +249,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
mutable_file();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+ file() const;
// @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet)
private:
@@ -405,10 +405,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_message_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ message_type() const;
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
int enum_type_size() const;
@@ -417,10 +417,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
int service_size() const;
@@ -429,10 +429,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
mutable_service();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+ service() const;
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
int extension_size() const;
@@ -441,10 +441,10 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
// optional .google.protobuf.FileOptions options = 8;
bool has_options() const;
@@ -797,10 +797,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_field();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ field() const;
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
int extension_size() const;
@@ -809,10 +809,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
mutable_extension();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+ extension() const;
// repeated .google.protobuf.DescriptorProto nested_type = 3;
int nested_type_size() const;
@@ -821,10 +821,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
mutable_nested_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+ nested_type() const;
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
int enum_type_size() const;
@@ -833,10 +833,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
mutable_enum_type();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+ enum_type() const;
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
int extension_range_size() const;
@@ -845,10 +845,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
mutable_extension_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+ extension_range() const;
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
int oneof_decl_size() const;
@@ -857,10 +857,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
mutable_oneof_decl();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+ oneof_decl() const;
// optional .google.protobuf.MessageOptions options = 7;
bool has_options() const;
@@ -878,10 +878,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message {
const ::google::protobuf::DescriptorProto_ReservedRange& reserved_range(int index) const;
::google::protobuf::DescriptorProto_ReservedRange* mutable_reserved_range(int index);
::google::protobuf::DescriptorProto_ReservedRange* add_reserved_range();
- const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
- reserved_range() const;
::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
mutable_reserved_range();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+ reserved_range() const;
// repeated string reserved_name = 10;
int reserved_name_size() const;
@@ -1361,10 +1361,10 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
mutable_value();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+ value() const;
// optional .google.protobuf.EnumOptions options = 3;
bool has_options() const;
@@ -1596,10 +1596,10 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
mutable_method();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ method() const;
// optional .google.protobuf.ServiceOptions options = 3;
bool has_options() const;
@@ -2014,10 +2014,10 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.FileOptions)
@@ -2182,10 +2182,10 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions)
@@ -2381,10 +2381,10 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions)
@@ -2508,10 +2508,10 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions)
@@ -2616,10 +2616,10 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions)
@@ -2721,10 +2721,10 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions)
@@ -2826,10 +2826,10 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
mutable_uninterpreted_option();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ uninterpreted_option() const;
GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions)
// @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions)
@@ -3033,10 +3033,10 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
mutable_name();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+ name() const;
// optional string identifier_value = 3;
bool has_identifier_value() const;
@@ -3356,10 +3356,10 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message {
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;
::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
mutable_location();
+ const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+ location() const;
// @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo)
private:
@@ -3402,16 +3402,16 @@ inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() {
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file)
return file_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
-FileDescriptorSet::file() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
- return file_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
FileDescriptorSet::mutable_file() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file)
return &file_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+FileDescriptorSet::file() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file)
+ return file_;
+}
// -------------------------------------------------------------------
@@ -3656,16 +3656,16 @@ inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_typ
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type)
return message_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-FileDescriptorProto::message_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
- return message_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
FileDescriptorProto::mutable_message_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type)
return &message_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+FileDescriptorProto::message_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type)
+ return message_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
inline int FileDescriptorProto::enum_type_size() const {
@@ -3686,16 +3686,16 @@ inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_ty
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type)
return enum_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-FileDescriptorProto::enum_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
- return enum_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
FileDescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type)
return &enum_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+FileDescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.ServiceDescriptorProto service = 6;
inline int FileDescriptorProto::service_size() const {
@@ -3716,16 +3716,16 @@ inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_serv
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service)
return service_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
-FileDescriptorProto::service() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
- return service_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >*
FileDescriptorProto::mutable_service() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service)
return &service_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >&
+FileDescriptorProto::service() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service)
+ return service_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 7;
inline int FileDescriptorProto::extension_size() const {
@@ -3746,16 +3746,16 @@ inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extens
// @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension)
return extension_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-FileDescriptorProto::extension() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
- return extension_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
FileDescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension)
return &extension_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+FileDescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension)
+ return extension_;
+}
// optional .google.protobuf.FileOptions options = 8;
inline bool FileDescriptorProto::has_options() const {
@@ -4076,16 +4076,16 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field)
return field_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::field() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
- return field_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_field() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field)
return &field_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::field() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field)
+ return field_;
+}
// repeated .google.protobuf.FieldDescriptorProto extension = 6;
inline int DescriptorProto::extension_size() const {
@@ -4106,16 +4106,16 @@ inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension(
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension)
return extension_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
-DescriptorProto::extension() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
- return extension_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >*
DescriptorProto::mutable_extension() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension)
return &extension_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >&
+DescriptorProto::extension() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension)
+ return extension_;
+}
// repeated .google.protobuf.DescriptorProto nested_type = 3;
inline int DescriptorProto::nested_type_size() const {
@@ -4136,16 +4136,16 @@ inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() {
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type)
return nested_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
-DescriptorProto::nested_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
- return nested_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >*
DescriptorProto::mutable_nested_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type)
return &nested_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >&
+DescriptorProto::nested_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type)
+ return nested_type_;
+}
// repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
inline int DescriptorProto::enum_type_size() const {
@@ -4166,16 +4166,16 @@ inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type()
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type)
return enum_type_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
-DescriptorProto::enum_type() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
- return enum_type_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >*
DescriptorProto::mutable_enum_type() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type)
return &enum_type_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >&
+DescriptorProto::enum_type() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type)
+ return enum_type_;
+}
// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
inline int DescriptorProto::extension_range_size() const {
@@ -4196,16 +4196,16 @@ inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range)
return extension_range_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
-DescriptorProto::extension_range() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
- return extension_range_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >*
DescriptorProto::mutable_extension_range() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range)
return &extension_range_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >&
+DescriptorProto::extension_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range)
+ return extension_range_;
+}
// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
inline int DescriptorProto::oneof_decl_size() const {
@@ -4226,16 +4226,16 @@ inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl)
return oneof_decl_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
-DescriptorProto::oneof_decl() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
- return oneof_decl_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >*
DescriptorProto::mutable_oneof_decl() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl)
return &oneof_decl_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >&
+DescriptorProto::oneof_decl() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl)
+ return oneof_decl_;
+}
// optional .google.protobuf.MessageOptions options = 7;
inline bool DescriptorProto::has_options() const {
@@ -4299,16 +4299,16 @@ inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_r
// @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range)
return reserved_range_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
-DescriptorProto::reserved_range() const {
- // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
- return reserved_range_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >*
DescriptorProto::mutable_reserved_range() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range)
return &reserved_range_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >&
+DescriptorProto::reserved_range() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range)
+ return reserved_range_;
+}
// repeated string reserved_name = 10;
inline int DescriptorProto::reserved_name_size() const {
@@ -4854,16 +4854,16 @@ inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_va
// @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value)
return value_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
-EnumDescriptorProto::value() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
- return value_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >*
EnumDescriptorProto::mutable_value() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value)
return &value_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >&
+EnumDescriptorProto::value() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value)
+ return value_;
+}
// optional .google.protobuf.EnumOptions options = 3;
inline bool EnumDescriptorProto::has_options() const {
@@ -5108,16 +5108,16 @@ inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_me
// @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method)
return method_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
-ServiceDescriptorProto::method() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
- return method_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >*
ServiceDescriptorProto::mutable_method() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method)
return &method_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >&
+ServiceDescriptorProto::method() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method)
+ return method_;
+}
// optional .google.protobuf.ServiceOptions options = 3;
inline bool ServiceDescriptorProto::has_options() const {
@@ -5945,16 +5945,16 @@ inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_o
// @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FileOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FileOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FileOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6075,16 +6075,16 @@ inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterprete
// @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MessageOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MessageOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MessageOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6255,16 +6255,16 @@ inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_
// @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-FieldOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
FieldOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+FieldOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6337,16 +6337,16 @@ inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_o
// @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6395,16 +6395,16 @@ inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpre
// @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-EnumValueOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
EnumValueOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+EnumValueOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6453,16 +6453,16 @@ inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterprete
// @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-ServiceOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
ServiceOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ServiceOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6511,16 +6511,16 @@ inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted
// @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option)
return uninterpreted_option_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
-MethodOptions::uninterpreted_option() const {
- // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
- return uninterpreted_option_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
MethodOptions::mutable_uninterpreted_option() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option)
return &uninterpreted_option_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+MethodOptions::uninterpreted_option() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option)
+ return uninterpreted_option_;
+}
// -------------------------------------------------------------------
@@ -6626,16 +6626,16 @@ inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::ad
// @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name)
return name_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
-UninterpretedOption::name() const {
- // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
- return name_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >*
UninterpretedOption::mutable_name() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name)
return &name_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >&
+UninterpretedOption::name() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name)
+ return name_;
+}
// optional string identifier_value = 3;
inline bool UninterpretedOption::has_identifier_value() const {
@@ -7115,16 +7115,16 @@ inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location
// @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location)
return location_.Add();
}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
-SourceCodeInfo::location() const {
- // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
- return location_;
-}
inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >*
SourceCodeInfo::mutable_location() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location)
return &location_;
}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >&
+SourceCodeInfo::location() const {
+ // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location)
+ return location_;
+}
#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS
// -------------------------------------------------------------------
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 9d3dd8fb..8f90a956 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -42,9 +42,9 @@ syntax = "proto2";
package google.protobuf;
option go_package = "descriptor";
option java_package = "com.google.protobuf";
-option javanano_use_deprecated_package = true;
option java_outer_classname = "DescriptorProtos";
-option csharp_namespace = "Google.Protobuf.Reflection";
+// Re-enable this once the tools have picked up the csharp_namespace option.
+// option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos";
option objc_class_prefix = "GPB";
// descriptor.proto must be optimized for speed because reflection-based
@@ -301,10 +301,12 @@ message FileOptions {
// If set true, then the Java code generator will generate equals() and
// hashCode() methods for all messages defined in the .proto file.
- // - In the full runtime, this is purely a speed optimization, as the
+ // This increases generated code size, potentially substantially for large
+ // protos, which may harm a memory-constrained application.
+ // - In the full runtime this is a speed optimization, as the
// AbstractMessage base class includes reflection-based implementations of
// these methods.
- //- In the lite runtime, setting this option changes the semantics of
+ // - In the lite runtime, setting this option changes the semantics of
// equals() and hashCode() to more closely match those of the full runtime;
// the generated methods compute their results based on field values rather
// than object identity. (Implementations should not assume that hashcodes
@@ -525,6 +527,7 @@ message FieldOptions {
// For Google-internal migration only. Do not use.
optional bool weak = 10 [default=false];
+
// The parser stores options it doesn't recognize here. See above.
repeated UninterpretedOption uninterpreted_option = 999;
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index 1c03c443..a87fa049 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -42,7 +42,9 @@
#include <google/protobuf/text_format.h>
#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 760df097..e9b027db 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -49,6 +49,8 @@
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -368,6 +370,37 @@ TEST_F(FileDescriptorTest, BuildAgain) {
EXPECT_TRUE(pool_.BuildFile(file) == NULL);
}
+TEST_F(FileDescriptorTest, BuildAgainWithSyntax) {
+ // Test that if te call BuildFile again on the same input we get the same
+ // FileDescriptor back even if syntax param is specified.
+ FileDescriptorProto proto_syntax2;
+ proto_syntax2.set_name("foo_syntax2");
+ proto_syntax2.set_syntax("proto2");
+
+ const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2);
+ EXPECT_TRUE(proto2_descriptor != NULL);
+ EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2));
+
+ FileDescriptorProto implicit_proto2;
+ implicit_proto2.set_name("foo_implicit_syntax2");
+
+ const FileDescriptor* implicit_proto2_descriptor =
+ pool_.BuildFile(implicit_proto2);
+ EXPECT_TRUE(implicit_proto2_descriptor != NULL);
+ // We get the same FileDescriptor back if syntax param is explicitly
+ // specified.
+ implicit_proto2.set_syntax("proto2");
+ EXPECT_EQ(implicit_proto2_descriptor, pool_.BuildFile(implicit_proto2));
+
+ FileDescriptorProto proto_syntax3;
+ proto_syntax3.set_name("foo_syntax3");
+ proto_syntax3.set_syntax("proto3");
+
+ const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3);
+ EXPECT_TRUE(proto3_descriptor != NULL);
+ EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3));
+}
+
TEST_F(FileDescriptorTest, Syntax) {
FileDescriptorProto proto;
proto.set_name("foo");
@@ -3583,7 +3616,7 @@ TEST_F(ValidationErrorTest, FieldOneofIndexNegative) {
TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
// Fields belonging to the same oneof must be defined consecutively.
- BuildFileWithWarnings(
+ BuildFileWithErrors(
"name: \"foo.proto\" "
"message_type {"
" name: \"Foo\""
@@ -3600,7 +3633,7 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
"\"foos\" oneof definition.\n");
// Prevent interleaved fields, which belong to different oneofs.
- BuildFileWithWarnings(
+ BuildFileWithErrors(
"name: \"foo2.proto\" "
"message_type {"
" name: \"Foo2\""
@@ -3621,6 +3654,25 @@ TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) {
"foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined "
"consecutively. \"foo2\" cannot be defined before the completion of the "
"\"bars\" oneof definition.\n");
+
+ // Another case for normal fields and different oneof fields interleave.
+ BuildFileWithErrors(
+ "name: \"foo3.proto\" "
+ "message_type {"
+ " name: \"Foo3\""
+ " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 1 }"
+ " field { name:\"baz\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 }"
+ " field { name:\"foo2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 "
+ " oneof_index: 0 }"
+ " oneof_decl { name:\"foos\" }"
+ " oneof_decl { name:\"bars\" }"
+ "}",
+ "foo3.proto: Foo3.baz: OTHER: Fields in the same oneof must be defined "
+ "consecutively. \"baz\" cannot be defined before the completion of the "
+ "\"foos\" oneof definition.\n");
}
TEST_F(ValidationErrorTest, FieldNumberConflict) {
@@ -5369,6 +5421,35 @@ TEST_F(ValidationErrorTest, MapEntryConflictsWithOneof) {
"with an existing oneof type.\n");
}
+TEST_F(ValidationErrorTest, MapEntryUsesNoneZeroEnumDefaultValue) {
+ BuildFileWithErrors(
+ "name: \"foo.proto\" "
+ "enum_type {"
+ " name: \"Bar\""
+ " value { name:\"ENUM_A\" number:1 }"
+ " value { name:\"ENUM_B\" number:2 }"
+ "}"
+ "message_type {"
+ " name: 'Foo' "
+ " field { "
+ " name: 'foo_map' number: 1 label:LABEL_REPEATED "
+ " type_name: 'FooMapEntry' "
+ " } "
+ " nested_type { "
+ " name: 'FooMapEntry' "
+ " options { map_entry: true } "
+ " field { "
+ " name: 'key' number: 1 type:TYPE_INT32 label:LABEL_OPTIONAL "
+ " } "
+ " field { "
+ " name: 'value' number: 2 type_name:\"Bar\" label:LABEL_OPTIONAL "
+ " } "
+ " } "
+ "}",
+ "foo.proto: Foo.foo_map: "
+ "TYPE: Enum value in map must define 0 as the first value.\n");
+}
+
TEST_F(ValidationErrorTest, Proto3RequiredFields) {
BuildFileWithErrors(
"name: 'foo.proto' "
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 318ce6f9..2324d952 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -65,6 +65,7 @@
#include <algorithm>
#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/dynamic_message.h>
@@ -79,6 +80,7 @@
#include <google/protobuf/map_type_handler.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/map_field.h>
namespace google {
namespace protobuf {
@@ -87,7 +89,7 @@ using internal::WireFormat;
using internal::ExtensionSet;
using internal::GeneratedMessageReflection;
using internal::MapField;
-using internal::MapFieldBase;
+using internal::DynamicMapField;
using internal::ArenaStringPtr;
@@ -116,7 +118,7 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
case FD::CPPTYPE_ENUM : return sizeof(RepeatedField<int >);
case FD::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
- return sizeof(MapFieldBase);
+ return sizeof(DynamicMapField);
} else {
return sizeof(RepeatedPtrField<Message>);
}
@@ -389,7 +391,8 @@ void DynamicMessage::SharedCtor() {
new(field_ptr) Message*(NULL);
} else {
if (IsMapFieldInApi(field)) {
- new (field_ptr) MapFieldBase();
+ new (field_ptr) DynamicMapField(
+ type_info_->factory->GetPrototypeNoLock(field->message_type()));
} else {
new (field_ptr) RepeatedPtrField<Message>();
}
@@ -437,8 +440,8 @@ DynamicMessage::~DynamicMessage() {
&(reinterpret_cast<const ArenaStringPtr*>(
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]))->Get(NULL));
- reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
- NULL);
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+ default_value, NULL);
break;
}
}
@@ -480,7 +483,7 @@ DynamicMessage::~DynamicMessage() {
case FieldDescriptor::CPPTYPE_MESSAGE:
if (IsMapFieldInApi(field)) {
- reinterpret_cast<MapFieldBase*>(field_ptr)->~MapFieldBase();
+ reinterpret_cast<DynamicMapField*>(field_ptr)->~DynamicMapField();
} else {
reinterpret_cast<RepeatedPtrField<Message>*>(field_ptr)
->~RepeatedPtrField<Message>();
@@ -496,8 +499,8 @@ DynamicMessage::~DynamicMessage() {
&(reinterpret_cast<const ArenaStringPtr*>(
type_info_->prototype->OffsetToPointer(
type_info_->offsets[i]))->Get(NULL));
- reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(default_value,
- NULL);
+ reinterpret_cast<ArenaStringPtr*>(field_ptr)->Destroy(
+ default_value, NULL);
break;
}
}
@@ -723,8 +726,14 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
// Allocate the prototype.
void* base = operator new(size);
memset(base, 0, size);
+ // The prototype in type_info has to be set before creating the prototype
+ // instance on memory. e.g., message Foo { map<int32, Foo> a = 1; }. When
+ // creating prototype for Foo, prototype of the map entry will also be
+ // created, which needs the address of the prototype of Foo (the value in
+ // map). To break the cyclic dependency, we have to assgin the address of
+ // prototype into type_info first.
+ type_info->prototype = static_cast<DynamicMessage*>(base);
DynamicMessage* prototype = new(base) DynamicMessage(type_info);
- type_info->prototype = prototype;
// Construct the reflection object.
if (type->oneof_decl_count() > 0) {
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index b5928a52..f74cd7dd 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -45,6 +45,7 @@
#include <google/protobuf/message.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/mutex.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index 522a092a..b9796c76 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -40,6 +40,7 @@
// reflection_ops_unittest, cover the rest of the functionality used by
// DynamicMessage.
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/descriptor.h>
@@ -48,6 +49,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_no_field_presence.pb.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index c371e011..9ef4e27d 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -45,6 +45,7 @@
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/repeated_field.h>
@@ -330,6 +331,8 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
const MessageLite& prototype, desc);
MessageLite* AddMessage(const FieldDescriptor* descriptor,
MessageFactory* factory);
+ void AddAllocatedMessage(const FieldDescriptor* descriptor,
+ MessageLite* new_entry);
#undef desc
void RemoveLast(int number);
@@ -578,6 +581,10 @@ class LIBPROTOBUF_EXPORT ExtensionSet {
bool MaybeNewExtension(int number, const FieldDescriptor* descriptor,
Extension** result);
+ // Gets the repeated extension for the given descriptor, creating it if
+ // it does not exist.
+ Extension* MaybeNewRepeatedExtension(const FieldDescriptor* descriptor);
+
// Parse a single MessageSet item -- called just after the item group start
// tag has been read.
bool ParseMessageSetItem(io::CodedInputStream* input,
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index 330bd828..82e3e099 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -213,8 +213,7 @@ MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor,
}
}
-MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
- MessageFactory* factory) {
+ExtensionSet::Extension* ExtensionSet::MaybeNewRepeatedExtension(const FieldDescriptor* descriptor) {
Extension* extension;
if (MaybeNewExtension(descriptor->number(), descriptor, &extension)) {
extension->type = descriptor->type();
@@ -225,6 +224,12 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
} else {
GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE);
}
+ return extension;
+}
+
+MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
+ MessageFactory* factory) {
+ Extension* extension = MaybeNewRepeatedExtension(descriptor);
// RepeatedPtrField<Message> does not know how to Add() since it cannot
// allocate an abstract object, so we have to be tricky.
@@ -244,6 +249,13 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor,
return result;
}
+void ExtensionSet::AddAllocatedMessage(const FieldDescriptor* descriptor,
+ MessageLite* new_entry) {
+ Extension* extension = MaybeNewRepeatedExtension(descriptor);
+
+ extension->repeated_message_value->AddAllocated(new_entry);
+}
+
static bool ValidateEnumUsingDescriptor(const void* arg, int number) {
return reinterpret_cast<const EnumDescriptor*>(arg)
->FindValueByNumber(number) != NULL;
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 684ce002..1569120d 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -44,6 +44,7 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
@@ -173,7 +174,7 @@ TEST(ExtensionSetTest, SetAllocatedExtension) {
}
TEST(ExtensionSetTest, ReleaseExtension) {
- unittest::TestMessageSet message;
+ proto2_wireformat_unittest::TestMessageSet message;
EXPECT_FALSE(message.HasExtension(
unittest::TestMessageSetExtension1::message_set_extension));
// Add a extension using SetAllocatedExtension
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 412c48a1..b9957e75 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -35,6 +35,7 @@
#include <algorithm>
#include <set>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
@@ -818,7 +819,16 @@ void GeneratedMessageReflection::ClearField(
}
case FieldDescriptor::CPPTYPE_MESSAGE:
- (*MutableRaw<Message*>(message, field))->Clear();
+ if (has_bits_offset_ == -1) {
+ // Proto3 does not have has-bits and we need to set a message field
+ // to NULL in order to indicate its un-presence.
+ if (GetArena(message) == NULL) {
+ delete *MutableRaw<Message*>(message, field);
+ }
+ *MutableRaw<Message*>(message, field) = NULL;
+ } else {
+ (*MutableRaw<Message*>(message, field))->Clear();
+ }
break;
}
}
@@ -1649,6 +1659,25 @@ Message* GeneratedMessageReflection::AddMessage(
}
}
+void GeneratedMessageReflection::AddAllocatedMessage(
+ Message* message, const FieldDescriptor* field,
+ Message* new_entry) const {
+ USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
+
+ if (field->is_extension()) {
+ MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry);
+ } else {
+ RepeatedPtrFieldBase* repeated = NULL;
+ if (IsMapFieldInApi(field)) {
+ repeated =
+ MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
+ } else {
+ repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
+ }
+ repeated->AddAllocated<GenericTypeHandler<Message> >(new_entry);
+ }
+}
+
void* GeneratedMessageReflection::MutableRawRepeatedField(
Message* message, const FieldDescriptor* field,
FieldDescriptor::CppType cpptype,
@@ -1675,6 +1704,37 @@ void* GeneratedMessageReflection::MutableRawRepeatedField(
}
}
+const void* GeneratedMessageReflection::GetRawRepeatedField(
+ const Message& message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpptype,
+ int ctype, const Descriptor* desc) const {
+ USAGE_CHECK_REPEATED("GetRawRepeatedField");
+ if (field->cpp_type() != cpptype)
+ ReportReflectionUsageTypeError(descriptor_,
+ field, "GetRawRepeatedField", cpptype);
+ if (ctype >= 0)
+ GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
+ if (desc != NULL)
+ GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
+ if (field->is_extension()) {
+ // Should use extension_set::GetRawRepeatedField. However, the required
+ // parameter "default repeated value" is not very easy to get here.
+ // Map is not supported in extensions, it is acceptable to use
+ // extension_set::MutableRawRepeatedField which does not change the message.
+ return MutableExtensionSet(const_cast<Message*>(&message))
+ ->MutableRawRepeatedField(
+ field->number(), field->type(), field->is_packed(), field);
+ } else {
+ // Trigger transform for MapField
+ if (IsMapFieldInApi(field)) {
+ return &(reinterpret_cast<const MapFieldBase*>(
+ reinterpret_cast<const uint8*>(&message) +
+ offsets_[field->index()])->GetRepeatedField());
+ }
+ return reinterpret_cast<const uint8*>(&message) + offsets_[field->index()];
+ }
+}
+
const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
const Message& message,
const OneofDescriptor* oneof_descriptor) const {
@@ -1685,6 +1745,69 @@ const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
return descriptor_->FindFieldByNumber(field_number);
}
+bool GeneratedMessageReflection::ContainsMapKey(
+ const Message& message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "LookupMapValue",
+ "Field is not a map field.");
+ return GetRaw<MapFieldBase>(message, field).ContainsMapKey(key);
+}
+
+bool GeneratedMessageReflection::InsertOrLookupMapValue(
+ Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key,
+ MapValueRef* val) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "InsertOrLookupMapValue",
+ "Field is not a map field.");
+ val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+ return MutableRaw<MapFieldBase>(message, field)->InsertMapValue(key, val);
+}
+
+bool GeneratedMessageReflection::DeleteMapValue(
+ Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "DeleteMapValue",
+ "Field is not a map field.");
+ return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(key);
+}
+
+MapIterator GeneratedMessageReflection::MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapBegin",
+ "Field is not a map field.");
+ MapIterator iter(message, field);
+ GetRaw<MapFieldBase>(*message, field).MapBegin(&iter);
+ return iter;
+}
+
+MapIterator GeneratedMessageReflection::MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapEnd",
+ "Field is not a map field.");
+ MapIterator iter(message, field);
+ GetRaw<MapFieldBase>(*message, field).MapEnd(&iter);
+ return iter;
+}
+
+int GeneratedMessageReflection::MapSize(
+ const Message& message,
+ const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "MapSize",
+ "Field is not a map field.");
+ return GetRaw<MapFieldBase>(message, field).size();
+}
+
// -----------------------------------------------------------------------------
const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
@@ -2098,6 +2221,14 @@ void* GeneratedMessageReflection::RepeatedFieldData(
}
}
+MapFieldBase* GeneratedMessageReflection::MapData(
+ Message* message, const FieldDescriptor* field) const {
+ USAGE_CHECK(IsMapFieldInApi(field),
+ "GetMapData",
+ "Field is not a map field.");
+ return MutableRaw<MapFieldBase>(message, field);
+}
+
GeneratedMessageReflection*
GeneratedMessageReflection::NewGeneratedMessageReflection(
const Descriptor* descriptor,
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index dc8abb98..85ce6e2e 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -58,7 +58,9 @@ class GMR_Handlers;
} // namespace upb
namespace protobuf {
- class DescriptorPool;
+class DescriptorPool;
+class MapKey;
+class MapValueRef;
}
namespace protobuf {
@@ -261,6 +263,25 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
const Message& message,
const OneofDescriptor* oneof_descriptor) const;
+ private:
+ bool ContainsMapKey(const Message& message,
+ const FieldDescriptor* field,
+ const MapKey& key) const;
+ bool InsertOrLookupMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key,
+ MapValueRef* val) const;
+ bool DeleteMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key) const;
+ MapIterator MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const;
+ MapIterator MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const;
+ int MapSize(const Message& message, const FieldDescriptor* field) const;
+
public:
void SetInt32 (Message* message,
const FieldDescriptor* field, int32 value) const;
@@ -371,6 +392,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
int value) const;
Message* AddMessage(Message* message, const FieldDescriptor* field,
MessageFactory* factory = NULL) const;
+ void AddAllocatedMessage(
+ Message* message, const FieldDescriptor* field,
+ Message* new_entry) const;
const FieldDescriptor* FindKnownExtensionByName(const string& name) const;
const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
@@ -391,9 +415,14 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
static const int kUnknownFieldSetInMetadata = -1;
protected:
- virtual void* MutableRawRepeatedField(
+ void* MutableRawRepeatedField(
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
- int ctype, const Descriptor* desc) const;
+ int ctype, const Descriptor* desc) const override;
+
+ const void* GetRawRepeatedField(
+ const Message& message, const FieldDescriptor* field,
+ FieldDescriptor::CppType, int ctype,
+ const Descriptor* desc) const override;
virtual MessageFactory* GetMessageFactory() const;
@@ -407,7 +436,7 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
// To parse directly into a proto2 generated class, the class GMR_Handlers
// needs access to member offsets and hasbits.
- friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
+ friend class upb::google_opensource::GMR_Handlers;
const Descriptor* descriptor_;
const Message* default_instance_;
@@ -539,6 +568,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection {
Message* sub_message,
const FieldDescriptor* field) const;
+ internal::MapFieldBase* MapData(
+ Message* message, const FieldDescriptor* field) const;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
};
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index ca1a2918..df043844 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -47,6 +47,7 @@
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -546,6 +547,57 @@ TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) {
&to_message, TestUtil::ReflectionTester::IS_NULL);
}
+TEST(GeneratedMessageReflectionTest, AddRepeatedMessage) {
+ unittest::TestAllTypes message;
+
+ const Reflection* reflection = message.GetReflection();
+ const Reflection* nested_reflection =
+ unittest::TestAllTypes::NestedMessage::default_instance().GetReflection();
+
+ const FieldDescriptor* nested_bb =
+ unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName(
+ "bb");
+
+ Message* nested = reflection->AddMessage(
+ &message, F("repeated_nested_message"));
+ nested_reflection->SetInt32(nested, nested_bb, 11);
+
+ EXPECT_EQ(11, message.repeated_nested_message(0).bb());
+}
+
+TEST(GeneratedMessageReflectionTest, MutableRepeatedMessage) {
+ unittest::TestAllTypes message;
+
+ const Reflection* reflection = message.GetReflection();
+ const Reflection* nested_reflection =
+ unittest::TestAllTypes::NestedMessage::default_instance().GetReflection();
+
+ const FieldDescriptor* nested_bb =
+ unittest::TestAllTypes::NestedMessage::descriptor()->FindFieldByName(
+ "bb");
+
+ message.add_repeated_nested_message()->set_bb(12);
+
+ Message* nested = reflection->MutableRepeatedMessage(
+ &message, F("repeated_nested_message"), 0);
+ EXPECT_EQ(12, nested_reflection->GetInt32(*nested, nested_bb));
+ nested_reflection->SetInt32(nested, nested_bb, 13);
+ EXPECT_EQ(13, message.repeated_nested_message(0).bb());
+}
+
+TEST(GeneratedMessageReflectionTest, AddAllocatedMessage) {
+ unittest::TestAllTypes message;
+
+ const Reflection* reflection = message.GetReflection();
+
+ unittest::TestAllTypes::NestedMessage* nested =
+ new unittest::TestAllTypes::NestedMessage();
+ nested->set_bb(11);
+ reflection->AddAllocatedMessage(&message, F("repeated_nested_message"), nested);
+ EXPECT_EQ(1, message.repeated_nested_message_size());
+ EXPECT_EQ(11, message.repeated_nested_message(0).bb());
+}
+
TEST(GeneratedMessageReflectionTest, ListFieldsOneOf) {
unittest::TestOneof2 message;
TestUtil::SetOneof1(&message);
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 3b8650d6..4bcd354f 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -44,6 +44,7 @@
#include <limits.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/arena.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stl_util.h>
@@ -338,9 +339,9 @@ namespace {
// The first part of the pair is true iff the read was successful. The second
// part is buffer + (number of bytes read). This function is always inlined,
// so returning a pair is costless.
-inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::std::pair<bool, const uint8*> ReadVarint32FromArray(
uint32 first_byte, const uint8* buffer,
- uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ uint32* value);
inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
uint32 first_byte, const uint8* buffer, uint32* value) {
// Fast path: We have enough bytes left in the buffer to guarantee that
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index ad351dc3..361c406b 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -191,16 +191,15 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Like GetDirectBufferPointer, but this method is inlined, and does not
// attempt to Refresh() if the buffer is currently empty.
- inline void GetDirectBufferPointerInline(const void** data,
- int* size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void GetDirectBufferPointerInline(const void** data,
+ int* size);
// Read raw bytes, copying them into the given buffer.
bool ReadRaw(void* buffer, int size);
// Like the above, with inlined optimizations. This should only be used
// by the protobuf implementation.
- inline bool InternalReadRawInline(void* buffer,
- int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadRawInline(void* buffer, int size);
// Like ReadRaw, but reads into a string.
//
@@ -212,8 +211,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
bool ReadString(string* buffer, int size);
// Like the above, with inlined optimizations. This should only be used
// by the protobuf implementation.
- inline bool InternalReadStringInline(string* buffer,
- int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InternalReadStringInline(string* buffer,
+ int size);
// Read a 32-bit little-endian integer.
@@ -243,7 +242,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// Always inline because this is only called in one place per parse loop
// but it is called for every iteration of said loop, so it should be fast.
// GCC doesn't want to inline this by default.
- uint32 ReadTag() GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag();
// This usually a faster alternative to ReadTag() when cutoff is a manifest
// constant. It does particularly well for cutoff >= 127. The first part
@@ -253,8 +252,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// above cutoff or is 0. (There's intentional wiggle room when tag is 0,
// because that can arise in several ways, and for best performance we want
// to avoid an extra "is tag == 0?" check here.)
- inline std::pair<uint32, bool> ReadTagWithCutoff(uint32 cutoff)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair<uint32, bool> ReadTagWithCutoff(
+ uint32 cutoff);
// Usually returns true if calling ReadVarint32() now would produce the given
// value. Will always return false if ReadVarint32() would not return the
@@ -263,7 +262,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
// parameter.
// Always inline because this collapses to a small number of instructions
// when given a constant parameter, but GCC doesn't want to inline by default.
- bool ExpectTag(uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool ExpectTag(uint32 expected);
// Like above, except this reads from the specified buffer. The caller is
// responsible for ensuring that the buffer is large enough to read a varint
@@ -272,9 +271,9 @@ class LIBPROTOBUF_EXPORT CodedInputStream {
//
// Returns a pointer beyond the expected tag if it was found, or NULL if it
// was not.
- static const uint8* ExpectTagFromArray(
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static const uint8* ExpectTagFromArray(
const uint8* buffer,
- uint32 expected) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ uint32 expected);
// Usually returns true if no more bytes can be read. Always returns false
// if more bytes can be read. If ExpectAtEnd() returns true, a subsequent
@@ -766,8 +765,8 @@ class LIBPROTOBUF_EXPORT CodedOutputStream {
// but GCC by default doesn't want to inline this.
void WriteTag(uint32 value);
// Like WriteTag() but writing directly to the target array.
- static uint8* WriteTagToArray(
- uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteTagToArray(uint32 value,
+ uint8* target);
// Returns the number of bytes needed to encode the given value as a varint.
static int VarintSize32(uint32 value);
@@ -831,8 +830,8 @@ 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* WriteVarint64ToArrayInline(
- uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE static uint8* WriteVarint64ToArrayInline(
+ uint64 value, uint8* target);
static int VarintSize32Fallback(uint32 value);
};
diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h
index fa20f208..d95b06e0 100644
--- a/src/google/protobuf/io/coded_stream_inl.h
+++ b/src/google/protobuf/io/coded_stream_inl.h
@@ -36,6 +36,7 @@
#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index 02d5bad3..630c9086 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -41,6 +41,8 @@
#include <limits.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
index dd7c036e..1be6c863 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -33,10 +33,12 @@
// This file contains the implementation of classes GzipInputStream and
// GzipOutputStream.
+
#if HAVE_ZLIB
#include <google/protobuf/io/gzip_stream.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 3ae8c268..7d886506 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index 1331a8d9..258dd986 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc
index 56973439..579de9aa 100644
--- a/src/google/protobuf/io/strtod.cc
+++ b/src/google/protobuf/io/strtod.cc
@@ -34,6 +34,7 @@
#include <cstring>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index 60bd7957..7ccd633d 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -90,6 +90,7 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/io/strtod.h>
#include <google/protobuf/io/zero_copy_stream.h>
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 98576f56..49885eda 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -40,6 +40,7 @@
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index de096fb9..6526056a 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -41,6 +41,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc
index f77c768f..186de001 100644
--- a/src/google/protobuf/io/zero_copy_stream.cc
+++ b/src/google/protobuf/io/zero_copy_stream.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
index f7901b27..7ec2b5da 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -46,6 +46,7 @@
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index 97b73b88..686e63f2 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -39,6 +39,7 @@
#include <google/protobuf/stubs/casts.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stl_util.h>
namespace google {
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 4360b18f..9cdf0378 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -48,6 +48,7 @@
#include <iosfwd>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index f2e5b629..3850e76c 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -46,6 +46,7 @@
// "parametized tests" so that one set of tests can be used on all the
// implementations.
+
#ifdef _MSC_VER
#include <io.h>
#else
@@ -66,6 +67,8 @@
#endif
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/testing/googletest.h>
#include <google/protobuf/testing/file.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index 5af8b24d..d1948ab5 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -33,6 +33,7 @@
#include <string>
#include <iostream>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena_test_util.h>
#include <google/protobuf/map_lite_unittest.pb.h>
@@ -377,13 +378,6 @@ int main(int argc, char* argv[]) {
}
{
- // Proto2SetMapFieldsInitialized
- protobuf_unittest::TestEnumStartWithNonZeroMapLite message;
- EXPECT_EQ(protobuf_unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE,
- (*message.mutable_map_field())[0]);
- }
-
- {
// Clear
protobuf_unittest::TestMapLite message;
@@ -692,37 +686,6 @@ int main(int argc, char* argv[]) {
EXPECT_TRUE(map_message.IsInitialized());
}
- // arena support for map =========================================
-
- {
- // ParsingAndSerializingNoHeapAllocation
-
- // Allocate a large initial block to avoid mallocs during hooked test.
- std::vector<char> arena_block(128 * 1024);
- google::protobuf::ArenaOptions options;
- options.initial_block = &arena_block[0];
- options.initial_block_size = arena_block.size();
- google::protobuf::Arena arena(options);
- string data;
- data.reserve(128 * 1024);
-
- {
- google::protobuf::internal::NoHeapChecker no_heap;
-
- protobuf_unittest::TestArenaMapLite* from =
- google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
- &arena);
- google::protobuf::MapLiteTestUtil::SetArenaMapFields(from);
- from->SerializeToString(&data);
-
- protobuf_unittest::TestArenaMapLite* to =
- google::protobuf::Arena::CreateMessage<protobuf_unittest::TestArenaMapLite>(
- &arena);
- to->ParseFromString(data);
- google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to);
- }
- }
-
std::cout << "PASS" << std::endl;
return 0;
}
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index d928b7a7..c43df13e 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -35,9 +35,12 @@
#include <google/protobuf/stubs/hash.h>
#include <limits> // To support Visual Studio 2008
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/generated_enum_util.h>
#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/descriptor.h>
namespace google {
namespace protobuf {
@@ -47,13 +50,379 @@ class Map;
template <typename Enum> struct is_proto_enum;
+class MapIterator;
+
namespace internal {
template <typename Key, typename T,
WireFormatLite::FieldType key_wire_type,
WireFormatLite::FieldType value_wire_type,
int default_enum_value>
class MapFieldLite;
-}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType key_wire_type,
+ WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+class MapField;
+
+template <typename Key, typename T>
+class TypeDefinedMapFieldBase;
+
+class DynamicMapField;
+
+class GeneratedMessageReflection;
+} // namespace internal
+
+#define TYPE_CHECK(EXPECTEDTYPE, METHOD) \
+ if (type() != EXPECTEDTYPE) { \
+ GOOGLE_LOG(FATAL) \
+ << "Protocol Buffer map usage error:\n" \
+ << METHOD << " type does not match\n" \
+ << " Expected : " \
+ << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
+ << " Actual : " \
+ << FieldDescriptor::CppTypeName(type()); \
+ }
+
+// MapKey is an union type for representing any possible
+// map key.
+class LIBPROTOBUF_EXPORT MapKey {
+ public:
+ MapKey() : type_(0) {
+ }
+ MapKey(const MapKey& other) : type_(0) {
+ CopyFrom(other);
+ }
+
+ ~MapKey() {
+ if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+ delete val_.string_value_;
+ }
+ }
+
+ FieldDescriptor::CppType type() const {
+ if (type_ == 0) {
+ GOOGLE_LOG(FATAL)
+ << "Protocol Buffer map usage error:\n"
+ << "MapKey::type MapKey is not initialized. "
+ << "Call set methods to initialize MapKey.";
+ }
+ return (FieldDescriptor::CppType)type_;
+ }
+
+ void SetInt64Value(int64 value) {
+ SetType(FieldDescriptor::CPPTYPE_INT64);
+ val_.int64_value_ = value;
+ }
+ void SetUInt64Value(uint64 value) {
+ SetType(FieldDescriptor::CPPTYPE_UINT64);
+ val_.uint64_value_ = value;
+ }
+ void SetInt32Value(int32 value) {
+ SetType(FieldDescriptor::CPPTYPE_INT32);
+ val_.int32_value_ = value;
+ }
+ void SetUInt32Value(uint32 value) {
+ SetType(FieldDescriptor::CPPTYPE_UINT32);
+ val_.uint32_value_ = value;
+ }
+ void SetBoolValue(bool value) {
+ SetType(FieldDescriptor::CPPTYPE_BOOL);
+ val_.bool_value_ = value;
+ }
+ void SetStringValue(const string& val) {
+ SetType(FieldDescriptor::CPPTYPE_STRING);
+ *val_.string_value_ = val;
+ }
+
+ int64 GetInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+ "MapKey::GetInt64Value");
+ return val_.int64_value_;
+ }
+ uint64 GetUInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+ "MapKey::GetUInt64Value");
+ return val_.uint64_value_;
+ }
+ int32 GetInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+ "MapKey::GetInt32Value");
+ return val_.int32_value_;
+ }
+ uint32 GetUInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+ "MapKey::GetUInt32Value");
+ return val_.uint32_value_;
+ }
+ int32 GetBoolValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+ "MapKey::GetBoolValue");
+ return val_.bool_value_;
+ }
+ const string& GetStringValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+ "MapKey::GetStringValue");
+ return *val_.string_value_;
+ }
+
+ bool operator==(const MapKey& other) const {
+ if (type_ != other.type_) {
+ return false;
+ }
+ switch (type()) {
+ case FieldDescriptor::CPPTYPE_STRING:
+ return *val_.string_value_ == *other.val_.string_value_;
+ case FieldDescriptor::CPPTYPE_INT64:
+ return val_.int64_value_ == other.val_.int64_value_;
+ case FieldDescriptor::CPPTYPE_INT32:
+ return val_.int32_value_ == other.val_.int32_value_;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return val_.uint64_value_ == other.val_.uint64_value_;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return val_.uint32_value_ == other.val_.uint32_value_;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return val_.bool_value_ == other.val_.bool_value_;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return false;
+ }
+ }
+
+ void CopyFrom(const MapKey& other) {
+ SetType(other.type());
+ switch (type_) {
+ case FieldDescriptor::CPPTYPE_STRING:
+ *val_.string_value_ = *other.val_.string_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_INT64:
+ val_.int64_value_ = other.val_.int64_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_INT32:
+ val_.int32_value_ = other.val_.int32_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_UINT64:
+ val_.uint64_value_ = other.val_.uint64_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_UINT32:
+ val_.uint32_value_ = other.val_.uint32_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_BOOL:
+ val_.bool_value_ = other.val_.bool_value_;
+ break;
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ case FieldDescriptor::CPPTYPE_ENUM:
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+ }
+
+ private:
+ template <typename K, typename V>
+ friend class internal::TypeDefinedMapFieldBase;
+ friend class MapIterator;
+ friend class internal::DynamicMapField;
+
+ union KeyValue {
+ KeyValue() {}
+ string* string_value_;
+ int64 int64_value_;
+ int32 int32_value_;
+ uint64 uint64_value_;
+ uint32 uint32_value_;
+ bool bool_value_;
+ } val_;
+
+ void SetType(FieldDescriptor::CppType type) {
+ if (type_ == type) return;
+ if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+ delete val_.string_value_;
+ }
+ type_ = type;
+ if (type_ == FieldDescriptor::CPPTYPE_STRING) {
+ val_.string_value_ = new string;
+ }
+ }
+
+ // type_ is 0 or a valid FieldDescriptor::CppType.
+ int type_;
+};
+
+// MapValueRef points to a map value.
+class LIBPROTOBUF_EXPORT MapValueRef {
+ public:
+ MapValueRef() : data_(NULL), type_(0) {}
+
+ void SetInt64Value(int64 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+ "MapValueRef::SetInt64Value");
+ *reinterpret_cast<int64*>(data_) = value;
+ }
+ void SetUInt64Value(uint64 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+ "MapValueRef::SetUInt64Value");
+ *reinterpret_cast<uint64*>(data_) = value;
+ }
+ void SetInt32Value(int32 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+ "MapValueRef::SetInt32Value");
+ *reinterpret_cast<int32*>(data_) = value;
+ }
+ void SetUInt32Value(uint64 value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+ "MapValueRef::SetUInt32Value");
+ *reinterpret_cast<uint32*>(data_) = value;
+ }
+ void SetBoolValue(bool value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+ "MapValueRef::SetBoolValue");
+ *reinterpret_cast<bool*>(data_) = value;
+ }
+ // TODO(jieluo) - Checks that enum is member.
+ void SetEnumValue(int value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
+ "MapValueRef::SetEnumValue");
+ *reinterpret_cast<int*>(data_) = value;
+ }
+ void SetStringValue(const string& value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+ "MapValueRef::SetStringValue");
+ *reinterpret_cast<string*>(data_) = value;
+ }
+ void SetFloatValue(float value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
+ "MapValueRef::SetFloatValue");
+ *reinterpret_cast<float*>(data_) = value;
+ }
+ void SetDoubleValue(double value) {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
+ "MapValueRef::SetDoubleValue");
+ *reinterpret_cast<double*>(data_) = value;
+ }
+
+ int64 GetInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
+ "MapValueRef::GetInt64Value");
+ return *reinterpret_cast<int64*>(data_);
+ }
+ uint64 GetUInt64Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
+ "MapValueRef::GetUInt64Value");
+ return *reinterpret_cast<uint64*>(data_);
+ }
+ int32 GetInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
+ "MapValueRef::GetInt32Value");
+ return *reinterpret_cast<int32*>(data_);
+ }
+ uint32 GetUInt32Value() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
+ "MapValueRef::GetUInt32Value");
+ return *reinterpret_cast<uint32*>(data_);
+ }
+ bool GetBoolValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL,
+ "MapValueRef::GetBoolValue");
+ return *reinterpret_cast<bool*>(data_);
+ }
+ int GetEnumValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM,
+ "MapValueRef::GetEnumValue");
+ return *reinterpret_cast<int*>(data_);
+ }
+ const string& GetStringValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
+ "MapValueRef::GetStringValue");
+ return *reinterpret_cast<string*>(data_);
+ }
+ float GetFloatValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
+ "MapValueRef::GetFloatValue");
+ return *reinterpret_cast<float*>(data_);
+ }
+ double GetDoubleValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
+ "MapValueRef::GetDoubleValue");
+ return *reinterpret_cast<double*>(data_);
+ }
+
+ const Message& GetMessageValue() const {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
+ "MapValueRef::GetMessageValue");
+ return *reinterpret_cast<Message*>(data_);
+ }
+
+ Message* MutableMessageValue() {
+ TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
+ "MapValueRef::MutableMessageValue");
+ return reinterpret_cast<Message*>(data_);
+ }
+
+ private:
+ template <typename K, typename V,
+ internal::WireFormatLite::FieldType key_wire_type,
+ internal::WireFormatLite::FieldType value_wire_type,
+ int default_enum_value>
+ friend class internal::MapField;
+ template <typename K, typename V>
+ friend class internal::TypeDefinedMapFieldBase;
+ friend class MapIterator;
+ friend class internal::GeneratedMessageReflection;
+ friend class internal::DynamicMapField;
+
+ void SetType(FieldDescriptor::CppType type) {
+ type_ = type;
+ }
+
+ FieldDescriptor::CppType type() const {
+ if (type_ == 0 || data_ == NULL) {
+ GOOGLE_LOG(FATAL)
+ << "Protocol Buffer map usage error:\n"
+ << "MapValueRef::type MapValueRef is not initialized.";
+ }
+ return (FieldDescriptor::CppType)type_;
+ }
+ void SetValue(const void* val) {
+ data_ = const_cast<void*>(val);
+ }
+ void CopyFrom(const MapValueRef& other) {
+ type_ = other.type_;
+ data_ = other.data_;
+ }
+ // Only used in DynamicMapField
+ void DeleteData() {
+ switch (type_) {
+#define HANDLE_TYPE(CPPTYPE, TYPE) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ delete reinterpret_cast<TYPE*>(data_); \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32);
+ HANDLE_TYPE(INT64, int64);
+ HANDLE_TYPE(UINT32, uint32);
+ HANDLE_TYPE(UINT64, uint64);
+ HANDLE_TYPE(DOUBLE, double);
+ HANDLE_TYPE(FLOAT, float);
+ HANDLE_TYPE(BOOL, bool);
+ HANDLE_TYPE(STRING, string);
+ HANDLE_TYPE(ENUM, int32);
+ HANDLE_TYPE(MESSAGE, Message);
+#undef HANDLE_TYPE
+ }
+ }
+ // data_ point to a map value. MapValueRef does not
+ // own this value.
+ void* data_;
+ // type_ is 0 or a valid FieldDescriptor::CppType.
+ int type_;
+};
+
+#undef TYPE_CHECK
// 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
@@ -82,7 +451,6 @@ class MapPair {
T second;
private:
- typedef void DestructorSkippable_;
friend class ::google::protobuf::Arena;
friend class Map<Key, T>;
};
@@ -92,9 +460,6 @@ 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:
typedef Key key_type;
typedef T mapped_type;
@@ -118,7 +483,9 @@ class Map {
: arena_(arena),
allocator_(arena_),
elements_(0, hasher(), key_equal(), allocator_),
- default_enum_value_(0) {}
+ default_enum_value_(0) {
+ arena_->OwnDestructor(&elements_);
+ }
Map(const Map& other)
: arena_(NULL),
@@ -127,6 +494,14 @@ class Map {
default_enum_value_(other.default_enum_value_) {
insert(other.begin(), other.end());
}
+ template <class InputIt>
+ explicit Map(const InputIt& first, const InputIt& last)
+ : arena_(NULL),
+ allocator_(arena_),
+ elements_(0, hasher(), key_equal(), allocator_),
+ default_enum_value_(0) {
+ insert(first, last);
+ }
~Map() { clear(); }
@@ -172,7 +547,7 @@ class Map {
!defined(GOOGLE_PROTOBUF_OS_NACL) && !defined(GOOGLE_PROTOBUF_OS_ANDROID)
template<class NodeType, class... Args>
void construct(NodeType* p, Args&&... args) {
- new ((void*)p) NodeType(std::forward<Args>(args)...);
+ new (static_cast<void*>(p)) NodeType(std::forward<Args>(args)...);
}
template<class NodeType>
@@ -206,6 +581,7 @@ class Map {
}
private:
+ typedef void DestructorSkippable_;
Arena* arena_;
template <typename X>
@@ -216,7 +592,7 @@ class Map {
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*, hash<Key>, equal_to<Key>,
@@ -449,6 +825,35 @@ class Map {
};
} // namespace protobuf
-
} // namespace google
+
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
+template<>
+struct hash<google::protobuf::MapKey> {
+ size_t
+ operator()(const google::protobuf::MapKey& map_key) const {
+ switch (map_key.type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ return hash<string>()(map_key.GetStringValue());
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ return hash< ::google::protobuf::int64>()(map_key.GetInt64Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ return hash< ::google::protobuf::int32>()(map_key.GetInt32Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ return hash< ::google::protobuf::uint64>()(map_key.GetUInt64Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ return hash< ::google::protobuf::uint32>()(map_key.GetUInt32Value());
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ return hash<bool>()(map_key.GetBoolValue());
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return 0;
+ }
+ }
+};
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
+
#endif // GOOGLE_PROTOBUF_MAP_H__
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index e93d0348..987c4e29 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -34,6 +34,7 @@
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/map_entry_lite.h>
#include <google/protobuf/map_type_handler.h>
+#include <google/protobuf/metadata.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/unknown_field_set.h>
#include <google/protobuf/wire_format_lite_inl.h>
@@ -79,40 +80,46 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
// MapEntry is the returned google::protobuf::Message when calling AddMessage of
// google::protobuf::Reflection. In order to let it work with generated message
-// reflection, its internal layout is the same as generated message with the
-// same fields. However, in order to decide the internal layout of key/value, we
-// need to know both their cpp type in generated api and proto type.
+// reflection, its in-memory type is the same as generated message with the same
+// fields. However, in order to decide the in-memory type of key/value, we need
+// to know both their cpp type in generated api and proto type. In
+// implmentation, all in-memory types have related wire format functions to
+// support except ArenaStringPtr. Therefore, we need to define another type with
+// supporting wire format functions. Since this type is only used as return type
+// of MapEntry accessors, it's named MapEntry accessor type.
//
-// cpp type | proto type | internal layout
-// int32 TYPE_INT32 int32
-// int32 TYPE_FIXED32 int32
-// FooEnum TYPE_ENUM int
-// FooMessage TYPE_MESSAGE FooMessage*
+// cpp type: the type visible to users in public API.
+// proto type: WireFormatLite::FieldType of the field.
+// in-memory type: type of the data member used to stored this field.
+// MapEntry accessor type: type used in MapEntry getters/mutators to access the
+// field.
//
-// The internal layouts of primitive types can be inferred from its proto type,
-// 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.
+// cpp type | proto type | in-memory type | MapEntry accessor type
+// int32 TYPE_INT32 int32 int32
+// int32 TYPE_FIXED32 int32 int32
+// string TYPE_STRING ArenaStringPtr string
+// FooEnum TYPE_ENUM int int
+// FooMessage TYPE_MESSAGE FooMessage* FooMessage
+//
+// The in-memory types of primitive types can be inferred from its proto type,
+// while we need to explicitly specify the cpp type if proto type is
+// TYPE_MESSAGE to infer the in-memory type. Moreover, default_enum_value is
+// used to initialize enum field in proto2.
template <typename Key, typename Value,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value>
class 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.
- 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;
+ // Provide utilities to parse/serialize key/value. Provide utilities to
+ // manipulate internal stored type.
+ typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+ typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
+
+ // Enum type cannot be used for MapTypeHandler::Read. Define a type
+ // which will replace Enum with int.
+ typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename ValueTypeHandler::MapEntryAccessorType
+ ValueMapEntryAccessorType;
// Abbreviation for MapEntry
typedef typename google::protobuf::internal::MapEntry<
@@ -132,16 +139,16 @@ class MapEntry : public MapEntryBase {
// accessors ======================================================
- virtual inline const KeyCppType& key() const {
+ virtual inline const KeyMapEntryAccessorType& key() const {
return entry_lite_.key();
}
- inline KeyCppType* mutable_key() {
+ inline KeyMapEntryAccessorType* mutable_key() {
return entry_lite_.mutable_key();
}
- virtual inline const ValCppType& value() const {
+ virtual inline const ValueMapEntryAccessorType& value() const {
return entry_lite_.value();
}
- inline ValCppType* mutable_value() {
+ inline ValueMapEntryAccessorType* mutable_value() {
return entry_lite_.mutable_value();
}
@@ -240,7 +247,9 @@ class MapEntry : public MapEntryBase {
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);
+ ::google::protobuf::MessageFactory::generated_factory(),
+ sizeof(MapEntry),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_));
entry->descriptor_ = descriptor;
entry->reflection_ = reflection;
entry->set_default_instance(entry);
@@ -250,10 +259,13 @@ class MapEntry : public MapEntryBase {
}
private:
- MapEntry() : default_instance_(NULL), entry_lite_() {}
+ MapEntry()
+ : _internal_metadata_(NULL), default_instance_(NULL), entry_lite_() {}
explicit MapEntry(Arena* arena)
- : default_instance_(NULL), entry_lite_(arena) {}
+ : _internal_metadata_(arena),
+ default_instance_(NULL),
+ entry_lite_(arena) {}
inline Arena* GetArenaNoVirtual() const {
return entry_lite_.GetArenaNoVirtual();
@@ -266,6 +278,7 @@ class MapEntry : public MapEntryBase {
static int offsets_[2];
UnknownFieldSet _unknown_fields_;
+ InternalMetadataWithArena _internal_metadata_;
MapEntry* default_instance_;
EntryLiteType entry_lite_;
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 52746da5..0e6ee013 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -61,38 +61,21 @@ template <typename Key, typename Value,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value>
class 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;
+ // Provide utilities to parse/serialize key/value. Provide utilities to
+ // manipulate internal stored type.
+ typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+ typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
// 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;
+ typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
+ typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
+
+ // Enum type cannot be used for MapTypeHandler::Read. Define a type
+ // which will replace Enum with int.
+ typedef typename KeyTypeHandler::MapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename ValueTypeHandler::MapEntryAccessorType
+ ValueMapEntryAccessorType;
// Constants for field number.
static const int kKeyFieldNumber = 1;
@@ -100,38 +83,37 @@ class MapEntryLite : public MessageLite {
// Constants for field tag.
static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kKeyFieldNumber, KeyWireHandler::kWireType);
+ kKeyFieldNumber, KeyTypeHandler::kWireType);
static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG(
- kValueFieldNumber, ValueWireHandler::kWireType);
+ kValueFieldNumber, ValueTypeHandler::kWireType);
static const int kTagSize = 1;
public:
~MapEntryLite() {
if (this != default_instance_) {
- KeyCppHandler::Delete(key_);
- ValueCppHandler::Delete(value_);
+ if (GetArenaNoVirtual() != NULL) return;
+ KeyTypeHandler::DeleteNoArena(key_);
+ ValueTypeHandler::DeleteNoArena(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 KeyMapEntryAccessorType& key() const {
+ return KeyTypeHandler::GetExternalReference(key_);
}
- virtual inline const ValCppType& value() const {
+ virtual inline const ValueMapEntryAccessorType& value() const {
GOOGLE_CHECK(default_instance_ != NULL);
- return ValueCppHandler::DefaultIfNotInitialized(value_,
+ return ValueTypeHandler::DefaultIfNotInitialized(value_,
default_instance_->value_);
}
- inline ValCppType* mutable_value() {
+ inline KeyMapEntryAccessorType* mutable_key() {
+ set_has_key();
+ return KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ }
+ inline ValueMapEntryAccessorType* mutable_value() {
set_has_value();
- ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
- return ValueCppHandler::Pointer(value_);
+ return ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
}
// implements MessageLite =========================================
@@ -159,13 +141,17 @@ class MapEntryLite : public MessageLite {
tag = input->ReadTag();
switch (tag) {
case kKeyTag:
- if (!KeyWireHandler::Read(input, mutable_key())) return false;
+ if (!KeyTypeHandler::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;
+ if (!ValueTypeHandler::Read(input, mutable_value())) {
+ return false;
+ }
set_has_value();
if (input->ExpectAtEnd()) return true;
break;
@@ -184,32 +170,35 @@ class MapEntryLite : public MessageLite {
int ByteSize() const {
int size = 0;
- size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0;
- size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0;
+ size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0;
+ size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0;
return size;
}
void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const {
- KeyWireHandler::Write(kKeyFieldNumber, key(), output);
- ValueWireHandler::Write(kValueFieldNumber, value(), output);
+ KeyTypeHandler::Write(kKeyFieldNumber, key(), output);
+ ValueTypeHandler::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);
+ output = KeyTypeHandler::WriteToArray(kKeyFieldNumber, key(), output);
+ output = ValueTypeHandler::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;
+ size += has_key()
+ ? kTagSize + KeyTypeHandler::GetCachedSize(key())
+ : 0;
+ size += has_value()
+ ? kTagSize + ValueTypeHandler::GetCachedSize(
+ value())
+ : 0;
return size;
}
- bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); }
+ bool IsInitialized() const { return ValueTypeHandler::IsInitialized(value_); }
MessageLite* New() const {
MapEntryLite* entry = new MapEntryLite;
@@ -225,36 +214,37 @@ class MapEntryLite : public MessageLite {
int SpaceUsed() const {
int size = sizeof(MapEntryLite);
- size += KeyCppHandler::SpaceUsedInMapEntry(key_);
- size += ValueCppHandler::SpaceUsedInMapEntry(value_);
+ size += KeyTypeHandler::SpaceUsedInMapEntry(key_);
+ size += ValueTypeHandler::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_);
+ KeyTypeHandler::EnsureMutable(&key_, GetArenaNoVirtual());
+ KeyTypeHandler::Merge(from.key(), &key_, GetArenaNoVirtual());
set_has_key();
}
if (from.has_value()) {
- ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual());
- ValueCppHandler::Merge(from.value(), &value_);
+ ValueTypeHandler::EnsureMutable(&value_, GetArenaNoVirtual());
+ ValueTypeHandler::Merge(from.value(), &value_, GetArenaNoVirtual());
set_has_value();
}
}
}
void Clear() {
- KeyCppHandler::Clear(&key_);
- ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value);
+ KeyTypeHandler::Clear(&key_, GetArenaNoVirtual());
+ ValueTypeHandler::ClearMaybeByDefaultEnum(
+ &value_, GetArenaNoVirtual(), default_enum_value);
clear_has_key();
clear_has_value();
}
void InitAsDefaultInstance() {
- KeyCppHandler::AssignDefaultValue(&key_);
- ValueCppHandler::AssignDefaultValue(&value_);
+ KeyTypeHandler::AssignDefaultValue(&key_);
+ ValueTypeHandler::AssignDefaultValue(&value_);
}
Arena* GetArena() const {
@@ -302,11 +292,11 @@ class MapEntryLite : public MessageLite {
// 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 MapEntryWrapper
+ 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;
+ typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
public:
MapEntryWrapper(Arena* arena, const K& key, const V& value)
@@ -316,8 +306,8 @@ class MapEntryLite : public MessageLite {
Base::set_has_key();
Base::set_has_value();
}
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
+ inline const KeyMapEntryAccessorType& key() const { return key_; }
+ inline const ValueMapEntryAccessorType& value() const { return value_; }
private:
const Key& key_;
@@ -336,11 +326,11 @@ class MapEntryLite : public MessageLite {
// the temporary.
template <typename K, typename V, WireFormatLite::FieldType k_wire_type,
WireFormatLite::FieldType v_wire_type, int default_enum>
- class MapEnumEntryWrapper
+ 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;
+ typedef typename Base::KeyMapEntryAccessorType KeyMapEntryAccessorType;
+ typedef typename Base::ValueMapEntryAccessorType ValueMapEntryAccessorType;
public:
MapEnumEntryWrapper(Arena* arena, const K& key, const V& value)
@@ -350,28 +340,28 @@ class MapEntryLite : public MessageLite {
Base::set_has_key();
Base::set_has_value();
}
- inline const KeyCppType& key() const { return key_; }
- inline const ValCppType& value() const { return value_; }
+ inline const KeyMapEntryAccessorType& key() const { return key_; }
+ inline const ValueMapEntryAccessorType& value() const { return value_; }
private:
- const KeyCppType& key_;
- const ValCppType value_;
+ const KeyMapEntryAccessorType& key_;
+ const ValueMapEntryAccessorType value_;
friend class google::protobuf::Arena;
typedef void DestructorSkippable_;
};
MapEntryLite() : default_instance_(NULL), arena_(NULL) {
- KeyCppHandler::Initialize(&key_, NULL);
- ValueCppHandler::InitializeMaybeByDefaultEnum(
+ KeyTypeHandler::Initialize(&key_, NULL);
+ ValueTypeHandler::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(
+ KeyTypeHandler::Initialize(&key_, arena);
+ ValueTypeHandler::InitializeMaybeByDefaultEnum(
&value_, default_enum_value, arena);
_has_bits_[0] = 0;
}
@@ -386,8 +376,8 @@ class MapEntryLite : public MessageLite {
MapEntryLite* default_instance_;
- KeyBase key_;
- ValueBase value_;
+ KeyOnMemory key_;
+ ValueOnMemory value_;
Arena* arena_;
uint32 _has_bits_[1];
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index 6ff1936e..d8879f24 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -29,6 +29,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/map_field.h>
+#include <google/protobuf/map_field_inl.h>
#include <vector>
@@ -145,6 +146,321 @@ void MapFieldBase::SyncMapWithRepeatedField() const {
}
}
+// ------------------DynamicMapField------------------
+DynamicMapField::DynamicMapField(const Message* default_entry)
+ : default_entry_(default_entry) {
+}
+
+DynamicMapField::DynamicMapField(const Message* default_entry,
+ Arena* arena)
+ : TypeDefinedMapFieldBase<MapKey, MapValueRef>(arena),
+ default_entry_(default_entry) {
+}
+
+DynamicMapField::~DynamicMapField() {
+ // DynamicMapField owns map values. Need to delete them before clearing
+ // the map.
+ for (typename Map<MapKey, MapValueRef>::iterator iter = map_.begin();
+ iter != map_.end(); ++iter) {
+ iter->second.DeleteData();
+ }
+ map_.clear();
+}
+
+int DynamicMapField::size() const {
+ return GetMap().size();
+}
+
+bool DynamicMapField::ContainsMapKey(
+ const MapKey& map_key) const {
+ const Map<MapKey, MapValueRef>& map = GetMap();
+ typename Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
+ return iter != map.end();
+}
+
+bool DynamicMapField::InsertMapValue(
+ const MapKey& map_key, MapValueRef* val) {
+ bool result = false;
+
+ MapValueRef& map_val = (*MutableMap())[map_key];
+ // If map_val.data_ is not set, it is newly inserted by map_[map_key].
+ if (map_val.data_ == NULL) {
+ result = true;
+ const FieldDescriptor* val_des =
+ default_entry_->GetDescriptor()->FindFieldByName("value");
+ map_val.SetType(val_des->cpp_type());
+ // Allocate momery for the inserted MapValueRef, and initialize to
+ // default value.
+ switch (val_des->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ TYPE * value = new TYPE(); \
+ map_val.SetValue(value); \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32);
+ HANDLE_TYPE(INT64, int64);
+ HANDLE_TYPE(UINT32, uint32);
+ HANDLE_TYPE(UINT64, uint64);
+ HANDLE_TYPE(DOUBLE, double);
+ HANDLE_TYPE(FLOAT, float);
+ HANDLE_TYPE(BOOL, bool);
+ HANDLE_TYPE(STRING, string);
+ HANDLE_TYPE(ENUM, int32);
+#undef HANDLE_TYPE
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ const Message& message = default_entry_->GetReflection()->GetMessage(
+ *default_entry_, val_des);
+ Message* value = message.New();
+ map_val.SetValue(value);
+ break;
+ }
+ }
+ }
+ val->CopyFrom(map_val);
+ return result;
+}
+
+bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
+ MapFieldBase::SyncMapWithRepeatedField();
+ Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
+ if (iter == map_.end()) {
+ return false;
+ }
+ // Set map dirty only if the delete is successful.
+ MapFieldBase::SetMapDirty();
+ iter->second.DeleteData();
+ map_.erase(iter);
+ return true;
+}
+
+const Map<MapKey, MapValueRef>& DynamicMapField::GetMap() const {
+ MapFieldBase::SyncMapWithRepeatedField();
+ return map_;
+}
+
+Map<MapKey, MapValueRef>* DynamicMapField::MutableMap() {
+ MapFieldBase::SyncMapWithRepeatedField();
+ MapFieldBase::SetMapDirty();
+ return &map_;
+}
+
+void DynamicMapField::SetMapIteratorValue(MapIterator* map_iter) const {
+ typename Map<MapKey, MapValueRef>::const_iterator iter =
+ TypeDefinedMapFieldBase<MapKey, MapValueRef>::InternalGetIterator(
+ map_iter);
+ if (iter == map_.end()) return;
+ map_iter->key_.CopyFrom(iter->first);
+ map_iter->value_.CopyFrom(iter->second);
+}
+
+void DynamicMapField::SyncRepeatedFieldWithMapNoLock() const {
+ const Reflection* reflection = default_entry_->GetReflection();
+ const FieldDescriptor* key_des =
+ default_entry_->GetDescriptor()->FindFieldByName("key");
+ const FieldDescriptor* val_des =
+ default_entry_->GetDescriptor()->FindFieldByName("value");
+ if (MapFieldBase::repeated_field_ == NULL) {
+ if (MapFieldBase::arena_ == NULL) {
+ MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
+ } else {
+ MapFieldBase::repeated_field_ =
+ Arena::CreateMessage<RepeatedPtrField<Message> >(
+ MapFieldBase::arena_);
+ }
+ }
+
+ MapFieldBase::repeated_field_->Clear();
+
+ for (typename Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
+ it != map_.end(); ++it) {
+ Message* new_entry = default_entry_->New();
+ MapFieldBase::repeated_field_->AddAllocated(new_entry);
+ const MapKey& map_key = it->first;
+ switch (key_des->cpp_type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ reflection->SetString(new_entry, key_des, map_key.GetStringValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ reflection->SetInt64(new_entry, key_des, map_key.GetInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ reflection->SetInt32(new_entry, key_des, map_key.GetInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ reflection->SetUInt64(new_entry, key_des, map_key.GetUInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ reflection->SetUInt32(new_entry, key_des, map_key.GetUInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ reflection->SetBool(new_entry, key_des, map_key.GetBoolValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+ const MapValueRef& map_val = it->second;
+ switch (val_des->cpp_type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ reflection->SetString(new_entry, val_des, map_val.GetStringValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ reflection->SetInt64(new_entry, val_des, map_val.GetInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ reflection->SetInt32(new_entry, val_des, map_val.GetInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ reflection->SetUInt64(new_entry, val_des, map_val.GetUInt64Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ reflection->SetUInt32(new_entry, val_des, map_val.GetUInt32Value());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ reflection->SetBool(new_entry, val_des, map_val.GetBoolValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ reflection->SetDouble(new_entry, val_des, map_val.GetDoubleValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ reflection->SetFloat(new_entry, val_des, map_val.GetFloatValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ reflection->SetEnumValue(new_entry, val_des, map_val.GetEnumValue());
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ const Message& message = map_val.GetMessageValue();
+ reflection->MutableMessage(new_entry, val_des)->CopyFrom(message);
+ break;
+ }
+ }
+ }
+}
+
+void DynamicMapField::SyncMapWithRepeatedFieldNoLock() const {
+ Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
+ const Reflection* reflection = default_entry_->GetReflection();
+ const FieldDescriptor* key_des =
+ default_entry_->GetDescriptor()->FindFieldByName("key");
+ const FieldDescriptor* val_des =
+ default_entry_->GetDescriptor()->FindFieldByName("value");
+ // DynamicMapField owns map values. Need to delete them before clearing
+ // the map.
+ for (typename Map<MapKey, MapValueRef>::iterator iter = map->begin();
+ iter != map->end(); ++iter) {
+ iter->second.DeleteData();
+ }
+ map->clear();
+ for (typename RepeatedPtrField<Message>::iterator it =
+ MapFieldBase::repeated_field_->begin();
+ it != MapFieldBase::repeated_field_->end(); ++it) {
+ MapKey map_key;
+ switch (key_des->cpp_type()) {
+ case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
+ map_key.SetStringValue(reflection->GetString(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
+ map_key.SetInt64Value(reflection->GetInt64(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
+ map_key.SetInt32Value(reflection->GetInt32(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
+ map_key.SetUInt64Value(reflection->GetUInt64(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
+ map_key.SetUInt32Value(reflection->GetUInt32(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
+ map_key.SetBoolValue(reflection->GetBool(*it, key_des));
+ break;
+ case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
+ case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ break;
+ }
+ MapValueRef& map_val = (*map)[map_key];
+ map_val.SetType(val_des->cpp_type());
+ switch (val_des->cpp_type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE, METHOD) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ TYPE * value = new TYPE; \
+ *value = reflection->Get##METHOD(*it, val_des); \
+ map_val.SetValue(value); \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32, Int32);
+ HANDLE_TYPE(INT64, int64, Int64);
+ HANDLE_TYPE(UINT32, uint32, UInt32);
+ HANDLE_TYPE(UINT64, uint64, UInt64);
+ HANDLE_TYPE(DOUBLE, double, Double);
+ HANDLE_TYPE(FLOAT, float, Float);
+ HANDLE_TYPE(BOOL, bool, Bool);
+ HANDLE_TYPE(STRING, string, String);
+ HANDLE_TYPE(ENUM, int32, EnumValue);
+#undef HANDLE_TYPE
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ const Message& message = reflection->GetMessage(*it, val_des);
+ Message* value = message.New();
+ value->CopyFrom(message);
+ map_val.SetValue(value);
+ break;
+ }
+ }
+ }
+}
+
+int DynamicMapField::SpaceUsedExcludingSelfNoLock() const {
+ int size = 0;
+ if (MapFieldBase::repeated_field_ != NULL) {
+ size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
+ }
+ size += sizeof(map_);
+ int map_size = map_.size();
+ if (map_size) {
+ typename Map<MapKey, MapValueRef>::const_iterator it = map_.begin();
+ size += sizeof(it->first) * map_size;
+ size += sizeof(it->second) * map_size;
+ // If key is string, add the allocated space.
+ if (it->first.type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
+ size += sizeof(string) * map_size;
+ }
+ // Add the allocated space in MapValueRef.
+ switch (it->second.type()) {
+#define HANDLE_TYPE(CPPTYPE, TYPE) \
+ case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: { \
+ size += sizeof(TYPE) * map_size; \
+ break; \
+ }
+ HANDLE_TYPE(INT32, int32);
+ HANDLE_TYPE(INT64, int64);
+ HANDLE_TYPE(UINT32, uint32);
+ HANDLE_TYPE(UINT64, uint64);
+ HANDLE_TYPE(DOUBLE, double);
+ HANDLE_TYPE(FLOAT, float);
+ HANDLE_TYPE(BOOL, bool);
+ HANDLE_TYPE(STRING, string);
+ HANDLE_TYPE(ENUM, int32);
+#undef HANDLE_TYPE
+ case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
+ while (it != map_.end()) {
+ const Message& message = it->second.GetMessageValue();
+ size += message.GetReflection()->SpaceUsed(message);
+ ++it;
+ }
+ break;
+ }
+ }
+ }
+ return size;
+}
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 56d3d0f4..9130166b 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -32,6 +32,7 @@
#define GOOGLE_PROTOBUF_MAP_FIELD_H__
#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/arena.h>
@@ -45,7 +46,8 @@
namespace google {
namespace protobuf {
-
+class DynamicMessage;
+class MapKey;
namespace internal {
class ContendedMapCleanTest;
@@ -83,6 +85,17 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
// Like above. Returns mutable pointer to the internal repeated field.
RepeatedPtrFieldBase* MutableRepeatedField();
+ // Pure virtual map APIs for Map Reflection.
+ virtual bool ContainsMapKey(const MapKey& map_key) const = 0;
+ virtual bool InsertMapValue(const MapKey& map_key, MapValueRef* val) = 0;
+ virtual bool DeleteMapValue(const MapKey& map_key) = 0;
+ virtual bool EqualIterator(const MapIterator& a,
+ const MapIterator& b) const = 0;
+ virtual void MapBegin(MapIterator* map_iter) const = 0;
+ virtual void MapEnd(MapIterator* map_iter) const = 0;
+ // Sync Map with repeated field and returns the size of map.
+ virtual int size() const = 0;
+
// Returns the number of bytes used by the repeated field, excluding
// sizeof(*this)
int SpaceUsedExcludingSelf() const;
@@ -141,6 +154,57 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
friend class ContendedMapCleanTest;
friend class GeneratedMessageReflection;
friend class MapFieldAccessor;
+ friend class ::google::protobuf::DynamicMessage;
+
+ // Virtual helper methods for MapIterator. MapIterator doesn't have the
+ // type helper for key and value. Call these help methods to deal with
+ // different types. Real helper methods are implemented in
+ // TypeDefinedMapFieldBase.
+ friend class ::google::protobuf::MapIterator;
+ // Allocate map<...>::iterator for MapIterator.
+ virtual void InitializeIterator(MapIterator* map_iter) const = 0;
+
+ // DeleteIterator() is called by the destructor of MapIterator only.
+ // It deletes map<...>::iterator for MapIterator.
+ virtual void DeleteIterator(MapIterator* map_iter) const = 0;
+
+ // Copy the map<...>::iterator from other_iterator to
+ // this_iterator.
+ virtual void CopyIterator(MapIterator* this_iterator,
+ const MapIterator& other_iterator) const = 0;
+
+ // IncreaseIterator() is called by operator++() of MapIterator only.
+ // It implements the ++ operator of MapIterator.
+ virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
+};
+
+// This class provides common Map Reflection implementations for generated
+// message and dynamic message.
+template<typename Key, typename T>
+class TypeDefinedMapFieldBase : public MapFieldBase {
+ public:
+ TypeDefinedMapFieldBase() {}
+ explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {}
+ ~TypeDefinedMapFieldBase() {}
+ void MapBegin(MapIterator* map_iter) const;
+ void MapEnd(MapIterator* map_iter) const;
+ bool EqualIterator(const MapIterator& a, const MapIterator& b) const;
+
+ virtual const Map<Key, T>& GetMap() const = 0;
+ virtual Map<Key, T>* MutableMap() = 0;
+
+ protected:
+ typename Map<Key, T>::const_iterator& InternalGetIterator(
+ const MapIterator* map_iter) const;
+
+ private:
+ void InitializeIterator(MapIterator* map_iter) const;
+ void DeleteIterator(MapIterator* map_iter) const;
+ void CopyIterator(MapIterator* this_iteratorm,
+ const MapIterator& that_iterator) const;
+ void IncreaseIterator(MapIterator* map_iter) const;
+
+ virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
};
// This class provides accesss to map field using generated api. It is used for
@@ -150,25 +214,13 @@ template <typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
WireFormatLite::FieldType kValueFieldType,
int default_enum_value = 0>
-class MapField : public MapFieldBase,
+class MapField : public TypeDefinedMapFieldBase<Key, T>,
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.
- 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;
+ // Provide utilities to parse/serialize key/value. Provide utilities to
+ // manipulate internal stored type.
+ typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+ typedef MapTypeHandler<kValueFieldType, T> ValueTypeHandler;
// Define message type for internal repeated field.
typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
@@ -183,8 +235,8 @@ class MapField : public MapFieldBase,
// 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 = ValueWireHandler::kIsEnum;
+ // SyncMapWithRepeatedFieldNoLock.
+ static const bool kIsValueEnum = ValueTypeHandler::kIsEnum;
typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
public:
@@ -197,6 +249,11 @@ class MapField : public MapFieldBase,
MapField(Arena* arena, const Message* default_entry);
~MapField();
+ // Implement MapFieldBase
+ bool ContainsMapKey(const MapKey& map_key) const;
+ bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
+ bool DeleteMapValue(const MapKey& map_key);
+
// Accessors
const Map<Key, T>& GetMap() const;
Map<Key, T>* MutableMap();
@@ -230,12 +287,109 @@ class MapField : public MapFieldBase,
void SyncMapWithRepeatedFieldNoLock() const;
int SpaceUsedExcludingSelfNoLock() const;
+ void SetMapIteratorValue(MapIterator* map_iter) const;
+
mutable const EntryType* default_entry_;
friend class ::google::protobuf::Arena;
};
+class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
+ public:
+ explicit DynamicMapField(const Message* default_entry);
+ DynamicMapField(const Message* default_entry, Arena* arena);
+ ~DynamicMapField();
+
+ // Implement MapFieldBase
+ bool ContainsMapKey(const MapKey& map_key) const;
+ bool InsertMapValue(const MapKey& map_key, MapValueRef* val);
+ bool DeleteMapValue(const MapKey& map_key);
+
+ const Map<MapKey, MapValueRef>& GetMap() const;
+ Map<MapKey, MapValueRef>* MutableMap();
+
+ int size() const;
+
+ private:
+ Map<MapKey, MapValueRef> map_;
+ const Message* default_entry_;
+
+ // Implements MapFieldBase
+ void SyncRepeatedFieldWithMapNoLock() const;
+ void SyncMapWithRepeatedFieldNoLock() const;
+ int SpaceUsedExcludingSelfNoLock() const;
+ void SetMapIteratorValue(MapIterator* map_iter) const;
+};
+
} // namespace internal
+
+class LIBPROTOBUF_EXPORT MapIterator {
+ public:
+ MapIterator(Message* message, const FieldDescriptor* field) {
+ const Reflection* reflection = message->GetReflection();
+ map_ = reflection->MapData(message, field);
+ key_.SetType(field->message_type()->FindFieldByName("key")->cpp_type());
+ value_.SetType(field->message_type()->FindFieldByName("value")->cpp_type());
+ map_->InitializeIterator(this);
+ }
+ MapIterator(const MapIterator& other) {
+ map_ = other.map_;
+ map_->InitializeIterator(this);
+ map_->CopyIterator(this, other);
+ }
+ ~MapIterator() {
+ map_->DeleteIterator(this);
+ }
+ friend bool operator==(const MapIterator& a, const MapIterator& b) {
+ return a.map_->EqualIterator(a, b);
+ }
+ friend bool operator!=(const MapIterator& a, const MapIterator& b) {
+ return !a.map_->EqualIterator(a, b);
+ }
+ MapIterator& operator++() {
+ map_->IncreaseIterator(this);
+ return *this;
+ }
+ MapIterator operator++(int) {
+ // iter_ is copied from Map<...>::iterator, no need to
+ // copy from its self again. Use the same implementation
+ // with operator++()
+ map_->IncreaseIterator(this);
+ return *this;
+ }
+ const MapKey& GetKey() {
+ return key_;
+ }
+ const MapValueRef& GetValueRef() {
+ return value_;
+ }
+ MapValueRef* MutableValueRef() {
+ map_->SetMapDirty();
+ return &value_;
+ }
+
+ private:
+ template <typename Key, typename T>
+ friend class internal::TypeDefinedMapFieldBase;
+ friend class internal::DynamicMapField;
+ template <typename Key, typename T,
+ internal::WireFormatLite::FieldType kKeyFieldType,
+ internal::WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+ friend class internal::MapField;
+
+ // reinterpret_cast from heap-allocated Map<...>::iterator*. MapIterator owns
+ // the iterator. It is allocated by MapField<...>::InitializeIterator() called
+ // in constructor and deleted by MapField<...>::DeleteIterator() called in
+ // destructor.
+ void* iter_;
+ // Point to a MapField to call helper methods implemented in MapField.
+ // MapIterator does not own this object.
+ internal::MapFieldBase* map_;
+ MapKey key_;
+ MapValueRef value_;
+};
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 5b4305f9..1a4ce937 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -36,12 +36,128 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/map.h>
#include <google/protobuf/map_field.h>
#include <google/protobuf/map_type_handler.h>
namespace google {
namespace protobuf {
namespace internal {
+// UnwrapMapKey template
+template<typename T>
+T UnwrapMapKey(const MapKey& map_key);
+template<>
+inline int32 UnwrapMapKey<int32>(const MapKey& map_key) {
+ return map_key.GetInt32Value();
+}
+template<>
+inline uint32 UnwrapMapKey<uint32>(const MapKey& map_key) {
+ return map_key.GetUInt32Value();
+}
+template<>
+inline int64 UnwrapMapKey<int64>(const MapKey& map_key) {
+ return map_key.GetInt64Value();
+}
+template<>
+inline uint64 UnwrapMapKey<uint64>(const MapKey& map_key) {
+ return map_key.GetUInt64Value();
+}
+template<>
+inline bool UnwrapMapKey<bool>(const MapKey& map_key) {
+ return map_key.GetBoolValue();
+}
+template<>
+inline string UnwrapMapKey<string>(const MapKey& map_key) {
+ return map_key.GetStringValue();
+}
+
+// SetMapKey template
+template<typename T>
+inline void SetMapKey(MapKey* map_key, const T& value);
+template<>
+inline void SetMapKey<int32>(MapKey* map_key, const int32& value) {
+ map_key->SetInt32Value(value);
+}
+template<>
+inline void SetMapKey<uint32>(MapKey* map_key, const uint32& value) {
+ map_key->SetUInt32Value(value);
+}
+template<>
+inline void SetMapKey<int64>(MapKey* map_key, const int64& value) {
+ map_key->SetInt64Value(value);
+}
+template<>
+inline void SetMapKey<uint64>(MapKey* map_key, const uint64& value) {
+ map_key->SetUInt64Value(value);
+}
+template<>
+inline void SetMapKey<bool>(MapKey* map_key, const bool& value) {
+ map_key->SetBoolValue(value);
+}
+template<>
+inline void SetMapKey<string>(MapKey* map_key, const string& value) {
+ map_key->SetStringValue(value);
+}
+
+// ------------------------TypeDefinedMapFieldBase---------------
+template <typename Key, typename T>
+typename Map<Key, T>::const_iterator&
+TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(
+ const MapIterator* map_iter) const {
+ return *reinterpret_cast<typename Map<Key, T>::const_iterator *>(
+ map_iter->iter_);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::MapBegin(MapIterator* map_iter) const {
+ InternalGetIterator(map_iter) = GetMap().begin();
+ SetMapIteratorValue(map_iter);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::MapEnd(MapIterator* map_iter) const {
+ InternalGetIterator(map_iter) = GetMap().end();
+}
+
+template <typename Key, typename T>
+bool TypeDefinedMapFieldBase<Key, T>::EqualIterator(const MapIterator& a,
+ const MapIterator& b)
+ const {
+ return InternalGetIterator(&a) == InternalGetIterator(&b);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::IncreaseIterator(MapIterator* map_iter)
+ const {
+ ++InternalGetIterator(map_iter);
+ SetMapIteratorValue(map_iter);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::InitializeIterator(
+ MapIterator* map_iter) const {
+ map_iter->iter_ = new typename Map<Key, T>::const_iterator;
+ GOOGLE_CHECK(map_iter->iter_ != NULL);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::DeleteIterator(MapIterator* map_iter)
+ const {
+ delete reinterpret_cast<typename Map<Key, T>::const_iterator *>(
+ map_iter->iter_);
+}
+
+template <typename Key, typename T>
+void TypeDefinedMapFieldBase<Key, T>::CopyIterator(
+ MapIterator* this_iter,
+ const MapIterator& that_iter) const {
+ InternalGetIterator(this_iter) = InternalGetIterator(&that_iter);
+ this_iter->key_.SetType(that_iter.key_.type());
+ this_iter->value_.SetType(that_iter.value_.type());
+ SetMapIteratorValue(this_iter);
+}
+
+// ----------------------------------------------------------------------
template <typename Key, typename T,
WireFormatLite::FieldType kKeyFieldType,
@@ -56,7 +172,7 @@ template <typename Key, typename T,
int default_enum_value>
MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
Arena* arena)
- : MapFieldBase(arena),
+ : TypeDefinedMapFieldBase<Key, T>(arena),
MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
arena),
default_entry_(NULL) {}
@@ -75,7 +191,7 @@ template <typename Key, typename T,
int default_enum_value>
MapField<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>::MapField(
Arena* arena, const Message* default_entry)
- : MapFieldBase(arena),
+ : TypeDefinedMapFieldBase<Key, T>(arena),
MapFieldLite<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>(
arena),
default_entry_(down_cast<const EntryType*>(default_entry)) {}
@@ -94,7 +210,7 @@ template <typename Key, typename T,
int
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::size() const {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
return MapFieldLiteType::GetInternalMap().size();
}
@@ -105,9 +221,65 @@ template <typename Key, typename T,
void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::Clear() {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
MapFieldLiteType::MutableInternalMap()->clear();
- SetMapDirty();
+ MapFieldBase::SetMapDirty();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+void MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::SetMapIteratorValue(
+ MapIterator* map_iter) const {
+ const Map<Key, T>& map = GetMap();
+ typename Map<Key, T>::const_iterator iter =
+ TypeDefinedMapFieldBase<Key, T>::InternalGetIterator(map_iter);
+ if (iter == map.end()) return;
+ SetMapKey(&map_iter->key_, iter->first);
+ map_iter->value_.SetValue(&iter->second);
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::ContainsMapKey(
+ const MapKey& map_key) const {
+ const Map<Key, T>& map = GetMap();
+ const Key& key = UnwrapMapKey<Key>(map_key);
+ typename Map<Key, T>::const_iterator iter = map.find(key);
+ return iter != map.end();
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::InsertMapValue(const MapKey& map_key,
+ MapValueRef* val) {
+ Map<Key, T>* map = MutableMap();
+ bool result = false;
+ const Key& key = UnwrapMapKey<Key>(map_key);
+ if (map->end() == map->find(key)) {
+ result = true;
+ }
+ val->SetValue(&((*map)[key]));
+ return result;
+}
+
+template <typename Key, typename T,
+ WireFormatLite::FieldType kKeyFieldType,
+ WireFormatLite::FieldType kValueFieldType,
+ int default_enum_value>
+bool MapField<Key, T, kKeyFieldType, kValueFieldType,
+ default_enum_value>::DeleteMapValue(
+ const MapKey& map_key) {
+ const Key& key = UnwrapMapKey<Key>(map_key);
+ return MutableMap()->erase(key);
}
template <typename Key, typename T,
@@ -117,7 +289,7 @@ template <typename Key, typename T,
const Map<Key, T>&
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::GetMap() const {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
return MapFieldLiteType::GetInternalMap();
}
@@ -128,9 +300,9 @@ template <typename Key, typename T,
Map<Key, T>*
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::MutableMap() {
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
Map<Key, T>* result = MapFieldLiteType::MutableInternalMap();
- SetMapDirty();
+ MapFieldBase::SetMapDirty();
return result;
}
@@ -143,10 +315,10 @@ MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::MergeFrom(
const MapFieldLiteType& other) {
const MapField& down_other = down_cast<const MapField&>(other);
- SyncMapWithRepeatedField();
+ MapFieldBase::SyncMapWithRepeatedField();
down_other.SyncMapWithRepeatedField();
MapFieldLiteType::MergeFrom(other);
- SetMapDirty();
+ MapFieldBase::SetMapDirty();
}
template <typename Key, typename T,
@@ -158,9 +330,9 @@ 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_);
+ std::swap(MapFieldBase::repeated_field_, down_other->repeated_field_);
MapFieldLiteType::Swap(other);
- std::swap(state_, down_other->state_);
+ std::swap(MapFieldBase::state_, down_other->state_);
}
template <typename Key, typename T,
@@ -171,7 +343,7 @@ void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SetEntryDescriptor(
const Descriptor** descriptor) {
- entry_descriptor_ = descriptor;
+ MapFieldBase::entry_descriptor_ = descriptor;
}
template <typename Key, typename T,
@@ -181,7 +353,7 @@ template <typename Key, typename T,
void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SetAssignDescriptorCallback(void (*callback)()) {
- assign_descriptor_callback_ = callback;
+ MapFieldBase::assign_descriptor_callback_ = callback;
}
template <typename Key, typename T,
@@ -211,17 +383,19 @@ template <typename Key, typename T,
void
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SyncRepeatedFieldWithMapNoLock() const {
- if (repeated_field_ == NULL) {
+ if (MapFieldBase::repeated_field_ == NULL) {
if (MapFieldBase::arena_ == NULL) {
- repeated_field_ = new RepeatedPtrField<Message>();
+ MapFieldBase::repeated_field_ = new RepeatedPtrField<Message>();
} else {
- repeated_field_ = Arena::CreateMessage<RepeatedPtrField<Message> >(
- MapFieldBase::arena_);
+ MapFieldBase::repeated_field_ =
+ Arena::CreateMessage<RepeatedPtrField<Message> >(
+ MapFieldBase::arena_);
}
}
const Map<Key, T>& map = GetInternalMap();
RepeatedPtrField<EntryType>* repeated_field =
- reinterpret_cast<RepeatedPtrField<EntryType>*>(repeated_field_);
+ reinterpret_cast<RepeatedPtrField<EntryType>*>(
+ MapFieldBase::repeated_field_);
repeated_field->Clear();
@@ -246,7 +420,9 @@ 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_);
+ reinterpret_cast<RepeatedPtrField<EntryType>*>(
+ MapFieldBase::repeated_field_);
+ GOOGLE_CHECK(MapFieldBase::repeated_field_ != NULL);
map->clear();
for (typename RepeatedPtrField<EntryType>::iterator it =
repeated_field->begin(); it != repeated_field->end(); ++it) {
@@ -267,15 +443,15 @@ int
MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::SpaceUsedExcludingSelfNoLock() const {
int size = 0;
- if (repeated_field_ != NULL) {
- size += repeated_field_->SpaceUsedExcludingSelf();
+ if (MapFieldBase::repeated_field_ != NULL) {
+ size += MapFieldBase::repeated_field_->SpaceUsedExcludingSelf();
}
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) {
- size += KeyHandler::SpaceUsedInMap(it->first);
- size += ValHandler::SpaceUsedInMap(it->second);
+ size += KeyTypeHandler::SpaceUsedInMap(it->first);
+ size += ValueTypeHandler::SpaceUsedInMap(it->second);
}
return size;
}
@@ -289,10 +465,11 @@ MapField<Key, T, kKeyFieldType, kValueFieldType,
default_enum_value>::InitDefaultEntryOnce()
const {
if (default_entry_ == NULL) {
- InitMetadataOnce();
- GOOGLE_CHECK(*entry_descriptor_ != NULL);
+ MapFieldBase::InitMetadataOnce();
+ GOOGLE_CHECK(*MapFieldBase::entry_descriptor_ != NULL);
default_entry_ = down_cast<const EntryType*>(
- MessageFactory::generated_factory()->GetPrototype(*entry_descriptor_));
+ MessageFactory::generated_factory()->GetPrototype(
+ *MapFieldBase::entry_descriptor_));
}
}
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index e3a64079..2ff1d6bb 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/map.h>
@@ -74,6 +75,28 @@ class MapFieldBaseStub : public MapFieldBase {
bool IsRepeatedClean() { return state_ != 1; }
void SetMapDirty() { state_ = 0; }
void SetRepeatedDirty() { state_ = 1; }
+ bool ContainsMapKey(const MapKey& map_key) const {
+ return false;
+ }
+ bool InsertMapValue(const MapKey& map_key, MapValueRef* val) {
+ return false;
+ }
+ bool DeleteMapValue(const MapKey& map_key) {
+ return false;
+ }
+ bool EqualIterator(const MapIterator& a, const MapIterator& b) const {
+ return false;
+ }
+ int size() const { return 0; }
+ void MapBegin(MapIterator* map_iter) const {}
+ void MapEnd(MapIterator* map_iter) const {}
+ void InitializeIterator(MapIterator* map_iter) const {}
+ void DeleteIterator(MapIterator* map_iter) const {}
+ void CopyIterator(MapIterator* this_iterator,
+ const MapIterator& other_iterator) const {}
+ void IncreaseIterator(MapIterator* map_iter) const {}
+ void SetDefaultMessageEntry(const Message* message) const {}
+ const Message* GetDefaultMessageEntry() const { return NULL; }
};
class MapFieldBasePrimitiveTest : public ::testing::Test {
diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto
index c69e8d94..0592dd7a 100644
--- a/src/google/protobuf/map_lite_unittest.proto
+++ b/src/google/protobuf/map_lite_unittest.proto
@@ -34,6 +34,7 @@ option cc_enable_arenas = true;
option optimize_for = LITE_RUNTIME;
import "google/protobuf/unittest_lite.proto";
+import "google/protobuf/unittest_no_arena_lite.proto";
package protobuf_unittest;
@@ -72,8 +73,12 @@ message TestArenaMapLite {
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;
+ map<string , string > map_string_string = 14;
+ map<int32 , bytes > map_int32_bytes = 15;
+ map<int32 , MapEnumLite> map_int32_enum = 16;
+ map<int32 , ForeignMessageArenaLite> map_int32_foreign_message = 17;
+ map<int32, .protobuf_unittest_no_arena.ForeignMessageLite>
+ map_int32_foreign_message_no_arena = 18;
}
// Test embeded message with required fields
@@ -81,10 +86,6 @@ 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;
@@ -112,10 +113,6 @@ enum Proto2MapEnumPlusExtraLite {
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;
diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto
index 3d4af28e..6f9d6165 100644
--- a/src/google/protobuf/map_proto2_unittest.proto
+++ b/src/google/protobuf/map_proto2_unittest.proto
@@ -49,10 +49,6 @@ enum Proto2MapEnumPlusExtra {
E_PROTO2_MAP_ENUM_EXTRA = 3;
}
-enum Proto2MapEnumStartWithNonZero {
- PROTO2_NON_ZERO_MAP_ENUM_FOO = 1;
-}
-
message TestEnumMap {
map<int32, Proto2MapEnum> known_map_field = 101;
map<int32, Proto2MapEnum> unknown_map_field = 102;
@@ -62,7 +58,3 @@ message TestEnumMapPlusExtra {
map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
}
-
-message TestEnumStartWithNonZeroMap {
- map<int32, Proto2MapEnumStartWithNonZero> map_field = 101;
-}
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index d62ec85f..a74801d9 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -36,7 +36,9 @@
#include <sstream>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/arena_test_util.h>
@@ -70,6 +72,7 @@ namespace google {
using google::protobuf::unittest::ForeignMessage;
using google::protobuf::unittest::TestAllTypes;
using google::protobuf::unittest::TestMap;
+using google::protobuf::unittest::TestRecursiveMapMessage;
namespace protobuf {
namespace internal {
@@ -200,6 +203,21 @@ TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
EXPECT_DEATH(const_map_.at(0), "");
}
+TEST_F(MapImplTest, UsageErrors) {
+ MapKey key;
+ key.SetInt64Value(1);
+ EXPECT_DEATH(key.GetUInt64Value(),
+ "Protocol Buffer map usage error:\n"
+ "MapKey::GetUInt64Value type does not match\n"
+ " Expected : uint64\n"
+ " Actual : int64");
+
+ MapValueRef value;
+ EXPECT_DEATH(value.SetFloatValue(0.1),
+ "Protocol Buffer map usage error:\n"
+ "MapValueRef::type MapValueRef is not initialized.");
+}
+
#endif // PROTOBUF_HAS_DEATH_TEST
TEST_F(MapImplTest, CountNonExist) {
@@ -475,6 +493,23 @@ TEST_F(MapImplTest, CopyConstructor) {
EXPECT_EQ(value2, other.at(key2));
}
+TEST_F(MapImplTest, IterConstructor) {
+ int32 key1 = 0;
+ int32 key2 = 1;
+ int32 value1 = 100;
+ int32 value2 = 101;
+
+ std::map<int32, int32> map;
+ map[key1] = value1;
+ map[key2] = value2;
+
+ Map<int32, int32> new_map(map.begin(), map.end());
+
+ EXPECT_EQ(2, new_map.size());
+ EXPECT_EQ(value1, new_map.at(key1));
+ EXPECT_EQ(value2, new_map.at(key2));
+}
+
TEST_F(MapImplTest, Assigner) {
int32 key1 = 0;
int32 key2 = 1;
@@ -1140,6 +1175,19 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
mmf_int32_foreign_message.Add(*entry_int32_foreign_message);
EXPECT_EQ(1234, message.map_int32_foreign_message().at(4321).c());
+ // Test Reflection::AddAllocatedMessage
+ Message* free_entry_string_string = MessageFactory::generated_factory()
+ ->GetPrototype(fd_map_string_string->message_type())
+ ->New();
+ entry_string_string->GetReflection()->SetString(
+ free_entry_string_string,
+ fd_map_string_string->message_type()->field(0), "4321");
+ entry_string_string->GetReflection()->SetString(
+ free_entry_string_string, fd_map_string_string->message_type()->field(1),
+ "1234");
+ refl->AddAllocatedMessage(&message, fd_map_string_string,
+ free_entry_string_string);
+
// Test MutableRepeatedFieldRef::RemoveLast()
mmf_int32_int32.RemoveLast();
mmf_int32_double.RemoveLast();
@@ -1147,7 +1195,7 @@ TEST_F(MapFieldReflectionTest, RepeatedFieldRefForRegularFields) {
mmf_int32_foreign_message.RemoveLast();
EXPECT_EQ(10, message.map_int32_int32().size());
EXPECT_EQ(10, message.map_int32_double().size());
- EXPECT_EQ(10, message.map_string_string().size());
+ EXPECT_EQ(11, message.map_string_string().size());
EXPECT_EQ(10, message.map_int32_foreign_message().size());
// Test MutableRepeatedFieldRef::SwapElements()
@@ -1398,9 +1446,9 @@ TEST(GeneratedMapFieldTest, SetMapFieldsInitialized) {
}
TEST(GeneratedMapFieldTest, Proto2SetMapFieldsInitialized) {
- unittest::TestEnumStartWithNonZeroMap message;
- EXPECT_EQ(unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO,
- (*message.mutable_map_field())[0]);
+ unittest::TestEnumMap message;
+ EXPECT_EQ(unittest::PROTO2_MAP_ENUM_FOO,
+ (*message.mutable_known_map_field())[0]);
}
TEST(GeneratedMapFieldTest, Clear) {
@@ -1526,12 +1574,28 @@ TEST(GeneratedMapFieldTest, CopyFromDynamicMessage) {
google::protobuf::scoped_ptr<Message> message1;
message1.reset(
factory.GetPrototype(unittest::TestMap::descriptor())->New());
-
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.SetMapFieldsViaReflection(message1.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+ message2.CopyFrom(*message1);
+ MapTestUtil::ExpectMapFieldsSet(message2);
+}
+
+TEST(GeneratedMapFieldTest, CopyFromDynamicMessageMapReflection) {
+ unittest::TestMap message2;
+ // Construct a new version of the dynamic message via the factory.
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<Message> message1;
+ message1.reset(
+ factory.GetPrototype(unittest::TestMap::descriptor())->New());
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ reflection_tester.SetMapFieldsViaMapReflection(message1.get());
+ reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
message2.CopyFrom(*message1);
MapTestUtil::ExpectMapFieldsSet(message2);
}
@@ -1547,12 +1611,43 @@ TEST(GeneratedMapFieldTest, DynamicMessageCopyFrom) {
message1.reset(
factory.GetPrototype(unittest::TestMap::descriptor())->New());
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ message1->MergeFrom(message2);
+ reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
+}
+
+TEST(GeneratedMapFieldTest, DynamicMessageCopyFromMapReflection) {
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
+ unittest::TestMap message2;
+ reflection_tester.SetMapFieldsViaMapReflection(&message2);
+
+ // Construct a dynamic message via the factory.
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<Message> message1;
+ message1.reset(
+ factory.GetPrototype(unittest::TestMap::descriptor())->New());
+
message1->MergeFrom(message2);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message1.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message1);
}
+TEST(GeneratedMapFieldTest, SyncDynamicMapWithRepeatedField) {
+ // Construct a dynamic message via the factory.
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ DynamicMessageFactory factory;
+ google::protobuf::scoped_ptr<Message> message;
+ message.reset(
+ factory.GetPrototype(unittest::TestMap::descriptor())->New());
+ reflection_tester.SetMapFieldsViaReflection(message.get());
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(message.get());
+ reflection_tester.ExpectMapFieldsSetViaReflection(*message);
+}
+
#endif // !PROTOBUF_TEST_NO_DESCRIPTORS
TEST(GeneratedMapFieldTest, NonEmptyMergeFrom) {
@@ -1779,7 +1874,7 @@ TEST(GeneratedMapFieldTest, IsInitialized) {
TEST(GeneratedMapFieldReflectionTest, SpaceUsed) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.SetMapFieldsViaReflection(&message);
@@ -1790,11 +1885,12 @@ TEST(GeneratedMapFieldReflectionTest, Accessors) {
// Set every field to a unique value then go back and check all those
// values.
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.SetMapFieldsViaReflection(&message);
MapTestUtil::ExpectMapFieldsSet(message);
reflection_tester.ExpectMapFieldsSetViaReflection(message);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message);
reflection_tester.ModifyMapFieldsViaReflection(&message);
MapTestUtil::ExpectMapFieldsModified(message);
@@ -1848,15 +1944,16 @@ TEST(GeneratedMapFieldReflectionTest, ClearField) {
MapTestUtil::SetMapFields(&message);
MapTestUtil::ExpectMapFieldsSet(message);
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.ClearMapFieldsViaReflection(&message);
- MapTestUtil::ExpectClear(message);
+ reflection_tester.ExpectClearViaReflection(message);
+ reflection_tester.ExpectClearViaReflectionIterator(&message);
}
TEST(GeneratedMapFieldReflectionTest, RemoveLast) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
MapTestUtil::SetMapFields(&message);
@@ -1875,7 +1972,7 @@ TEST(GeneratedMapFieldReflectionTest, RemoveLast) {
TEST(GeneratedMapFieldReflectionTest, ReleaseLast) {
unittest::TestMap message;
const Descriptor* descriptor = message.GetDescriptor();
- MapTestUtil::MapReflectionTester reflection_tester(descriptor);
+ MapReflectionTester reflection_tester(descriptor);
MapTestUtil::SetMapFields(&message);
@@ -1904,7 +2001,7 @@ TEST(GeneratedMapFieldReflectionTest, ReleaseLast) {
TEST(GeneratedMapFieldReflectionTest, SwapElements) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
MapTestUtil::SetMapFields(&message);
@@ -1944,7 +2041,7 @@ TEST(GeneratedMapFieldReflectionTest, SwapElements) {
TEST(GeneratedMapFieldReflectionTest, MutableUnknownFields) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
}
@@ -2000,24 +2097,35 @@ TEST(GeneratedMapFieldReflectionTest, MergeFromClearMapEntry) {
TEST(GeneratedMapFieldReflectionTest, MapEntryClear) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester reflection_tester(
+ MapReflectionTester reflection_tester(
unittest::TestMap::descriptor());
reflection_tester.MutableUnknownFieldsOfMapFieldsViaReflection(&message);
}
TEST(GeneratedMapFieldReflectionTest, Proto2MapEntryClear) {
- unittest::TestEnumStartWithNonZeroMap message;
+ unittest::TestEnumMap message;
const Descriptor* descriptor = message.GetDescriptor();
const FieldDescriptor* field_descriptor =
- descriptor->FindFieldByName("map_field");
+ descriptor->FindFieldByName("known_map_field");
const FieldDescriptor* value_descriptor =
field_descriptor->message_type()->FindFieldByName("value");
Message* sub_message =
message.GetReflection()->AddMessage(&message, field_descriptor);
- EXPECT_EQ(1, sub_message->GetReflection()->GetEnumValue(*sub_message,
+ EXPECT_EQ(0, sub_message->GetReflection()->GetEnumValue(*sub_message,
value_descriptor));
}
+// Map Reflection API Test =========================================
+
+TEST(GeneratedMapFieldReflectionTest, SetViaMapReflection) {
+ unittest::TestMap message;
+ MapReflectionTester reflection_tester(
+ unittest::TestMap::descriptor());
+ reflection_tester.SetMapFieldsViaMapReflection(&message);
+ reflection_tester.ExpectMapFieldsSetViaReflection(message);
+ reflection_tester.ExpectMapFieldsSetViaReflectionIterator(&message);
+}
+
// Dynamic Message Test =============================================
class MapFieldInDynamicMessageTest : public testing::Test {
@@ -2025,6 +2133,7 @@ class MapFieldInDynamicMessageTest : public testing::Test {
const DescriptorPool* pool_;
DynamicMessageFactory factory_;
const Descriptor* map_descriptor_;
+ const Descriptor* recursive_map_descriptor_;
const Message* map_prototype_;
MapFieldInDynamicMessageTest()
@@ -2033,7 +2142,10 @@ class MapFieldInDynamicMessageTest : public testing::Test {
virtual void SetUp() {
map_descriptor_ =
pool_->FindMessageTypeByName("protobuf_unittest.TestMap");
+ recursive_map_descriptor_ =
+ pool_->FindMessageTypeByName("protobuf_unittest.TestRecursiveMapMessage");
ASSERT_TRUE(map_descriptor_ != NULL);
+ ASSERT_TRUE(recursive_map_descriptor_ != NULL);
map_prototype_ = factory_.GetPrototype(map_descriptor_);
}
};
@@ -2043,19 +2155,19 @@ TEST_F(MapFieldInDynamicMessageTest, MapIndependentOffsets) {
// one to a unique value then checking that they all still have those
// unique values (i.e. they don't stomp each other).
scoped_ptr<Message> message(map_prototype_->New());
- MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
+ MapReflectionTester reflection_tester(map_descriptor_);
reflection_tester.SetMapFieldsViaReflection(message.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message);
}
-TEST_F(MapFieldInDynamicMessageTest, Map) {
+TEST_F(MapFieldInDynamicMessageTest, DynamicMapReflection) {
// Check that map fields work properly.
scoped_ptr<Message> message(map_prototype_->New());
// Check set functions.
- MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
- reflection_tester.SetMapFieldsViaReflection(message.get());
+ MapReflectionTester reflection_tester(map_descriptor_);
+ reflection_tester.SetMapFieldsViaMapReflection(message.get());
reflection_tester.ExpectMapFieldsSetViaReflection(*message);
}
@@ -2066,7 +2178,7 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
// to test very much here. Just make sure it appears to be working.
scoped_ptr<Message> message(map_prototype_->New());
- MapTestUtil::MapReflectionTester reflection_tester(map_descriptor_);
+ MapReflectionTester reflection_tester(map_descriptor_);
int initial_space_used = message->SpaceUsed();
@@ -2074,6 +2186,15 @@ TEST_F(MapFieldInDynamicMessageTest, MapSpaceUsed) {
EXPECT_LT(initial_space_used, message->SpaceUsed());
}
+TEST_F(MapFieldInDynamicMessageTest, RecursiveMap) {
+ TestRecursiveMapMessage from;
+ (*from.mutable_a())[0];
+ string data = from.SerializeAsString();
+ google::protobuf::scoped_ptr<Message> to(
+ factory_.GetPrototype(recursive_map_descriptor_)->New());
+ ASSERT_TRUE(to->ParseFromString(data));
+}
+
// ReflectionOps Test ===============================================
TEST(ReflectionOpsForMapFieldTest, MapSanityCheck) {
@@ -2260,7 +2381,7 @@ TEST(TextFormatMapTest, SerializeAndParse) {
TEST(TextFormatMapTest, Sorted) {
unittest::TestMap message;
- MapTestUtil::MapReflectionTester tester(message.GetDescriptor());
+ MapReflectionTester tester(message.GetDescriptor());
tester.SetMapFieldsViaReflection(&message);
string expected_text;
@@ -2292,7 +2413,8 @@ TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) {
data.reserve(128 * 1024);
{
- NoHeapChecker no_heap;
+ // TODO(teboring): Enable no heap check when ArenaStringPtr is used in map.
+ // NoHeapChecker no_heap;
unittest::TestArenaMap* from =
Arena::CreateMessage<unittest::TestArenaMap>(&arena);
@@ -2326,6 +2448,22 @@ TEST(ArenaTest, RelfectionInTextFormat) {
MapTestUtil::ExpectArenaMapFieldsSet(*to);
}
+// Make sure the memory allocated for string in map is deallocated.
+TEST(ArenaTest, StringMapNoLeak) {
+ Arena arena;
+ unittest::TestArenaMap* message =
+ Arena::CreateMessage<unittest::TestArenaMap>(&arena);
+ string data;
+ // String with length less than 16 will not be allocated from heap.
+ int original_capacity = data.capacity();
+ while (data.capacity() <= original_capacity) {
+ data.append("a");
+ }
+ (*message->mutable_map_string_string())[data] = data;
+ // We rely on heap checkers to detect memory leak for us.
+ ASSERT_FALSE(message == NULL);
+}
+
} // 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 1713e373..ae094647 100644
--- a/src/google/protobuf/map_test_util.cc
+++ b/src/google/protobuf/map_test_util.cc
@@ -209,7 +209,7 @@ std::vector<const Message*> MapTestUtil::GetMapEntriesFromRelease(
return result;
}
-MapTestUtil::MapReflectionTester::MapReflectionTester(
+MapReflectionTester::MapReflectionTester(
const Descriptor* base_descriptor)
: base_descriptor_(base_descriptor) {
const DescriptorPool* pool = base_descriptor->file()->pool();
@@ -329,14 +329,14 @@ MapTestUtil::MapReflectionTester::MapReflectionTester(
}
// Shorthand to get a FieldDescriptor for a field of unittest::TestMap.
-const FieldDescriptor* MapTestUtil::MapReflectionTester::F(const string& name) {
+const FieldDescriptor* MapReflectionTester::F(const string& name) {
const FieldDescriptor* result = NULL;
result = base_descriptor_->FindFieldByName(name);
GOOGLE_CHECK(result != NULL);
return result;
}
-void MapTestUtil::MapReflectionTester::SetMapFieldsViaReflection(
+void MapReflectionTester::SetMapFieldsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
Message* sub_message = NULL;
@@ -555,7 +555,196 @@ void MapTestUtil::MapReflectionTester::SetMapFieldsViaReflection(
SetInt32(sub_foreign_message, foreign_c_, 1);
}
-void MapTestUtil::MapReflectionTester::ClearMapFieldsViaReflection(
+void MapReflectionTester::SetMapFieldsViaMapReflection(
+ Message* message) {
+ const Reflection* reflection = message->GetReflection();
+
+ Message* sub_foreign_message = NULL;
+ MapValueRef map_val;
+
+ // Add first element.
+ MapKey map_key;
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+ map_val.SetInt32Value(0);
+
+ map_key.SetInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+ map_val.SetInt64Value(0);
+
+ map_key.SetUInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_uint32_uint32"), map_key, &map_val));
+ map_val.SetUInt32Value(0);
+
+ map_key.SetUInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_uint64_uint64"), map_key, &map_val));
+ map_val.SetUInt64Value(0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sint32_sint32"), map_key, &map_val));
+ map_val.SetInt32Value(0);
+
+ map_key.SetInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sint64_sint64"), map_key, &map_val));
+ map_val.SetInt64Value(0);
+
+ map_key.SetUInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_fixed32_fixed32"), map_key, &map_val));
+ map_val.SetUInt32Value(0);
+
+ map_key.SetUInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_fixed64_fixed64"), map_key, &map_val));
+ map_val.SetUInt64Value(0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed32_sfixed32"), map_key, &map_val));
+ map_val.SetInt32Value(0);
+
+ map_key.SetInt64Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed64_sfixed64"), map_key, &map_val));
+ map_val.SetInt64Value(0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_float"), map_key, &map_val));
+ map_val.SetFloatValue(0.0);
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_double"), map_key, &map_val));
+ map_val.SetDoubleValue(0.0);
+
+ map_key.SetBoolValue(false);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_bool_bool"), map_key, &map_val));
+ map_val.SetBoolValue(false);
+
+ map_key.SetStringValue("0");
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_string_string"), map_key, &map_val));
+ map_val.SetStringValue("0");
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_bytes"), map_key, &map_val));
+ map_val.SetStringValue("0");
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_enum"), map_key, &map_val));
+ map_val.SetEnumValue(map_enum_bar_->number());
+
+ map_key.SetInt32Value(0);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_foreign_message"), map_key, &map_val));
+ sub_foreign_message = map_val.MutableMessageValue();
+ sub_foreign_message->GetReflection()->SetInt32(
+ sub_foreign_message, foreign_c_, 0);
+
+ // Add second element
+ map_key.SetInt32Value(1);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+ map_val.SetInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+
+ map_key.SetInt64Value(1);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+ map_val.SetInt64Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+
+ map_key.SetUInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_uint32_uint32"), map_key, &map_val);
+ map_val.SetUInt32Value(1);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_uint64_uint64"), map_key, &map_val);
+ map_val.SetUInt64Value(1);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint32_sint32"), map_key, &map_val);
+ map_val.SetInt32Value(1);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint64_sint64"), map_key, &map_val);
+ map_val.SetInt64Value(1);
+
+ map_key.SetUInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed32_fixed32"), map_key, &map_val);
+ map_val.SetUInt32Value(1);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed64_fixed64"), map_key, &map_val);
+ map_val.SetUInt64Value(1);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed32_sfixed32"), map_key, &map_val);
+ map_val.SetInt32Value(1);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed64_sfixed64"), map_key, &map_val);
+ map_val.SetInt64Value(1);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_float"), map_key, &map_val);
+ map_val.SetFloatValue(1.0);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_double"), map_key, &map_val);
+ map_val.SetDoubleValue(1.0);
+
+ map_key.SetBoolValue(true);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_bool_bool"), map_key, &map_val);
+ map_val.SetBoolValue(true);
+
+ map_key.SetStringValue("1");
+ reflection->InsertOrLookupMapValue(
+ message, F("map_string_string"), map_key, &map_val);
+ map_val.SetStringValue("1");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_bytes"), map_key, &map_val);
+ map_val.SetStringValue("1");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_enum"), map_key, &map_val);
+ map_val.SetEnumValue(map_enum_baz_->number());
+
+ map_key.SetInt32Value(1);
+ EXPECT_TRUE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_foreign_message"), map_key, &map_val));
+ sub_foreign_message = map_val.MutableMessageValue();
+ sub_foreign_message->GetReflection()->SetInt32(
+ sub_foreign_message, foreign_c_, 1);
+}
+
+void MapReflectionTester::ClearMapFieldsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
@@ -578,97 +767,103 @@ void MapTestUtil::MapReflectionTester::ClearMapFieldsViaReflection(
reflection->ClearField(message, F("map_int32_foreign_message"));
}
-void MapTestUtil::MapReflectionTester::ModifyMapFieldsViaReflection(
+void MapReflectionTester::ModifyMapFieldsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
- Message* sub_message;
+ MapValueRef map_val;
Message* sub_foreign_message;
- // Find out which one's key is 0.
- int size = reflection->FieldSize(*message, F("map_int32_int32"));
- int target = 0;
- for (int i = 0; i < size; i++) {
- const Message& temp_message = reflection
- ->GetRepeatedMessage(*message, F("map_int32_int32"), i);
- if (temp_message.GetReflection()
- ->GetInt32(temp_message, map_int32_int32_key_) == 1) {
- target = i;
- }
- }
-
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_int32"), target);
- sub_message->GetReflection()
- ->SetInt32(sub_message, map_int32_int32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int64_int64"), target);
- sub_message->GetReflection()
- ->SetInt64(sub_message, map_int64_int64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_uint32_uint32"), target);
- sub_message->GetReflection()
- ->SetUInt32(sub_message, map_uint32_uint32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_uint64_uint64"), target);
- sub_message->GetReflection()
- ->SetUInt64(sub_message, map_uint64_uint64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sint32_sint32"), target);
- sub_message->GetReflection()
- ->SetInt32(sub_message, map_sint32_sint32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sint64_sint64"), target);
- sub_message->GetReflection()
- ->SetInt64(sub_message, map_sint64_sint64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_fixed32_fixed32"), target);
- sub_message->GetReflection()
- ->SetUInt32(sub_message, map_fixed32_fixed32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_fixed64_fixed64"), target);
- sub_message->GetReflection()
- ->SetUInt64(sub_message, map_fixed64_fixed64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sfixed32_sfixed32"), target);
- sub_message->GetReflection()
- ->SetInt32(sub_message, map_sfixed32_sfixed32_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_sfixed64_sfixed64"), target);
- sub_message->GetReflection()
- ->SetInt64(sub_message, map_sfixed64_sfixed64_val_, 2);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_float"), target);
- sub_message->GetReflection()
- ->SetFloat(sub_message, map_int32_float_val_, 2.0);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_double"), target);
- sub_message->GetReflection()
- ->SetDouble(sub_message, map_int32_double_val_, 2.0);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_bool_bool"), target);
- sub_message->GetReflection()
- ->SetBool(sub_message, map_bool_bool_val_, false);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_string_string"), target);
- sub_message->GetReflection()
- ->SetString(sub_message, map_string_string_val_, "2");
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_bytes"), target);
- sub_message->GetReflection()
- ->SetString(sub_message, map_int32_bytes_val_, "2");
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_enum"), target);
- sub_message->GetReflection()
- ->SetEnum(sub_message, map_int32_enum_val_, map_enum_foo_);
- sub_message = reflection
- ->MutableRepeatedMessage(message, F("map_int32_foreign_message"), target);
- sub_foreign_message = sub_message->GetReflection()->
- MutableMessage(sub_message, map_int32_foreign_message_val_, NULL);
- sub_foreign_message->GetReflection()->
- SetInt32(sub_foreign_message, foreign_c_, 2);
+ // Modify the second element
+ MapKey map_key;
+ map_key.SetInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_int32"), map_key, &map_val));
+ map_val.SetInt32Value(2);
+
+ map_key.SetInt64Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int64_int64"), map_key, &map_val));
+ map_val.SetInt64Value(2);
+
+ map_key.SetUInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_uint32_uint32"), map_key, &map_val));
+ map_val.SetUInt32Value(2);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_uint64_uint64"), map_key, &map_val);
+ map_val.SetUInt64Value(2);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint32_sint32"), map_key, &map_val);
+ map_val.SetInt32Value(2);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sint64_sint64"), map_key, &map_val);
+ map_val.SetInt64Value(2);
+
+ map_key.SetUInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed32_fixed32"), map_key, &map_val);
+ map_val.SetUInt32Value(2);
+
+ map_key.SetUInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_fixed64_fixed64"), map_key, &map_val);
+ map_val.SetUInt64Value(2);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed32_sfixed32"), map_key, &map_val);
+ map_val.SetInt32Value(2);
+
+ map_key.SetInt64Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_sfixed64_sfixed64"), map_key, &map_val);
+ map_val.SetInt64Value(2);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_float"), map_key, &map_val);
+ map_val.SetFloatValue(2.0);
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_double"), map_key, &map_val);
+ map_val.SetDoubleValue(2.0);
+
+ map_key.SetBoolValue(true);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_bool_bool"), map_key, &map_val);
+ map_val.SetBoolValue(false);
+
+ map_key.SetStringValue("1");
+ reflection->InsertOrLookupMapValue(
+ message, F("map_string_string"), map_key, &map_val);
+ map_val.SetStringValue("2");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_bytes"), map_key, &map_val);
+ map_val.SetStringValue("2");
+
+ map_key.SetInt32Value(1);
+ reflection->InsertOrLookupMapValue(
+ message, F("map_int32_enum"), map_key, &map_val);
+ map_val.SetEnumValue(map_enum_foo_->number());
+
+ map_key.SetInt32Value(1);
+ EXPECT_FALSE(reflection->InsertOrLookupMapValue(
+ message, F("map_int32_foreign_message"), map_key, &map_val));
+ sub_foreign_message = map_val.MutableMessageValue();
+ sub_foreign_message->GetReflection()->SetInt32(
+ sub_foreign_message, foreign_c_, 2);
}
-void MapTestUtil::MapReflectionTester::RemoveLastMapsViaReflection(
+void MapReflectionTester::RemoveLastMapsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
@@ -681,7 +876,7 @@ void MapTestUtil::MapReflectionTester::RemoveLastMapsViaReflection(
}
}
-void MapTestUtil::MapReflectionTester::ReleaseLastMapsViaReflection(
+void MapReflectionTester::ReleaseLastMapsViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
@@ -699,7 +894,7 @@ void MapTestUtil::MapReflectionTester::ReleaseLastMapsViaReflection(
}
}
-void MapTestUtil::MapReflectionTester::SwapMapsViaReflection(Message* message) {
+void MapReflectionTester::SwapMapsViaReflection(Message* message) {
const Reflection* reflection = message->GetReflection();
vector<const FieldDescriptor*> output;
reflection->ListFields(*message, &output);
@@ -710,7 +905,7 @@ void MapTestUtil::MapReflectionTester::SwapMapsViaReflection(Message* message) {
}
}
-void MapTestUtil::MapReflectionTester::
+void MapReflectionTester::
MutableUnknownFieldsOfMapFieldsViaReflection(Message* message) {
const Reflection* reflection = message->GetReflection();
Message* sub_message = NULL;
@@ -768,11 +963,12 @@ void MapTestUtil::MapReflectionTester::
NULL);
}
-void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
+void MapReflectionTester::ExpectMapFieldsSetViaReflection(
const Message& message) {
string scratch;
const Reflection* reflection = message.GetReflection();
const Message* sub_message;
+ MapKey map_key;
// -----------------------------------------------------------------
@@ -799,6 +995,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
map[0] = 0;
map[1] = 1;
for (int i = 0; i < 2; i++) {
+ // Check with RepeatedField Reflection
sub_message =
&reflection->GetRepeatedMessage(message, F("map_int32_int32"), i);
int32 key = sub_message->GetReflection()->GetInt32(
@@ -806,6 +1003,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_int32_int32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_int32_int32"), map_key));
}
}
{
@@ -813,6 +1014,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
map[0] = 0;
map[1] = 1;
for (int i = 0; i < 2; i++) {
+ // Check with RepeatedField Reflection
sub_message =
&reflection->GetRepeatedMessage(message, F("map_int64_int64"), i);
int64 key = sub_message->GetReflection()->GetInt64(
@@ -820,6 +1022,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_int64_int64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt64Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_int64_int64"), map_key));
}
}
{
@@ -827,6 +1033,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
map[0] = 0;
map[1] = 1;
for (int i = 0; i < 2; i++) {
+ // Check with RepeatedField Reflection
sub_message =
&reflection->GetRepeatedMessage(message, F("map_uint32_uint32"), i);
uint32 key = sub_message->GetReflection()->GetUInt32(
@@ -834,6 +1041,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint32 val = sub_message->GetReflection()->GetUInt32(
*sub_message, map_uint32_uint32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt32Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_uint32_uint32"), map_key));
}
}
{
@@ -848,6 +1059,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint64 val = sub_message->GetReflection()->GetUInt64(
*sub_message, map_uint64_uint64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt64Value(key);
+ EXPECT_TRUE(reflection->ContainsMapKey(
+ message, F("map_uint64_uint64"), map_key));
}
}
{
@@ -862,6 +1077,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_sint32_sint32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sint32_sint32"), map_key));
}
}
{
@@ -876,6 +1095,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_sint64_sint64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt64Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sint64_sint64"), map_key));
}
}
{
@@ -890,6 +1113,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint32 val = sub_message->GetReflection()->GetUInt32(
*sub_message, map_fixed32_fixed32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_fixed32_fixed32"), map_key));
}
}
{
@@ -904,6 +1131,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
uint64 val = sub_message->GetReflection()->GetUInt64(
*sub_message, map_fixed64_fixed64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetUInt64Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_fixed64_fixed64"), map_key));
}
}
{
@@ -918,6 +1149,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_sfixed32_sfixed32_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sfixed32_sfixed32"), map_key));
}
}
{
@@ -932,6 +1167,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_sfixed64_sfixed64_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt64Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_sfixed64_sfixed64"), map_key));
}
}
{
@@ -946,6 +1185,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
float val = sub_message->GetReflection()->GetFloat(
*sub_message, map_int32_float_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_float"), map_key));
}
}
{
@@ -960,6 +1203,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
double val = sub_message->GetReflection()->GetDouble(
*sub_message, map_int32_double_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_double"), map_key));
}
}
{
@@ -974,6 +1221,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
bool val = sub_message->GetReflection()->GetBool(
*sub_message, map_bool_bool_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetBoolValue(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_bool_bool"), map_key));
}
}
{
@@ -988,6 +1239,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
string val = sub_message->GetReflection()->GetString(
*sub_message, map_string_string_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetStringValue(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_string_string"), map_key));
}
}
{
@@ -1002,6 +1257,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
string val = sub_message->GetReflection()->GetString(
*sub_message, map_int32_bytes_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_bytes"), map_key));
}
}
{
@@ -1016,6 +1275,10 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum(
*sub_message, map_int32_enum_val_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_enum"), map_key));
}
}
{
@@ -1032,11 +1295,245 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
int32 val = foreign_message.GetReflection()->GetInt32(
foreign_message, foreign_c_);
EXPECT_EQ(map[key], val);
+ // Check with Map Reflection
+ map_key.SetInt32Value(key);
+ EXPECT_EQ(true, reflection->ContainsMapKey(
+ message, F("map_int32_foreign_message"), map_key));
}
}
}
-void MapTestUtil::MapReflectionTester::ExpectClearViaReflection(
+void MapReflectionTester::ExpectMapFieldsSetViaReflectionIterator(
+ Message* message) {
+ string scratch;
+ string serialized;
+ const Reflection* reflection = message->GetReflection();
+
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_int32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int64_int64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint32_uint32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_uint64_uint64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint32_sint32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sint64_sint64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed32_fixed32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_fixed64_fixed64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed32_sfixed32")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_sfixed64_sfixed64")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_float")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_double")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_bool_bool")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_string_string")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_bytes")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_enum")));
+ ASSERT_EQ(2, reflection->FieldSize(*message, F("map_int32_foreign_message")));
+
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ int size = 0;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_int32"));
+ iter != reflection->MapEnd(message, F("map_int32_int32"));
+ ++iter, ++size) {
+ // Check const methods do not invalidate map.
+ message->DebugString();
+ message->ShortDebugString();
+ message->SerializeToString(&serialized);
+ message->SpaceUsed();
+ message->ByteSize();
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetInt32Value());
+ }
+ EXPECT_EQ(size, 2);
+ }
+ {
+ std::map<int64, int64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int64_int64"));
+ iter != reflection->MapEnd(message, F("map_int64_int64")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt64Value()],
+ iter.GetValueRef().GetInt64Value());
+ }
+ }
+ {
+ std::map<uint32, uint32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_uint32_uint32"));
+ iter != reflection->MapEnd(message, F("map_uint32_uint32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt32Value()],
+ iter.GetValueRef().GetUInt32Value());
+ }
+ }
+ {
+ std::map<uint64, uint64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_uint64_uint64"));
+ iter != reflection->MapEnd(message, F("map_uint64_uint64"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt64Value()],
+ iter.GetValueRef().GetUInt64Value());
+ }
+ }
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_sint32_sint32"));
+ iter != reflection->MapEnd(message, F("map_sint32_sint32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetInt32Value());
+ }
+ }
+ {
+ std::map<int64, int64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_sint64_sint64"));
+ iter != reflection->MapEnd(message, F("map_sint64_sint64")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt64Value()],
+ iter.GetValueRef().GetInt64Value());
+ }
+ }
+ {
+ std::map<uint32, uint32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_fixed32_fixed32"));
+ iter != reflection->MapEnd(message, F("map_fixed32_fixed32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt32Value()],
+ iter.GetValueRef().GetUInt32Value());
+ }
+ }
+ {
+ std::map<uint64, uint64> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_fixed64_fixed64"));
+ iter != reflection->MapEnd(message, F("map_fixed64_fixed64"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetUInt64Value()],
+ iter.GetValueRef().GetUInt64Value());
+ }
+ }
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_sfixed32_sfixed32"));
+ iter != reflection->MapEnd(message, F("map_sfixed32_sfixed32"));
+ ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetInt32Value());
+ }
+ }
+ {
+ std::map<int32, float> map;
+ map[0] = 0.0;
+ map[1] = 1.0;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_float"));
+ iter != reflection->MapEnd(message, F("map_int32_float")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetFloatValue());
+ }
+ }
+ {
+ std::map<int32, double> map;
+ map[0] = 0.0;
+ map[1] = 1.0;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_int32_double"));
+ iter != reflection->MapEnd(message, F("map_int32_double")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetDoubleValue());
+ }
+ }
+ {
+ std::map<bool, bool> map;
+ map[false] = false;
+ map[true] = true;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_bool_bool"));
+ iter != reflection->MapEnd(message, F("map_bool_bool")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetBoolValue()],
+ iter.GetValueRef().GetBoolValue());
+ }
+ }
+ {
+ std::map<string, string> map;
+ map["0"] = "0";
+ map["1"] = "1";
+ int size = 0;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_string_string"));
+ iter != reflection->MapEnd(message, F("map_string_string"));
+ ++iter, ++size) {
+ // Check const methods do not invalidate map.
+ message->DebugString();
+ message->ShortDebugString();
+ message->SerializeToString(&serialized);
+ message->SpaceUsed();
+ message->ByteSize();
+ EXPECT_EQ(map[iter.GetKey().GetStringValue()],
+ iter.GetValueRef().GetStringValue());
+ }
+ EXPECT_EQ(size, 2);
+ }
+ {
+ std::map<int32, string> map;
+ map[0] = "0";
+ map[1] = "1";
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_bytes"));
+ iter != reflection->MapEnd(message, F("map_int32_bytes")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ iter.GetValueRef().GetStringValue());
+ }
+ }
+ {
+ std::map<int32, const EnumValueDescriptor*> map;
+ map[0] = map_enum_bar_;
+ map[1] = map_enum_baz_;
+ for (MapIterator iter = reflection->MapBegin(message, F("map_int32_enum"));
+ iter != reflection->MapEnd(message, F("map_int32_enum")); ++iter) {
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()]->number(),
+ iter.GetValueRef().GetEnumValue());
+ }
+ }
+ {
+ std::map<int32, int32> map;
+ map[0] = 0;
+ map[1] = 1;
+ int size = 0;
+ for (MapIterator iter = reflection->MapBegin(
+ message, F("map_int32_foreign_message"));
+ iter != reflection->MapEnd(message, F("map_int32_foreign_message"));
+ ++iter, ++size) {
+ // Check const methods do not invalidate map.
+ message->DebugString();
+ message->ShortDebugString();
+ message->SerializeToString(&serialized);
+ message->SpaceUsed();
+ message->ByteSize();
+ const Message& sub_message = iter.GetValueRef().GetMessageValue();
+ EXPECT_EQ(map[iter.GetKey().GetInt32Value()],
+ sub_message.GetReflection()->GetInt32(sub_message, foreign_c_));
+ }
+ EXPECT_EQ(size, 2);
+ }
+}
+
+void MapReflectionTester::ExpectClearViaReflection(
const Message& message) {
const Reflection* reflection = message.GetReflection();
// Map fields are empty.
@@ -1059,7 +1556,46 @@ void MapTestUtil::MapReflectionTester::ExpectClearViaReflection(
EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message")));
}
-void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection(
+void MapReflectionTester::ExpectClearViaReflectionIterator(
+ Message* message) {
+ const Reflection* reflection = message->GetReflection();
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_int32")) ==
+ reflection->MapEnd(message, F("map_int32_int32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int64_int64")) ==
+ reflection->MapEnd(message, F("map_int64_int64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_uint32_uint32")) ==
+ reflection->MapEnd(message, F("map_uint32_uint32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_uint64_uint64")) ==
+ reflection->MapEnd(message, F("map_uint64_uint64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sint32_sint32")) ==
+ reflection->MapEnd(message, F("map_sint32_sint32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sint64_sint64")) ==
+ reflection->MapEnd(message, F("map_sint64_sint64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed32_fixed32")) ==
+ reflection->MapEnd(message, F("map_fixed32_fixed32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_fixed64_fixed64")) ==
+ reflection->MapEnd(message, F("map_fixed64_fixed64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed32_sfixed32")) ==
+ reflection->MapEnd(message, F("map_sfixed32_sfixed32")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_sfixed64_sfixed64")) ==
+ reflection->MapEnd(message, F("map_sfixed64_sfixed64")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_float")) ==
+ reflection->MapEnd(message, F("map_int32_float")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_double")) ==
+ reflection->MapEnd(message, F("map_int32_double")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_bool_bool")) ==
+ reflection->MapEnd(message, F("map_bool_bool")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_string_string")) ==
+ reflection->MapEnd(message, F("map_string_string")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_bytes")) ==
+ reflection->MapEnd(message, F("map_int32_bytes")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_enum")) ==
+ reflection->MapEnd(message, F("map_int32_enum")));
+ EXPECT_TRUE(reflection->MapBegin(message, F("map_int32_foreign_message")) ==
+ reflection->MapEnd(message, F("map_int32_foreign_message")));
+}
+
+void MapReflectionTester::ExpectMapEntryClearViaReflection(
Message* message) {
const Reflection* reflection = message->GetReflection();
const Message* sub_message;
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index f437e33e..107a639d 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -83,71 +83,74 @@ class MapTestUtil {
// Get pointers of map entries from release.
static std::vector<const Message*> GetMapEntriesFromRelease(
unittest::TestMap* message);
+};
- // Like above, but use the reflection interface.
- class MapReflectionTester {
- public:
- // base_descriptor must be a descriptor for TestMap, which is used for
- // MapReflectionTester to fetch the FieldDescriptors needed to use the
- // reflection interface.
- explicit MapReflectionTester(const Descriptor* base_descriptor);
-
- void SetMapFieldsViaReflection(Message* message);
- void ClearMapFieldsViaReflection(Message* message);
- void ModifyMapFieldsViaReflection(Message* message);
- void RemoveLastMapsViaReflection(Message* message);
- void ReleaseLastMapsViaReflection(Message* message);
- void SwapMapsViaReflection(Message* message);
- void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message);
- void ExpectMapFieldsSetViaReflection(const Message& message);
- void ExpectClearViaReflection(const Message& message);
- void ExpectMapEntryClearViaReflection(Message* message);
-
- private:
- const FieldDescriptor* F(const string& name);
-
- const Descriptor* base_descriptor_;
-
- const EnumValueDescriptor* map_enum_bar_;
- const EnumValueDescriptor* map_enum_baz_;
- const EnumValueDescriptor* map_enum_foo_;
-
- const FieldDescriptor* foreign_c_;
- const FieldDescriptor* map_int32_int32_key_;
- const FieldDescriptor* map_int32_int32_val_;
- const FieldDescriptor* map_int64_int64_key_;
- const FieldDescriptor* map_int64_int64_val_;
- const FieldDescriptor* map_uint32_uint32_key_;
- const FieldDescriptor* map_uint32_uint32_val_;
- const FieldDescriptor* map_uint64_uint64_key_;
- const FieldDescriptor* map_uint64_uint64_val_;
- const FieldDescriptor* map_sint32_sint32_key_;
- const FieldDescriptor* map_sint32_sint32_val_;
- const FieldDescriptor* map_sint64_sint64_key_;
- const FieldDescriptor* map_sint64_sint64_val_;
- const FieldDescriptor* map_fixed32_fixed32_key_;
- const FieldDescriptor* map_fixed32_fixed32_val_;
- const FieldDescriptor* map_fixed64_fixed64_key_;
- const FieldDescriptor* map_fixed64_fixed64_val_;
- const FieldDescriptor* map_sfixed32_sfixed32_key_;
- const FieldDescriptor* map_sfixed32_sfixed32_val_;
- const FieldDescriptor* map_sfixed64_sfixed64_key_;
- const FieldDescriptor* map_sfixed64_sfixed64_val_;
- const FieldDescriptor* map_int32_float_key_;
- const FieldDescriptor* map_int32_float_val_;
- const FieldDescriptor* map_int32_double_key_;
- const FieldDescriptor* map_int32_double_val_;
- const FieldDescriptor* map_bool_bool_key_;
- const FieldDescriptor* map_bool_bool_val_;
- const FieldDescriptor* map_string_string_key_;
- const FieldDescriptor* map_string_string_val_;
- const FieldDescriptor* map_int32_bytes_key_;
- const FieldDescriptor* map_int32_bytes_val_;
- const FieldDescriptor* map_int32_enum_key_;
- const FieldDescriptor* map_int32_enum_val_;
- const FieldDescriptor* map_int32_foreign_message_key_;
- const FieldDescriptor* map_int32_foreign_message_val_;
- };
+// Like above, but use the reflection interface.
+class MapReflectionTester {
+ public:
+ // base_descriptor must be a descriptor for TestMap, which is used for
+ // MapReflectionTester to fetch the FieldDescriptors needed to use the
+ // reflection interface.
+ explicit MapReflectionTester(const Descriptor* base_descriptor);
+
+ void SetMapFieldsViaReflection(Message* message);
+ void SetMapFieldsViaMapReflection(Message* message);
+ void ClearMapFieldsViaReflection(Message* message);
+ void ModifyMapFieldsViaReflection(Message* message);
+ void RemoveLastMapsViaReflection(Message* message);
+ void ReleaseLastMapsViaReflection(Message* message);
+ void SwapMapsViaReflection(Message* message);
+ void MutableUnknownFieldsOfMapFieldsViaReflection(Message* message);
+ void ExpectMapFieldsSetViaReflection(const Message& message);
+ void ExpectMapFieldsSetViaReflectionIterator(Message* message);
+ void ExpectClearViaReflection(const Message& message);
+ void ExpectClearViaReflectionIterator(Message* message);
+ void ExpectMapEntryClearViaReflection(Message* message);
+
+ private:
+ const FieldDescriptor* F(const string& name);
+
+ const Descriptor* base_descriptor_;
+
+ const EnumValueDescriptor* map_enum_bar_;
+ const EnumValueDescriptor* map_enum_baz_;
+ const EnumValueDescriptor* map_enum_foo_;
+
+ const FieldDescriptor* foreign_c_;
+ const FieldDescriptor* map_int32_int32_key_;
+ const FieldDescriptor* map_int32_int32_val_;
+ const FieldDescriptor* map_int64_int64_key_;
+ const FieldDescriptor* map_int64_int64_val_;
+ const FieldDescriptor* map_uint32_uint32_key_;
+ const FieldDescriptor* map_uint32_uint32_val_;
+ const FieldDescriptor* map_uint64_uint64_key_;
+ const FieldDescriptor* map_uint64_uint64_val_;
+ const FieldDescriptor* map_sint32_sint32_key_;
+ const FieldDescriptor* map_sint32_sint32_val_;
+ const FieldDescriptor* map_sint64_sint64_key_;
+ const FieldDescriptor* map_sint64_sint64_val_;
+ const FieldDescriptor* map_fixed32_fixed32_key_;
+ const FieldDescriptor* map_fixed32_fixed32_val_;
+ const FieldDescriptor* map_fixed64_fixed64_key_;
+ const FieldDescriptor* map_fixed64_fixed64_val_;
+ const FieldDescriptor* map_sfixed32_sfixed32_key_;
+ const FieldDescriptor* map_sfixed32_sfixed32_val_;
+ const FieldDescriptor* map_sfixed64_sfixed64_key_;
+ const FieldDescriptor* map_sfixed64_sfixed64_val_;
+ const FieldDescriptor* map_int32_float_key_;
+ const FieldDescriptor* map_int32_float_val_;
+ const FieldDescriptor* map_int32_double_key_;
+ const FieldDescriptor* map_int32_double_val_;
+ const FieldDescriptor* map_bool_bool_key_;
+ const FieldDescriptor* map_bool_bool_val_;
+ const FieldDescriptor* map_string_string_key_;
+ const FieldDescriptor* map_string_string_val_;
+ const FieldDescriptor* map_int32_bytes_key_;
+ const FieldDescriptor* map_int32_bytes_val_;
+ const FieldDescriptor* map_int32_enum_key_;
+ const FieldDescriptor* map_int32_enum_val_;
+ const FieldDescriptor* map_int32_foreign_message_key_;
+ const FieldDescriptor* map_int32_foreign_message_val_;
};
} // namespace protobuf
diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
index 5e7882a1..7e8757ed 100644
--- a/src/google/protobuf/map_test_util_impl.h
+++ b/src/google/protobuf/map_test_util_impl.h
@@ -31,6 +31,7 @@
#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
@@ -167,8 +168,11 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
(*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);
+ (*message->mutable_map_int32_foreign_message_no_arena())[0].set_c(0);
// Add second element
(*message->mutable_map_int32_int32())[1] = 1;
@@ -184,8 +188,11 @@ void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) {
(*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);
+ (*message->mutable_map_int32_foreign_message_no_arena())[1].set_c(1);
}
template <typename MapMessage>
@@ -329,8 +336,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
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(2, message.map_int32_foreign_message_no_arena().size());
EXPECT_EQ(0, message.map_int32_int32().at(0));
EXPECT_EQ(0, message.map_int64_int64().at(0));
@@ -345,8 +355,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
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(0, message.map_int32_foreign_message_no_arena().at(0).c());
EXPECT_EQ(1, message.map_int32_int32().at(1));
EXPECT_EQ(1, message.map_int64_int64().at(1));
@@ -361,8 +374,11 @@ void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) {
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());
+ EXPECT_EQ(1, message.map_int32_foreign_message_no_arena().at(1).c());
}
template <typename EnumType, EnumType enum_value, typename MapMessage>
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index ffdb6dfb..5040e605 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -54,22 +54,6 @@ struct MapIf<false, TrueType, FalseType> {
typedef FalseType type;
};
-// In MapField, string and message are stored as pointer while others are stored
-// as object. However, google::protobuf::Map has unified api. Functions in this class
-// convert key/value to type wanted in api regardless how it's stored
-// internally.
-template <typename Type>
-class MapCommonTypeHandler {
- public:
- static inline Type& Reference(Type* x) { return *x; }
- static inline Type& Reference(Type& x) { return x; }
- static inline const Type& Reference(const Type& x) { return x; }
- static inline Type* Pointer(Type* x) { return x; }
- static inline Type* Pointer(Type& x) { return &x; }
- static inline const Type* Pointer(const Type* x) { return x; }
- static inline const Type* Pointer(const Type& x) { return &x; }
-};
-
// In proto2 Map, enum needs to be initialized to given default value, while
// other types' default value can be inferred from the type.
template <bool IsEnum, typename Type>
@@ -110,174 +94,29 @@ 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
-template <typename Type>
-class MapCppTypeHandler : public MapCommonTypeHandler<Type> {
- public:
- static const bool kIsStringOrMessage = true;
- // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
- // those already calculate in sizeof(MapField).
- static int SpaceUsedInMapEntry(const Type* value) {
- return value->SpaceUsed();
- }
- // Return bytes used by value in Map.
- static int SpaceUsedInMap(const Type& value) { return value.SpaceUsed(); }
- static inline void Clear(Type** value) {
- if (*value != NULL) (*value)->Clear();
- }
- static inline void ClearMaybeByDefaultEnum(Type** value,
- int default_enum_value) {
- if (*value != NULL) (*value)->Clear();
- }
- static inline void Merge(const Type& from, Type** to) {
- (*to)->MergeFrom(from);
- }
-
- static void Delete(const Type* ptr) { delete ptr; }
-
- // Assign default value to given instance.
- static inline void AssignDefaultValue(Type** value) {
- *value = const_cast<Type*>(&Type::default_instance());
- }
- // Initialize value when constructing MapEntry
- 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, Arena* arena) {
- *x = NULL;
- }
- // Initialize value for the first time mutable accessor is called.
- 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(const Type* value,
- const Type* default_value) {
- return value != NULL ? *value : *default_value;
- }
- // Check if all required fields have values set.
- static inline bool IsInitialized(Type* value) {
- return value->IsInitialized();
- }
-};
-
-// Handler for string.
-template <>
-class MapCppTypeHandler<string> : public MapCommonTypeHandler<string> {
- public:
- static const bool kIsStringOrMessage = true;
- static inline void Merge(const string& from, string** to) { **to = from; }
- static inline void Clear(string** value) { (*value)->clear(); }
- static inline void ClearMaybeByDefaultEnum(string** value, int default_enum) {
- (*value)->clear();
- }
- static inline int SpaceUsedInMapEntry(const string* value) {
- return sizeof(*value) + StringSpaceUsedExcludingSelf(*value);
- }
- static inline int SpaceUsedInMap(const string& value) {
- return sizeof(value) + StringSpaceUsedExcludingSelf(value);
- }
- static void Delete(const string* ptr) {
- if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr;
- }
- static inline void AssignDefaultValue(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, Arena* arena) {
- *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString());
- if (arena != NULL) arena->Own(*value);
+ return Arena::Create<Type>(arena);
}
- static inline void EnsureMutable(string** value, Arena* arena) {
- if (*value == &::google::protobuf::internal::GetEmptyString()) {
- *value = Arena::Create<string>(arena);
- }
- }
- 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; }
};
-// Base class for primitive type handlers.
-template <typename Type>
-class MapPrimitiveTypeHandler : public MapCommonTypeHandler<Type> {
- public:
- static const bool kIsStringOrMessage = false;
- static inline void Delete(const Type& x) {}
- static inline void Merge(const Type& from, Type* to) { *to = from; }
- static inline int SpaceUsedInMapEntry(const Type& value) { return 0; }
- static inline int SpaceUsedInMap(const Type& value) { return sizeof(Type); }
- static inline void AssignDefaultValue(Type* value) {}
- static inline const Type& DefaultIfNotInitialized(
- const Type& value, const Type& default_value) {
- return value;
- }
- static inline bool IsInitialized(const Type& value) { return true; }
-};
-
-// Handlers for primitive types.
-#define PRIMITIVE_HANDLER(CType) \
- template <> \
- class MapCppTypeHandler<CType> : public MapPrimitiveTypeHandler<CType> { \
- public: \
- static inline void Clear(CType* value) { *value = 0; } \
- static inline void ClearMaybeByDefaultEnum(CType* value, \
- int default_enum_value) { \
- *value = static_cast<CType>(default_enum_value); \
- } \
- static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \
- static inline void InitializeMaybeByDefaultEnum(CType* value, \
- int default_enum_value, \
- Arena* arena) { \
- *value = static_cast<CType>(default_enum_value); \
- } \
- static inline void EnsureMutable(CType* value, Arena* arena) {} \
- };
-
-PRIMITIVE_HANDLER(int32 )
-PRIMITIVE_HANDLER(int64 )
-PRIMITIVE_HANDLER(uint32)
-PRIMITIVE_HANDLER(uint64)
-PRIMITIVE_HANDLER(double)
-PRIMITIVE_HANDLER(float )
-PRIMITIVE_HANDLER(bool )
-
-#undef PRIMITIVE_HANDLER
-
// Define constants for given wire field type
-template <WireFormatLite::FieldType field_type>
+template <WireFormatLite::FieldType field_type, typename Type>
class MapWireFieldTypeTraits {};
-#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
- template <> \
- class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType> { \
- public: \
- typedef CType CppType; \
- static const bool kIsMessage = IsMessage; \
- static const bool kIsEnum = IsEnum; \
- static const WireFormatLite::WireType kWireType = \
- WireFormatLite::WIRETYPE_##WireFormatType; \
+#define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \
+ template <typename Type> \
+ class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> { \
+ public: \
+ static const bool kIsMessage = IsMessage; \
+ static const bool kIsEnum = IsEnum; \
+ typedef typename MapIf<kIsMessage, Type*, CType>::type TypeOnMemory; \
+ typedef typename MapIf<kIsEnum, int, Type>::type MapEntryAccessorType; \
+ static const WireFormatLite::WireType kWireType = \
+ WireFormatLite::WIRETYPE_##WireFormatType; \
};
-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(MESSAGE , Type, LENGTH_DELIMITED, true, false)
+TYPE_TRAITS(STRING , ArenaStringPtr, LENGTH_DELIMITED, false, false)
+TYPE_TRAITS(BYTES , ArenaStringPtr , LENGTH_DELIMITED, false, false)
TYPE_TRAITS(INT64 , int64 , VARINT , false, false)
TYPE_TRAITS(UINT64 , uint64 , VARINT , false, false)
TYPE_TRAITS(INT32 , int32 , VARINT , false, false)
@@ -295,46 +134,149 @@ TYPE_TRAITS(BOOL , bool , VARINT , false, false)
#undef TYPE_TRAITS
-template <WireFormatLite::FieldType field_type>
-class MapWireFieldTypeHandler {
+template <WireFormatLite::FieldType field_type, typename Type>
+class MapTypeHandler {};
+
+template <typename Type>
+class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
public:
+ // Enum type cannot be used for MapTypeHandler::Read. Define a type which will
+ // replace Enum with int.
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
+ Type>::MapEntryAccessorType MapEntryAccessorType;
// Internal stored type in MapEntryLite for given wire field type.
- typedef typename MapWireFieldTypeTraits<field_type>::CppType CppType;
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
+ Type>::TypeOnMemory TypeOnMemory;
// Corresponding wire type for field type.
static const WireFormatLite::WireType kWireType =
- MapWireFieldTypeTraits<field_type>::kWireType;
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
// Whether wire type is for message.
- static const bool kIsMessage = MapWireFieldTypeTraits<field_type>::kIsMessage;
+ static const bool kIsMessage =
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
// Whether wire type is for enum.
- static const bool kIsEnum = MapWireFieldTypeTraits<field_type>::kIsEnum;
+ static const bool kIsEnum =
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, 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,
+ static inline int ByteSize(const MapEntryAccessorType& value);
+ static inline int GetCachedSize(const MapEntryAccessorType& value);
+ static inline bool Read(io::CodedInputStream* input,
+ MapEntryAccessorType* value);
+ static inline void Write(int field, const MapEntryAccessorType& value,
io::CodedOutputStream* output);
- static inline uint8* WriteToArray(int field, const CppType& value,
+ static inline uint8* WriteToArray(int field,
+ const MapEntryAccessorType& value,
uint8* output);
+
+ // Functions to manipulate data on memory. ========================
+ static inline const Type& GetExternalReference(const Type* value);
+ static inline void DeleteNoArena(const Type* x);
+ static inline void Merge(const Type& from, Type** to, Arena* arena);
+ static inline void Clear(Type** value, Arena* arena);
+ static inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena,
+ int default_enum_value);
+ static inline void Initialize(Type** x, Arena* arena);
+
+ static inline void InitializeMaybeByDefaultEnum(Type** x,
+ int default_enum_value,
+ Arena* arena);
+ static inline Type* EnsureMutable(Type** value, Arena* arena);
+ // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
+ // those already calculate in sizeof(MapField).
+ static inline int SpaceUsedInMapEntry(const Type* value);
+ // Return bytes used by value in Map.
+ static inline int SpaceUsedInMap(const Type& value);
+ // Assign default value to given instance.
+ static inline void AssignDefaultValue(Type** value);
+ // Return default instance if value is not initialized when calling const
+ // reference accessor.
+ static inline const Type& DefaultIfNotInitialized(
+ const Type* value, const Type* default_value);
+ // Check if all required fields have values set.
+ static inline bool IsInitialized(Type* value);
};
-template <>
-template <typename ValueType>
-inline int MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::ByteSize(
- const ValueType& value) {
+#define MAP_HANDLER(FieldType) \
+ template <typename Type> \
+ class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> { \
+ public: \
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType \
+ MapEntryAccessorType; \
+ typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::TypeOnMemory TypeOnMemory; \
+ static const WireFormatLite::WireType kWireType = \
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::kWireType; \
+ static const bool kIsMessage = \
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::kIsMessage; \
+ static const bool kIsEnum = \
+ MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
+ Type>::kIsEnum; \
+ static inline int ByteSize(const MapEntryAccessorType& value); \
+ static inline int GetCachedSize(const MapEntryAccessorType& value); \
+ static inline bool Read(io::CodedInputStream* input, \
+ MapEntryAccessorType* value); \
+ static inline void Write(int field, const MapEntryAccessorType& value, \
+ io::CodedOutputStream* output); \
+ static inline uint8* WriteToArray(int field, \
+ const MapEntryAccessorType& value, \
+ uint8* output); \
+ static inline const MapEntryAccessorType& GetExternalReference( \
+ const TypeOnMemory& value); \
+ static inline void DeleteNoArena(const TypeOnMemory& x); \
+ static inline void Merge(const MapEntryAccessorType& from, \
+ TypeOnMemory* to, Arena* arena); \
+ static inline void Clear(TypeOnMemory* value, Arena* arena); \
+ static inline void ClearMaybeByDefaultEnum(TypeOnMemory* value, \
+ Arena* arena, \
+ int default_enum); \
+ static inline int SpaceUsedInMapEntry(const TypeOnMemory& value); \
+ static inline int SpaceUsedInMap(const TypeOnMemory& value); \
+ static inline int SpaceUsedInMap(const string& value); \
+ static inline void AssignDefaultValue(TypeOnMemory* value); \
+ static inline const MapEntryAccessorType& DefaultIfNotInitialized( \
+ const TypeOnMemory& value, const TypeOnMemory& default_value); \
+ static inline bool IsInitialized(const TypeOnMemory& value); \
+ static void DeleteNoArena(TypeOnMemory& value); \
+ static inline void Initialize(TypeOnMemory* value, Arena* arena); \
+ static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
+ int default_enum_value, \
+ Arena* arena); \
+ static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \
+ Arena* arena); \
+ };
+MAP_HANDLER(STRING)
+MAP_HANDLER(BYTES)
+MAP_HANDLER(INT64)
+MAP_HANDLER(UINT64)
+MAP_HANDLER(INT32)
+MAP_HANDLER(UINT32)
+MAP_HANDLER(SINT64)
+MAP_HANDLER(SINT32)
+MAP_HANDLER(ENUM)
+MAP_HANDLER(DOUBLE)
+MAP_HANDLER(FLOAT)
+MAP_HANDLER(FIXED64)
+MAP_HANDLER(FIXED32)
+MAP_HANDLER(SFIXED64)
+MAP_HANDLER(SFIXED32)
+MAP_HANDLER(BOOL)
+#undef MAP_HANDLER
+
+template <typename Type>
+inline int
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
+ const MapEntryAccessorType& value) {
return WireFormatLite::MessageSizeNoVirtual(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); \
+#define BYTE_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
BYTE_SIZE(STRING, String)
@@ -349,13 +291,11 @@ BYTE_SIZE(ENUM , Enum)
#undef BYTE_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; \
+#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
FIXED_BYTE_SIZE(DOUBLE , Double)
@@ -368,20 +308,19 @@ FIXED_BYTE_SIZE(BOOL , Bool)
#undef FIXED_BYTE_SIZE
-template <>
-template <typename ValueType>
-inline int MapWireFieldTypeHandler<
- WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) {
+template <typename Type>
+inline int
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
+ const MapEntryAccessorType& value) {
return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
}
-#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); \
+#define GET_CACHED_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::DeclaredType##Size(value); \
}
GET_CACHED_SIZE(STRING, String)
@@ -396,13 +335,12 @@ GET_CACHED_SIZE(ENUM , Enum)
#undef GET_CACHED_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; \
+#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
+ const MapEntryAccessorType& value) { \
+ return WireFormatLite::k##DeclaredType##Size; \
}
GET_FIXED_CACHED_SIZE(DOUBLE , Double)
@@ -415,30 +353,31 @@ GET_FIXED_CACHED_SIZE(BOOL , Bool)
#undef GET_FIXED_CACHED_SIZE
-template <>
-inline void MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Write(
- int field, const MessageLite& value, io::CodedOutputStream* output) {
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
+ int field, const MapEntryAccessorType& value,
+ io::CodedOutputStream* output) {
WireFormatLite::WriteMessageMaybeToArray(field, value, output);
}
-template <>
+template <typename Type>
inline uint8*
-MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::WriteToArray(
- int field, const MessageLite& value, uint8* output) {
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::WriteToArray(
+ int field, const MapEntryAccessorType& value, uint8* output) {
return WireFormatLite::WriteMessageToArray(field, value, output);
}
#define WRITE_METHOD(FieldType, DeclaredType) \
- template <> \
- inline void \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::Write( \
- int field, const CppType& value, io::CodedOutputStream* output) { \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write( \
+ int field, const MapEntryAccessorType& value, \
+ io::CodedOutputStream* output) { \
return WireFormatLite::Write##DeclaredType(field, value, output); \
} \
- template <> \
+ template <typename Type> \
inline uint8* \
- MapWireFieldTypeHandler<WireFormatLite::TYPE_##FieldType>::WriteToArray( \
- int field, const CppType& value, uint8* output) { \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::WriteToArray( \
+ int field, const MapEntryAccessorType& value, uint8* output) { \
return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \
}
@@ -461,35 +400,31 @@ WRITE_METHOD(BOOL , Bool)
#undef WRITE_METHOD
-template <>
-template <typename ValueType>
-inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_MESSAGE>::Read(
- io::CodedInputStream* input, ValueType* value) {
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
+ io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadMessageNoVirtual(input, value);
}
-template <>
-template <typename ValueType>
-inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_STRING>::Read(
- io::CodedInputStream* input, ValueType* value) {
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
+ io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadString(input, value);
}
-template <>
-template <typename ValueType>
-inline bool MapWireFieldTypeHandler<WireFormatLite::TYPE_BYTES>::Read(
- io::CodedInputStream* input, ValueType* value) {
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
+ io::CodedInputStream* input, MapEntryAccessorType* value) {
return WireFormatLite::ReadBytes(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); \
+#define READ_METHOD(FieldType) \
+ template <typename Type> \
+ inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
+ io::CodedInputStream* input, MapEntryAccessorType* value) { \
+ return WireFormatLite::ReadPrimitive<TypeOnMemory, \
+ WireFormatLite::TYPE_##FieldType>( \
+ input, value); \
}
READ_METHOD(INT64)
@@ -509,6 +444,282 @@ READ_METHOD(BOOL)
#undef READ_METHOD
+// Definition for message handler
+
+template <typename Type>
+inline const Type&
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::GetExternalReference(const Type* value) {
+ return *value;
+}
+
+template <typename Type>
+inline int
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::SpaceUsedInMapEntry(const Type* value) {
+ return value->SpaceUsed();
+}
+
+template <typename Type>
+int MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::SpaceUsedInMap(
+ const Type& value) {
+ return value.SpaceUsed();
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
+ Type** value, Arena* arena) {
+ if (*value != NULL) (*value)->Clear();
+}
+template <typename Type>
+inline void
+MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::ClearMaybeByDefaultEnum(Type** value,
+ Arena* arena,
+ int default_enum_value) {
+ if (*value != NULL) (*value)->Clear();
+}
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
+ const Type& from, Type** to, Arena* arena) {
+ (*to)->MergeFrom(from);
+}
+
+template <typename Type>
+void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena(
+ const Type* ptr) {
+ delete ptr;
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::AssignDefaultValue(Type** value) {
+ *value = const_cast<Type*>(&Type::default_instance());
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::Initialize(Type** x,
+ Arena* arena) {
+ *x = NULL;
+}
+
+template <typename Type>
+inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
+ InitializeMaybeByDefaultEnum(Type** x, int default_enum_value,
+ Arena* arena) {
+ *x = NULL;
+}
+
+template <typename Type>
+inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::EnsureMutable(Type** value,
+ Arena* arena) {
+ if (*value == NULL) {
+ *value =
+ MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>::
+ type::value>::CreateMessage(arena);
+ }
+ return *value;
+}
+
+template <typename Type>
+inline const Type& MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
+ DefaultIfNotInitialized(const Type* value, const Type* default_value) {
+ return value != NULL ? *value : *default_value;
+}
+
+template <typename Type>
+inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
+ Type>::IsInitialized(Type* value) {
+ return value->IsInitialized();
+}
+
+// Definition for string/bytes handler
+
+#define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType) \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::GetExternalReference(const TypeOnMemory& value) { \
+ return value.Get(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapEntry( \
+ const TypeOnMemory& value) { \
+ return sizeof(value); \
+ } \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::SpaceUsedInMap(const TypeOnMemory& value) { \
+ return sizeof(value); \
+ } \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::SpaceUsedInMap(const string& value) { \
+ return sizeof(value); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
+ TypeOnMemory* value, Arena* arena) { \
+ value->ClearToEmpty(&::google::protobuf::internal::GetEmptyString(), arena); \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::ClearMaybeByDefaultEnum(TypeOnMemory* value, \
+ Arena* arena, \
+ int default_enum) { \
+ Clear(value, arena); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
+ const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
+ to->Set(&::google::protobuf::internal::GetEmptyString(), from, arena); \
+ } \
+ template <typename Type> \
+ void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena( \
+ TypeOnMemory& value) { \
+ value.DestroyNoArena(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::AssignDefaultValue(TypeOnMemory* value) {} \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize( \
+ TypeOnMemory* value, Arena* arena) { \
+ value->UnsafeSetDefault(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
+ int default_enum_value, \
+ Arena* arena) { \
+ Initialize(value, arena); \
+ } \
+ template <typename Type> \
+ inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType* \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
+ TypeOnMemory* value, Arena* arena) { \
+ return value->Mutable(&::google::protobuf::internal::GetEmptyString(), arena); \
+ } \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::DefaultIfNotInitialized(const TypeOnMemory& value, \
+ const TypeOnMemory& \
+ default_value) { \
+ return value.Get(&::google::protobuf::internal::GetEmptyString()); \
+ } \
+ template <typename Type> \
+ inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::IsInitialized(const TypeOnMemory& value) { \
+ return true; \
+ }
+STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
+STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
+#undef STRING_OR_BYTES_HANDLER_FUNCTIONS
+
+#define PRIMITIVE_HANDLER_FUNCTIONS(FieldType) \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::GetExternalReference(const TypeOnMemory& value) { \
+ return value; \
+ } \
+ template <typename Type> \
+ inline int \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapEntry( \
+ const TypeOnMemory& value) { \
+ return 0; \
+ } \
+ template <typename Type> \
+ inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::SpaceUsedInMap(const TypeOnMemory& value) { \
+ return sizeof(Type); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear( \
+ TypeOnMemory* value, Arena* arena) { \
+ *value = 0; \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::ClearMaybeByDefaultEnum(TypeOnMemory* value, \
+ Arena* arena, \
+ int default_enum_value) { \
+ *value = static_cast<TypeOnMemory>(default_enum_value); \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge( \
+ const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) { \
+ *to = from; \
+ } \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::DeleteNoArena(TypeOnMemory& x) {} \
+ template <typename Type> \
+ inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::AssignDefaultValue(TypeOnMemory* value) {} \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize( \
+ TypeOnMemory* value, Arena* arena) { \
+ *value = 0; \
+ } \
+ template <typename Type> \
+ inline void \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::InitializeMaybeByDefaultEnum(TypeOnMemory* value, \
+ int default_enum_value, \
+ Arena* arena) { \
+ *value = static_cast<TypeOnMemory>(default_enum_value); \
+ } \
+ template <typename Type> \
+ inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType* \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable( \
+ TypeOnMemory* value, Arena* arena) { \
+ return value; \
+ } \
+ template <typename Type> \
+ inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::MapEntryAccessorType& \
+ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::DefaultIfNotInitialized(const TypeOnMemory& value, \
+ const TypeOnMemory& \
+ default_value) { \
+ return value; \
+ } \
+ template <typename Type> \
+ inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, \
+ Type>::IsInitialized(const TypeOnMemory& value) { \
+ return true; \
+ }
+PRIMITIVE_HANDLER_FUNCTIONS(INT64)
+PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
+PRIMITIVE_HANDLER_FUNCTIONS(INT32)
+PRIMITIVE_HANDLER_FUNCTIONS(UINT32)
+PRIMITIVE_HANDLER_FUNCTIONS(SINT64)
+PRIMITIVE_HANDLER_FUNCTIONS(SINT32)
+PRIMITIVE_HANDLER_FUNCTIONS(ENUM)
+PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE)
+PRIMITIVE_HANDLER_FUNCTIONS(FLOAT)
+PRIMITIVE_HANDLER_FUNCTIONS(FIXED64)
+PRIMITIVE_HANDLER_FUNCTIONS(FIXED32)
+PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64)
+PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32)
+PRIMITIVE_HANDLER_FUNCTIONS(BOOL)
+#undef PRIMITIVE_HANDLER_FUNCTIONS
+
} // namespace internal
} // namespace protobuf
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index b308c7ff..d3b525a0 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -33,6 +33,7 @@ syntax = "proto3";
option cc_enable_arenas = true;
import "google/protobuf/unittest.proto";
+import "google/protobuf/unittest_no_arena.proto";
// We don't put this in a package within proto2 because we need to make sure
// that the generated code doesn't depend on being in the proto2 namespace.
@@ -58,6 +59,7 @@ message TestMap {
map<int32 , bytes > map_int32_bytes = 15;
map<int32 , MapEnum > map_int32_enum = 16;
map<int32 , ForeignMessage> map_int32_foreign_message = 17;
+ map<string , ForeignMessage> map_string_foreign_message = 18;
}
message TestMapSubmessage {
@@ -100,8 +102,12 @@ message TestArenaMap {
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;
+ map<string , string > map_string_string = 14;
+ map<int32 , bytes > map_int32_bytes = 15;
+ map<int32 , MapEnum > map_int32_enum = 16;
+ map<int32 , ForeignMessage> map_int32_foreign_message = 17;
+ map<int32, .protobuf_unittest_no_arena.ForeignMessage>
+ map_int32_foreign_message_no_arena = 18;
}
// Previously, message containing enum called Type cannot be used as value of
@@ -117,3 +123,7 @@ message MessageContainingEnumCalledType {
message MessageContainingMapCalledEntry {
map<int32, int32> entry = 1;
}
+
+message TestRecursiveMapMessage {
+ map<int32, TestRecursiveMapMessage> a = 1;
+}
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 276d7de5..7d69c57a 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -38,12 +38,15 @@
#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/stubs/once.h>
#include <google/protobuf/reflection_internal.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/map_field.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/reflection_ops.h>
@@ -256,6 +259,22 @@ void Reflection::AddEnumValue(Message* message,
GOOGLE_LOG(FATAL) << "Unimplemented EnumValue API.";
}
+MapIterator Reflection::MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
+ MapIterator iter(message, field);
+ return iter;
+}
+
+MapIterator Reflection::MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const {
+ GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
+ MapIterator iter(message, field);
+ return iter;
+}
+
// =============================================================================
// MessageFactory
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 18c092d0..348e7c7f 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -134,12 +134,23 @@ class Reflection;
class MessageFactory;
// Defined in other files.
+class MapKey;
+class MapValueRef;
+class MapIterator;
+class MapReflectionTester;
+
+namespace internal {
+class MapFieldBase;
+}
class UnknownFieldSet; // unknown_field_set.h
namespace io {
- class ZeroCopyInputStream; // zero_copy_stream.h
- class ZeroCopyOutputStream; // zero_copy_stream.h
- class CodedInputStream; // coded_stream.h
- class CodedOutputStream; // coded_stream.h
+class ZeroCopyInputStream; // zero_copy_stream.h
+class ZeroCopyOutputStream; // zero_copy_stream.h
+class CodedInputStream; // coded_stream.h
+class CodedOutputStream; // coded_stream.h
+}
+namespace python {
+class MapReflectionFriend; // scalar_map_container.h
}
@@ -724,6 +735,14 @@ class LIBPROTOBUF_EXPORT Reflection {
const FieldDescriptor* field,
MessageFactory* factory = NULL) const = 0;
+ // Appends an already-allocated object 'new_entry' to the repeated field
+ // specifyed by 'field' passing ownership to the message.
+ // TODO(tmarek): Make virtual after all subclasses have been
+ // updated.
+ virtual void AddAllocatedMessage(Message* message,
+ const FieldDescriptor* field,
+ Message* new_entry) const {}
+
// Get a RepeatedFieldRef object that can be used to read the underlying
// repeated field. The type parameter T must be set according to the
@@ -868,11 +887,20 @@ class LIBPROTOBUF_EXPORT Reflection {
// on field->cpp_type(),
// on field->field_option().ctype() (if ctype >= 0)
// of field->message_type() (if message_type != NULL).
- // We use 1 routine rather than 4 (const vs mutable) x (scalar vs pointer).
+ // We use 2 routine rather than 4 (const vs mutable) x (scalar vs pointer).
virtual void* MutableRawRepeatedField(
Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
int ctype, const Descriptor* message_type) const = 0;
+ // TODO(jieluo) - make it pure virtual after updating all the subclasses.
+ virtual const void* GetRawRepeatedField(
+ const Message& message, const FieldDescriptor* field,
+ FieldDescriptor::CppType cpptype, int ctype,
+ const Descriptor* message_type) const {
+ return MutableRawRepeatedField(
+ const_cast<Message*>(&message), field, cpptype, ctype, message_type);
+ }
+
// 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
@@ -887,6 +915,8 @@ class LIBPROTOBUF_EXPORT Reflection {
// "message_type" should be set to its descriptor. Otherwise "message_type"
// should be set to NULL. Implementations of this method should check whether
// "cpp_type"/"message_type" is consistent with the actual type of the field.
+ // We use 1 routine rather than 2 (const vs mutable) because it is protected
+ // and it doesn't change the message.
virtual void* RepeatedFieldData(
Message* message, const FieldDescriptor* field,
FieldDescriptor::CppType cpp_type,
@@ -902,14 +932,73 @@ class LIBPROTOBUF_EXPORT Reflection {
friend class RepeatedFieldRef;
template<typename T, typename Enable>
friend class MutableRepeatedFieldRef;
+ friend class ::google::protobuf::python::MapReflectionFriend;
// Special version for specialized implementations of string. We can't call
// MutableRawRepeatedField directly here because we don't have access to
// FieldOptions::* which are defined in descriptor.pb.h. Including that
// file here is not possible because it would cause a circular include cycle.
+ // We use 1 routine rather than 2 (const vs mutable) because it is private
+ // and mutable a repeated string field doesn't change the message.
void* MutableRawRepeatedString(
Message* message, const FieldDescriptor* field, bool is_string) const;
+ friend class MapReflectionTester;
+ // TODO(jieluo) - make the map APIs pure virtual after updating
+ // all the subclasses.
+ // Returns true if key is in map. Returns false if key is not in map field.
+ virtual bool ContainsMapKey(const Message& message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ return false;
+ }
+
+ // If key is in map field: Saves the value pointer to val and returns
+ // false. If key in not in map field: Insert the key into map, saves
+ // value pointer to val and retuns true.
+ virtual bool InsertOrLookupMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key,
+ MapValueRef* val) const {
+ return false;
+ }
+
+ // Delete and returns true if key is in the map field. Returns false
+ // otherwise.
+ virtual bool DeleteMapValue(Message* message,
+ const FieldDescriptor* field,
+ const MapKey& key) const {
+ return false;
+ }
+
+ // Returns a MaIterator referring to the first element in the map field.
+ // If the map field is empty, this function returns the same as
+ // reflection::MapEnd. Mutation to the field may invalidate the iterator.
+ virtual MapIterator MapBegin(
+ Message* message,
+ const FieldDescriptor* field) const;
+
+ // Returns a MapIterator referring to the theoretical element that would
+ // follow the last element in the map field. It does not point to any
+ // real element. Mutation to the field may invalidate the iterator.
+ virtual MapIterator MapEnd(
+ Message* message,
+ const FieldDescriptor* field) const;
+
+ // Get the number of <key, value> pair of a map field. The result may be
+ // different from FieldSize which can have duplicate keys.
+ virtual int MapSize(const Message& message,
+ const FieldDescriptor* field) const {
+ return 0;
+ }
+
+ // Help method for MapIterator.
+ friend class MapIterator;
+ virtual internal::MapFieldBase* MapData(
+ Message* message, const FieldDescriptor* field) const {
+ return NULL;
+ }
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
};
@@ -1025,10 +1114,9 @@ inline RepeatedPtrField<string>* Reflection::MutableRepeatedPtrField<string>(
template<>
inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField(
const Message& message, const FieldDescriptor* field) const {
- return *static_cast<RepeatedPtrField<Message>* >(
- MutableRawRepeatedField(const_cast<Message*>(&message), field,
- FieldDescriptor::CPPTYPE_MESSAGE, -1,
- NULL));
+ return *static_cast<const RepeatedPtrField<Message>* >(
+ GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE,
+ -1, NULL));
}
template<>
@@ -1043,10 +1131,9 @@ inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField(
template<typename PB>
inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField(
const Message& message, const FieldDescriptor* field) const {
- return *static_cast<RepeatedPtrField<PB>* >(
- MutableRawRepeatedField(const_cast<Message*>(&message), field,
- FieldDescriptor::CPPTYPE_MESSAGE, -1,
- PB::default_instance().GetDescriptor()));
+ return *static_cast<const RepeatedPtrField<PB>* >(
+ GetRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_MESSAGE,
+ -1, PB::default_instance().GetDescriptor()));
}
template<typename PB>
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index 4f63ad2b..5bd8bcfb 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -35,7 +35,9 @@
#include <google/protobuf/message_lite.h>
#include <google/protobuf/arena.h>
+#include <google/protobuf/repeated_field.h>
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
@@ -98,27 +100,19 @@ string InitializationErrorMessage(const char* action,
// call MergePartialFromCodedStream(). However, when parsing very small
// messages, every function call introduces significant overhead. To avoid
// this without reproducing code, we use these forced-inline helpers.
-//
-// Note: GCC only allows GOOGLE_ATTRIBUTE_ALWAYS_INLINE on declarations, not
-// definitions.
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineMergeFromCodedStream(
+ io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromCodedStream(
+ io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromCodedStream(
+ io::CodedInputStream* input, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParseFromArray(
+ const void* data, int size, MessageLite* message);
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool InlineParsePartialFromArray(
+ const void* data, int size, MessageLite* message);
+
inline bool InlineMergeFromCodedStream(io::CodedInputStream* input,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParseFromArray(const void* data, int size,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-inline bool InlineParsePartialFromArray(const void* data, int size,
- MessageLite* message)
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-
-bool InlineMergeFromCodedStream(io::CodedInputStream* input,
- MessageLite* message) {
+ MessageLite* message) {
if (!message->MergePartialFromCodedStream(input)) return false;
if (!message->IsInitialized()) {
GOOGLE_LOG(ERROR) << InitializationErrorMessage("parse", *message);
@@ -127,26 +121,27 @@ bool InlineMergeFromCodedStream(io::CodedInputStream* input,
return true;
}
-bool InlineParseFromCodedStream(io::CodedInputStream* input,
- MessageLite* message) {
+inline bool InlineParseFromCodedStream(io::CodedInputStream* input,
+ MessageLite* message) {
message->Clear();
return InlineMergeFromCodedStream(input, message);
}
-bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
- MessageLite* message) {
+inline bool InlineParsePartialFromCodedStream(io::CodedInputStream* input,
+ MessageLite* message) {
message->Clear();
return message->MergePartialFromCodedStream(input);
}
-bool InlineParseFromArray(const void* data, int size, MessageLite* message) {
+inline bool InlineParseFromArray(
+ const void* data, int size, MessageLite* message) {
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
return InlineParseFromCodedStream(&input, message) &&
input.ConsumedEntireMessage();
}
-bool InlineParsePartialFromArray(const void* data, int size,
- MessageLite* message) {
+inline bool InlineParsePartialFromArray(
+ const void* data, int size, MessageLite* message) {
io::CodedInputStream input(reinterpret_cast<const uint8*>(data), size);
return InlineParsePartialFromCodedStream(&input, message) &&
input.ConsumedEntireMessage();
@@ -353,5 +348,18 @@ string MessageLite::SerializePartialAsString() const {
return output;
}
+namespace internal {
+template<>
+MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+ const MessageLite* prototype, google::protobuf::Arena* arena) {
+ return prototype->New(arena);
+}
+template <>
+void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
+ MessageLite* to) {
+ to->CheckTypeAndMergeFrom(from);
+}
+} // namespace internal
+
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index 75d60b8b..2d4780fe 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -53,6 +53,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/metadata.h b/src/google/protobuf/metadata.h
index 30b2a6ee..fdee150b 100644
--- a/src/google/protobuf/metadata.h
+++ b/src/google/protobuf/metadata.h
@@ -69,8 +69,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
ptr_ = NULL;
}
- inline const UnknownFieldSet& unknown_fields() const
- GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE const UnknownFieldSet& unknown_fields() const {
if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
return PtrValue<Container>()->unknown_fields_;
} else {
@@ -78,7 +77,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline UnknownFieldSet* mutable_unknown_fields() GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE UnknownFieldSet* mutable_unknown_fields() {
if (GOOGLE_PREDICT_TRUE(have_unknown_fields())) {
return &PtrValue<Container>()->unknown_fields_;
} else {
@@ -86,7 +85,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline Arena* arena() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE Arena* arena() const {
if (GOOGLE_PREDICT_FALSE(have_unknown_fields())) {
return PtrValue<Container>()->arena_;
} else {
@@ -94,11 +93,11 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline bool have_unknown_fields() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE bool have_unknown_fields() const {
return PtrTag() == kTagContainer;
}
- inline void Swap(InternalMetadataWithArena* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(InternalMetadataWithArena* other) {
// Semantics here are that we swap only the unknown fields, not the arena
// pointer. We cannot simply swap ptr_ with other->ptr_ because we need to
// maintain our own arena ptr. Also, our ptr_ and other's ptr_ may be in
@@ -110,7 +109,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
}
}
- inline void* raw_arena_ptr() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* raw_arena_ptr() const {
return ptr_;
}
@@ -128,7 +127,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
static const intptr_t kPtrValueMask = ~kPtrTagMask;
// Accessors for pointer tag and pointer value.
- inline int PtrTag() const GOOGLE_ATTRIBUTE_ALWAYS_INLINE {
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE int PtrTag() const {
return reinterpret_cast<intptr_t>(ptr_) & kPtrTagMask;
}
@@ -143,7 +142,7 @@ class LIBPROTOBUF_EXPORT InternalMetadataWithArena {
Arena* arena_;
};
- UnknownFieldSet* mutable_unknown_fields_slow() GOOGLE_ATTRIBUTE_NOINLINE {
+ GOOGLE_ATTRIBUTE_NOINLINE UnknownFieldSet* mutable_unknown_fields_slow() {
Arena* my_arena = arena();
Container* container = Arena::Create<Container>(my_arena);
ptr_ = reinterpret_cast<void*>(
diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc
index 4b7b31d9..bc41beec 100644
--- a/src/google/protobuf/no_field_presence_test.cc
+++ b/src/google/protobuf/no_field_presence_test.cc
@@ -341,6 +341,46 @@ TEST(NoFieldPresenceTest, ReflectionHasFieldTest) {
EXPECT_EQ(false, r->HasField(message, field_string));
}
+TEST(NoFieldPresenceTest, ReflectionClearFieldTest) {
+ proto2_nofieldpresence_unittest::TestAllTypes message;
+
+ const google::protobuf::Reflection* r = message.GetReflection();
+ const google::protobuf::Descriptor* desc = message.GetDescriptor();
+
+ const google::protobuf::FieldDescriptor* field_int32 = desc->FindFieldByName(
+ "optional_int32");
+ const google::protobuf::FieldDescriptor* field_double = desc->FindFieldByName(
+ "optional_double");
+ const google::protobuf::FieldDescriptor* field_string = desc->FindFieldByName(
+ "optional_string");
+ const google::protobuf::FieldDescriptor* field_message = desc->FindFieldByName(
+ "optional_nested_message");
+ const google::protobuf::FieldDescriptor* field_lazy = desc->FindFieldByName(
+ "optional_lazy_message");
+
+ message.set_optional_int32(42);
+ r->ClearField(&message, field_int32);
+ EXPECT_EQ(0, message.optional_int32());
+
+ message.set_optional_double(42.0);
+ r->ClearField(&message, field_double);
+ EXPECT_EQ(0.0, message.optional_double());
+
+ message.set_optional_string("test");
+ r->ClearField(&message, field_string);
+ EXPECT_EQ("", message.optional_string());
+
+ message.mutable_optional_nested_message()->set_bb(1234);
+ r->ClearField(&message, field_message);
+ EXPECT_FALSE(message.has_optional_nested_message());
+ EXPECT_EQ(0, message.optional_nested_message().bb());
+
+ message.mutable_optional_lazy_message()->set_bb(42);
+ r->ClearField(&message, field_lazy);
+ EXPECT_FALSE(message.has_optional_lazy_message());
+ EXPECT_EQ(0, message.optional_lazy_message().bb());
+}
+
TEST(NoFieldPresenceTest, HasFieldOneofsTest) {
// check that HasField behaves properly for oneofs.
proto2_nofieldpresence_unittest::TestAllTypes message;
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index da4be673..2838e0fc 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -119,7 +119,7 @@ void ExpectAllFieldsSet(const TestAllTypes& m) {
// proto3 and expect the arena support to be fully tested in proto2 unittests
// because proto3 shares most code with proto2.
-TEST(ArenaTest, Parsing) {
+TEST(Proto3ArenaTest, Parsing) {
TestAllTypes original;
SetAllFields(&original);
@@ -129,7 +129,7 @@ TEST(ArenaTest, Parsing) {
ExpectAllFieldsSet(*arena_message);
}
-TEST(ArenaTest, UnknownFields) {
+TEST(Proto3ArenaTest, UnknownFields) {
TestAllTypes original;
SetAllFields(&original);
@@ -150,7 +150,7 @@ TEST(ArenaTest, UnknownFields) {
arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
}
-TEST(ArenaTest, Swap) {
+TEST(Proto3ArenaTest, Swap) {
Arena arena1;
Arena arena2;
@@ -162,7 +162,7 @@ TEST(ArenaTest, Swap) {
EXPECT_EQ(&arena2, arena2_message->GetArena());
}
-TEST(ArenaTest, SetAllocatedMessage) {
+TEST(Proto3ArenaTest, SetAllocatedMessage) {
Arena arena;
TestAllTypes *arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage;
@@ -171,7 +171,7 @@ TEST(ArenaTest, SetAllocatedMessage) {
EXPECT_EQ(118, arena_message->optional_nested_message().bb());
}
-TEST(ArenaTest, ReleaseMessage) {
+TEST(Proto3ArenaTest, ReleaseMessage) {
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
arena_message->mutable_optional_nested_message()->set_bb(118);
@@ -180,7 +180,7 @@ TEST(ArenaTest, ReleaseMessage) {
EXPECT_EQ(118, nested->bb());
}
-TEST(ArenaTest, MessageFieldClear) {
+TEST(Proto3ArenaTest, MessageFieldClear) {
// GitHub issue #310: https://github.com/google/protobuf/issues/310
Arena arena;
TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -190,6 +190,20 @@ TEST(ArenaTest, MessageFieldClear) {
arena_message->Clear();
}
+TEST(Proto3ArenaTest, MessageFieldClearViaReflection) {
+ Arena arena;
+ TestAllTypes* message = Arena::CreateMessage<TestAllTypes>(&arena);
+ const Reflection* r = message->GetReflection();
+ const Descriptor* d = message->GetDescriptor();
+ const FieldDescriptor* msg_field = d->FindFieldByName(
+ "optional_nested_message");
+
+ message->mutable_optional_nested_message()->set_bb(1);
+ r->ClearField(message, msg_field);
+ EXPECT_FALSE(message->has_optional_nested_message());
+ EXPECT_EQ(0, message->optional_nested_message().bb());
+}
+
} // namespace
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/proto_cast.h b/src/google/protobuf/proto_cast.h
index e25c219f..dc0e9aca 100644
--- a/src/google/protobuf/proto_cast.h
+++ b/src/google/protobuf/proto_cast.h
@@ -33,6 +33,7 @@
#include <string>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
// proto_cast<> is used to simulate over-the-wire conversion of one
diff --git a/src/google/protobuf/proto_cast_test.cc b/src/google/protobuf/proto_cast_test.cc
index eb101eb6..a8f43ae4 100644
--- a/src/google/protobuf/proto_cast_test.cc
+++ b/src/google/protobuf/proto_cast_test.cc
@@ -32,7 +32,7 @@
#include <google/protobuf/util/unknown_enum_test.pb.h>
#include <gtest/gtest.h>
-#include <google/protobuf/testing/gmock.h>
+#include <gmock/gmock.h>
namespace google {
using google::protobuf::util::UpRevision;
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index 4ff0f6b4..671aafdc 100755
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -553,7 +553,7 @@ struct RefTypeTraits<
template<typename T>
struct RefTypeTraits<
- T, typename internal::enable_if<internal::is_same<string, T>::value>::type> {
+ T, typename internal::enable_if< ::google::protobuf::internal::is_same<string, T>::value>::type> {
typedef RepeatedFieldRefIterator<T> iterator;
typedef RepeatedFieldAccessor AccessorType;
typedef string AccessorValueType;
diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
index 32740ea4..88d6bfb6 100644
--- a/src/google/protobuf/reflection_ops_unittest.cc
+++ b/src/google/protobuf/reflection_ops_unittest.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index e5aedadc..949e0a23 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -35,6 +35,7 @@
#include <algorithm>
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
@@ -53,13 +54,17 @@ void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) {
Arena* arena = GetArenaNoVirtual();
new_size = max(kMinRepeatedFieldAllocationSize,
max(total_size_ * 2, new_size));
+ GOOGLE_CHECK_LE(new_size,
+ (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
+ sizeof(old_rep->elements[0]))
+ << "Requested size is too large to fit into size_t.";
if (arena == NULL) {
rep_ = reinterpret_cast<Rep*>(
- new char[kRepHeaderSize + sizeof(old_rep->elements[0])*new_size]);
+ new char[kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size]);
} else {
rep_ = reinterpret_cast<Rep*>(
::google::protobuf::Arena::CreateArray<char>(arena,
- kRepHeaderSize + sizeof(old_rep->elements[0])*new_size));
+ kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size));
}
total_size_ = new_size;
if (old_rep && old_rep->allocated_size > 0) {
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 14f46298..b42d4790 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -54,6 +54,7 @@
#include <string>
#include <iterator>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/type_traits.h>
#include <google/protobuf/arena.h>
@@ -361,7 +362,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
// To parse directly into a proto2 generated class, the upb class GMR_Handlers
// needs to be able to modify a RepeatedPtrFieldBase directly.
- friend class LIBPROTOBUF_EXPORT upb::google_opensource::GMR_Handlers;
+ friend class upb::google_opensource::GMR_Handlers;
RepeatedPtrFieldBase();
explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena);
@@ -408,7 +409,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
const typename TypeHandler::Type* const* data() const;
template <typename TypeHandler>
- inline void Swap(RepeatedPtrFieldBase* other) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ GOOGLE_ATTRIBUTE_ALWAYS_INLINE void Swap(RepeatedPtrFieldBase* other);
void SwapElements(int index1, int index2);
@@ -458,22 +459,20 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase {
void AddAllocatedInternal(typename TypeHandler::Type* value,
google::protobuf::internal::false_type);
- template <typename TypeHandler>
+ template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value,
Arena* value_arena,
- Arena* my_arena)
- GOOGLE_ATTRIBUTE_NOINLINE;
- template <typename TypeHandler>
- void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value)
- GOOGLE_ATTRIBUTE_NOINLINE;
+ Arena* my_arena);
+ template <typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
+ void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value);
template <typename TypeHandler>
typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::true_type);
template <typename TypeHandler>
typename TypeHandler::Type* ReleaseLastInternal(google::protobuf::internal::false_type);
- template<typename TypeHandler>
- inline void SwapFallback(RepeatedPtrFieldBase* other) GOOGLE_ATTRIBUTE_NOINLINE;
+ template<typename TypeHandler> GOOGLE_ATTRIBUTE_NOINLINE
+ void SwapFallback(RepeatedPtrFieldBase* other);
inline Arena* GetArenaNoVirtual() const {
return arena_;
@@ -542,20 +541,10 @@ class GenericTypeHandler {
}
// We force NewFromPrototype() and Delete() to be non-inline to reduce code
// size: else, several other methods get inlined copies of message types'
- // constructors and destructors. Note that the GOOGLE_ATTRIBUTE_NOINLINE macro
- // requires the 'inline' storage class here, which is somewhat confusing, but
- // the compiler does the right thing.
- static inline GenericType* NewFromPrototype(const GenericType* prototype,
- ::google::protobuf::Arena* arena = NULL)
- GOOGLE_ATTRIBUTE_NOINLINE {
- return New(arena);
- }
- static inline void Delete(GenericType* value, Arena* arena)
- GOOGLE_ATTRIBUTE_NOINLINE {
- if (arena == NULL) {
- delete value;
- }
- }
+ // constructors and destructors.
+ GOOGLE_ATTRIBUTE_NOINLINE static GenericType* NewFromPrototype(
+ const GenericType* prototype, ::google::protobuf::Arena* arena = NULL);
+ GOOGLE_ATTRIBUTE_NOINLINE static void Delete(GenericType* value, Arena* arena);
static inline ::google::protobuf::Arena* GetArena(GenericType* value) {
return ::google::protobuf::Arena::GetArena<Type>(value);
}
@@ -564,10 +553,8 @@ class GenericTypeHandler {
}
static inline void Clear(GenericType* value) { value->Clear(); }
- static inline void Merge(const GenericType& from, GenericType* to)
- GOOGLE_ATTRIBUTE_NOINLINE {
- to->MergeFrom(from);
- }
+ GOOGLE_ATTRIBUTE_NOINLINE static void Merge(const GenericType& from,
+ GenericType* to);
static inline int SpaceUsed(const GenericType& value) {
return value.SpaceUsed();
}
@@ -576,11 +563,31 @@ class GenericTypeHandler {
}
};
-template<>
-inline MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
- const MessageLite* prototype, google::protobuf::Arena* arena) {
- return prototype->New(arena);
+template <typename GenericType>
+GenericType* GenericTypeHandler<GenericType>::NewFromPrototype(
+ const GenericType* prototype, ::google::protobuf::Arena* arena) {
+ return New(arena);
+}
+template <typename GenericType>
+void GenericTypeHandler<GenericType>::Delete(GenericType* value, Arena* arena) {
+ if (arena == NULL) {
+ delete value;
+ }
}
+template <typename GenericType>
+void GenericTypeHandler<GenericType>::Merge(const GenericType& from,
+ GenericType* to) {
+ to->MergeFrom(from);
+}
+
+// NewFromPrototype() and Merge() cannot be defined here; if they're declared
+// inline the compiler will complain about not matching GOOGLE_ATTRIBUTE_NOINLINE
+// above, and if not, compilation will result in multiple definitions. These
+// are therefore declared as specializations here and defined in
+// message_lite.cc.
+template<>
+MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
+ const MessageLite* prototype, google::protobuf::Arena* arena);
template<>
inline google::protobuf::Arena* GenericTypeHandler<MessageLite>::GetArena(
MessageLite* value) {
@@ -591,14 +598,9 @@ inline void* GenericTypeHandler<MessageLite>::GetMaybeArenaPointer(
MessageLite* value) {
return value->GetMaybeArenaPointer();
}
-
-// Implements GenericTypeHandler specialization required by RepeatedPtrFields
-// to work with MessageLite type.
template <>
-inline void GenericTypeHandler<MessageLite>::Merge(
- const MessageLite& from, MessageLite* to) {
- to->CheckTypeAndMergeFrom(from);
-}
+void GenericTypeHandler<MessageLite>::Merge(const MessageLite& from,
+ MessageLite* to);
// Declarations of the specialization as we cannot define them here, as the
// header that defines ProtocolMessage depends on types defined in this header.
@@ -1221,13 +1223,17 @@ void RepeatedField<Element>::Reserve(int new_size) {
Arena* arena = GetArenaNoVirtual();
new_size = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
max(total_size_ * 2, new_size));
+ GOOGLE_CHECK_LE(new_size,
+ (std::numeric_limits<size_t>::max() - kRepHeaderSize) /
+ sizeof(Element))
+ << "Requested size is too large to fit into size_t.";
if (arena == NULL) {
rep_ = reinterpret_cast<Rep*>(
- new char[kRepHeaderSize + sizeof(Element)*new_size]);
+ new char[kRepHeaderSize + sizeof(Element) * new_size]);
} else {
rep_ = reinterpret_cast<Rep*>(
::google::protobuf::Arena::CreateArray<char>(arena,
- kRepHeaderSize + sizeof(Element)*new_size));
+ kRepHeaderSize + sizeof(Element) * new_size));
}
rep_->arena = arena;
int old_total_size = total_size_;
@@ -1342,7 +1348,7 @@ inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) {
}
template <typename TypeHandler>
-inline void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
+void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) {
GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual());
// Copy semantics in this case. We try to improve efficiency by placing the
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index af397932..b45664b0 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -42,6 +42,7 @@
#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/stubs/strutil.h>
@@ -1429,7 +1430,6 @@ class RepeatedFieldInsertionIteratorsTest : public testing::Test {
std::copy(nested_ptrs.begin(), nested_ptrs.end(),
RepeatedFieldBackInserter(
protobuffer.mutable_repeated_nested_message()));
-
}
virtual void TearDown() {
diff --git a/src/google/protobuf/service.h b/src/google/protobuf/service.h
index cc0b45d4..ad6f9685 100644
--- a/src/google/protobuf/service.h
+++ b/src/google/protobuf/service.h
@@ -74,12 +74,12 @@
//
// To call a remote MyServiceImpl, first you need an RpcChannel connected to it.
// How to construct a channel depends, again, on your RPC implementation.
-// Here we use a hypothentical "MyRpcChannel" as an example:
+// Here we use a hypothetical "MyRpcChannel" as an example:
// MyRpcChannel channel("rpc:hostname:1234/myservice");
// MyRpcController controller;
// MyServiceImpl::Stub stub(&channel);
// FooRequest request;
-// FooRespnose response;
+// FooResponse response;
//
// // ... fill in request ...
//
@@ -102,6 +102,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/callback.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index be1c90e0..07aa1d77 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -42,6 +42,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc
index 88eca0ad..388c0cbd 100644
--- a/src/google/protobuf/test_util_lite.cc
+++ b/src/google/protobuf/test_util_lite.cc
@@ -33,6 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <google/protobuf/test_util_lite.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 76ce9875..1aafd8e6 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -38,11 +38,13 @@
#include <stdlib.h>
#include <limits>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/test_util.h>
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_mset.pb.h>
+#include <google/protobuf/unittest_mset_wire_format.pb.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/strutil.h>
diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto
index 3aa31fa9..49d9adad 100644
--- a/src/google/protobuf/unittest_mset.proto
+++ b/src/google/protobuf/unittest_mset.proto
@@ -32,33 +32,31 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
//
-// This file contains messages for testing message_set_wire_format.
+// This file is similar to unittest_mset_wire_format.proto, but does not
+// have a TestMessageSet, so it can be downgraded to proto1.
syntax = "proto2";
+
+import "google/protobuf/unittest_mset_wire_format.proto";
+
package protobuf_unittest;
option cc_enable_arenas = true;
option optimize_for = SPEED;
-// A message with message_set_wire_format.
-message TestMessageSet {
- option message_set_wire_format = true;
- extensions 4 to max;
-}
-
message TestMessageSetContainer {
- optional TestMessageSet message_set = 1;
+ optional proto2_wireformat_unittest.TestMessageSet message_set = 1;
}
message TestMessageSetExtension1 {
- extend TestMessageSet {
+ extend proto2_wireformat_unittest.TestMessageSet {
optional TestMessageSetExtension1 message_set_extension = 1545008;
}
optional int32 i = 15;
}
message TestMessageSetExtension2 {
- extend TestMessageSet {
+ extend proto2_wireformat_unittest.TestMessageSet {
optional TestMessageSetExtension2 message_set_extension = 1547769;
}
optional string str = 25;
@@ -82,4 +80,3 @@ message RawMessageSet {
required bytes message = 3;
}
}
-
diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h
index 39c10cbc..7c68ad6c 100644
--- a/src/google/protobuf/unknown_enum_impl.h
+++ b/src/google/protobuf/unknown_enum_impl.h
@@ -34,7 +34,6 @@
#include <stdlib.h>
#include <google/protobuf/stubs/common.h>
-#include "net/proto/tagmapper.h"
#include <google/protobuf/bridge/compatibility_mode_support.h>
namespace google {
@@ -59,10 +58,10 @@ namespace util {
// In proto2, invalid enum values will be treated as unknown fields. This
// function checks that case.
bool HasUnknownEnum(const Message& message, int32 field_number,
- int32* unknown_value = nullptr);
+ int32* unknown_value = NULL);
// Same as above, but returns all unknown enums.
bool GetRepeatedEnumUnknowns(const Message& message, int32 field_number,
- vector<int32>* unknown_values = nullptr);
+ vector<int32>* unknown_values = NULL);
// In proto1, invalue enum values are stored in the same way as valid enum
// values.
// TODO(karner): Delete this once the migration to proto2 is complete.
@@ -75,7 +74,7 @@ bool GetRepeatedEnumUnknownsProto1(const Message& message, int32 field_number,
// or proto2.
template <typename T>
bool HasUnknownEnum_Template(const T& message, int32 field_number,
- int32* unknown_value = nullptr) {
+ int32* unknown_value = NULL) {
if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
!internal::is_base_of<ProtocolMessage, T>::value) {
return HasUnknownEnum(message, field_number, unknown_value);
@@ -88,7 +87,7 @@ bool HasUnknownEnum_Template(const T& message, int32 field_number,
template <typename T>
bool GetRepeatedEnumUnknowns_Template(
const T& message, int32 field_number,
- vector<int32>* unknown_values = nullptr) {
+ vector<int32>* unknown_values = NULL) {
if (internal::is_base_of<bridge::internal::Proto1CompatibleMessage, T>::value ||
!internal::is_base_of<ProtocolMessage, T>::value) {
return GetRepeatedEnumUnknowns(message, field_number, unknown_values);
diff --git a/src/google/protobuf/unknown_enum_test.proto b/src/google/protobuf/unknown_enum_test.proto
index 0ea1ede3..3c549cc7 100644
--- a/src/google/protobuf/unknown_enum_test.proto
+++ b/src/google/protobuf/unknown_enum_test.proto
@@ -36,6 +36,8 @@ syntax = "proto2";
package google.protobuf.util;
+option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
+
message DownRevision {
enum Enum {
DEFAULT_VALUE = 2;
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 93f0f206..d4e383da 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -34,6 +34,7 @@
#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 6781cd0f..612a942a 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -42,6 +42,7 @@
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index 9b02f0b0..5de72630 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -43,7 +43,10 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/stubs/stl_util.h>
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index 944fb2e3..ea360798 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -79,7 +79,9 @@ StatusOr<To> NumberConvertAndCheck(From before) {
// For conversion between double and float only.
template <typename To, typename From>
StatusOr<To> FloatingPointConvertAndCheck(From before) {
- if (MathLimits<From>::IsNaN(before)) return std::numeric_limits<To>::quiet_NaN();
+ if (MathLimits<From>::IsNaN(before)) {
+ return std::numeric_limits<To>::quiet_NaN();
+ }
To after = static_cast<To>(before);
if (MathUtil::AlmostEquals<To>(after, before)) {
@@ -167,7 +169,7 @@ StatusOr<string> DataPiece::ToString() const {
return str_.ToString();
case TYPE_BYTES: {
string base64;
- WebSafeBase64Escape(str_, &base64);
+ Base64Escape(str_, &base64);
return base64;
}
default:
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index 267e2cd3..97b248ff 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -46,6 +46,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter(
TypeResolver* type_resolver, const google::protobuf::Type& type,
ObjectWriter* ow)
: typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
+ own_typeinfo_(true),
type_(type),
disable_normalize_(false),
current_(NULL),
@@ -56,6 +57,9 @@ DefaultValueObjectWriter::~DefaultValueObjectWriter() {
for (int i = 0; i < string_values_.size(); ++i) {
delete string_values_[i];
}
+ if (own_typeinfo_) {
+ delete typeinfo_;
+ }
}
DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name,
@@ -197,33 +201,47 @@ void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
if (disable_normalize_) {
ow->DisableCaseNormalizationForNextKey();
}
+
if (kind_ == PRIMITIVE) {
ObjectWriter::RenderDataPieceTo(data_, name_, ow);
return;
}
- if (is_placeholder_) {
- // If is_placeholder_ = true, we didn't see this node in the response, so
- // skip output.
+
+ // Render maps. Empty maps are rendered as "{}".
+ if (kind_ == MAP) {
+ ow->StartObject(name_);
+ WriteChildren(ow);
+ ow->EndObject();
return;
}
+
+ // Write out lists. If we didn't have any list in response, write out empty
+ // list.
if (kind_ == LIST) {
ow->StartList(name_);
- } else {
- ow->StartObject(name_);
+ WriteChildren(ow);
+ ow->EndList();
+ return;
}
+
+ // If is_placeholder_ = true, we didn't see this node in the response, so
+ // skip output.
+ if (is_placeholder_) return;
+
+ ow->StartObject(name_);
+ WriteChildren(ow);
+ ow->EndObject();
+}
+
+void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) {
for (int i = 0; i < children_.size(); ++i) {
Node* child = children_[i];
child->WriteTo(ow);
}
- if (kind_ == LIST) {
- ow->EndList();
- } else {
- ow->EndObject();
- }
}
const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
- const google::protobuf::Type& found_type, TypeInfo* typeinfo) {
+ const google::protobuf::Type& found_type, const TypeInfo* typeinfo) {
// If this field is a map, we should use the type of its "Value" as
// the type of the child node.
for (int i = 0; i < found_type.fields_size(); ++i) {
@@ -248,7 +266,8 @@ const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
return NULL;
}
-void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) {
+void DefaultValueObjectWriter::Node::PopulateChildren(
+ const TypeInfo* typeinfo) {
// Ignores well known types that don't require automatically populating their
// primitive children. For type "Any", we only populate its children when the
// "@type" field is set.
@@ -310,15 +329,17 @@ void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) {
google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
kind = LIST;
}
- // If the child field is of primitive type, sets its data to the default
- // value of its type.
+
// If oneof_index() != 0, the child field is part of a "oneof", which means
// the child field is optional and we shouldn't populate its default value.
+ if (field.oneof_index() != 0) continue;
+
+ // If the child field is of primitive type, sets its data to the default
+ // value of its type.
google::protobuf::scoped_ptr<Node> child(
- new Node(field.name(), field_type, kind,
- ((kind == PRIMITIVE && field.oneof_index() == 0)
- ? CreateDefaultDataPieceForField(field)
- : DataPiece::NullData()),
+ new Node(field.json_name(), field_type, kind,
+ kind == PRIMITIVE ? CreateDefaultDataPieceForField(field)
+ : DataPiece::NullData(),
true));
new_children.push_back(child.release());
}
@@ -338,7 +359,7 @@ void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
// have been added, populates its children.
if (node != NULL && node->is_any() && node->type() != NULL &&
node->type()->name() != kAnyType && node->number_of_children() == 1) {
- node->PopulateChildren(typeinfo_.get());
+ node->PopulateChildren(typeinfo_);
}
}
@@ -388,7 +409,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
false));
root_->set_disable_normalize(GetAndResetDisableNormalize());
- root_->PopulateChildren(typeinfo_.get());
+ root_->PopulateChildren(typeinfo_);
current_ = root_.get();
return this;
}
@@ -409,7 +430,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
child->set_is_placeholder(false);
child->set_disable_normalize(GetAndResetDisableNormalize());
if (child->kind() == OBJECT && child->number_of_children() == 0) {
- child->PopulateChildren(typeinfo_.get());
+ child->PopulateChildren(typeinfo_);
}
stack_.push(current_);
@@ -492,12 +513,11 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
// first value field is rendered before we populate the children, because
// the "value" field of a Any message could be omitted.
if (current_->number_of_children() > 1 && current_->type() != NULL) {
- current_->PopulateChildren(typeinfo_.get());
+ current_->PopulateChildren(typeinfo_);
}
}
Node* child = current_->FindChild(name);
if (child == NULL || child->kind() != PRIMITIVE) {
- GOOGLE_LOG(WARNING) << "Cannot find primitive field '" << name << "'.";
// No children are found, creates a new child.
google::protobuf::scoped_ptr<Node> node(
new Node(name.ToString(), NULL, PRIMITIVE, data, false));
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 759ba91b..2468c8d9 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -57,7 +57,7 @@ namespace converter {
// ObjectWriter when EndObject() is called on the root object. It also writes
// out all non-repeated primitive fields that haven't been explicitly rendered
// with their default values (0 for numbers, "" for strings, etc).
-class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
+class DefaultValueObjectWriter : public ObjectWriter {
public:
DefaultValueObjectWriter(TypeResolver* type_resolver,
const google::protobuf::Type& type,
@@ -129,7 +129,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Populates children of this Node based on its type. If there are already
// children created, they will be merged to the result. Caller should pass
// in TypeInfo for looking up types of the children.
- void PopulateChildren(TypeInfo* typeinfo);
+ void PopulateChildren(const TypeInfo* typeinfo);
// If this node is a leaf (has data), writes the current node to the
// ObjectWriter; if not, then recursively writes the children to the
@@ -165,7 +165,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Returns the Value Type of a map given the Type of the map entry and a
// TypeInfo instance.
const google::protobuf::Type* GetMapValueType(
- const google::protobuf::Type& entry_type, TypeInfo* typeinfo);
+ const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);
+
+ // Calls WriteTo() on every child in children_.
+ void WriteChildren(ObjectWriter* ow);
// The name of this node.
string name_;
@@ -210,7 +213,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Type information for all the types used in the descriptor. Used to find
// google::protobuf::Type of nested messages/enums.
- google::protobuf::scoped_ptr<TypeInfo> typeinfo_;
+ const TypeInfo* typeinfo_;
+ // Whether the TypeInfo object is owned by this class.
+ bool own_typeinfo_;
// google::protobuf::Type of the root message type.
const google::protobuf::Type& type_;
// Holds copies of strings passed to RenderString.
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
index 593c7105..237d0722 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
@@ -73,15 +73,15 @@ INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
TEST_P(DefaultValueObjectWriterTest, Empty) {
// Set expectation
expects_.StartObject("")
- ->RenderDouble("double_value", 0.0)
- ->RenderFloat("float_value", 0.0)
- ->RenderInt64("int64_value", 0)
- ->RenderUint64("uint64_value", 0)
- ->RenderInt32("int32_value", 0)
- ->RenderUint32("uint32_value", 0)
- ->RenderBool("bool_value", false)
- ->RenderString("string_value", "")
- ->RenderBytes("bytes_value", "")
+ ->RenderDouble("doubleValue", 0.0)
+ ->RenderFloat("floatValue", 0.0)
+ ->RenderInt64("int64Value", 0)
+ ->RenderUint64("uint64Value", 0)
+ ->RenderInt32("int32Value", 0)
+ ->RenderUint32("uint32Value", 0)
+ ->RenderBool("boolValue", false)
+ ->RenderString("stringValue", "")
+ ->RenderBytes("bytesValue", "")
->EndObject();
// Actual testing
@@ -91,42 +91,42 @@ TEST_P(DefaultValueObjectWriterTest, Empty) {
TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) {
// Set expectation
expects_.StartObject("")
- ->RenderDouble("double_value", 1.0)
- ->RenderFloat("float_value", 0.0)
- ->RenderInt64("int64_value", 0)
- ->RenderUint64("uint64_value", 0)
- ->RenderInt32("int32_value", 0)
- ->RenderUint32("uint32_value", 0)
- ->RenderBool("bool_value", false)
- ->RenderString("string_value", "")
+ ->RenderDouble("doubleValue", 1.0)
+ ->RenderFloat("floatValue", 0.0)
+ ->RenderInt64("int64Value", 0)
+ ->RenderUint64("uint64Value", 0)
+ ->RenderInt32("int32Value", 0)
+ ->RenderUint32("uint32Value", 0)
+ ->RenderBool("boolValue", false)
+ ->RenderString("stringValue", "")
->EndObject();
// Actual testing
- testing_->StartObject("")->RenderDouble("double_value", 1.0)->EndObject();
+ testing_->StartObject("")->RenderDouble("doubleValue", 1.0)->EndObject();
}
TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) {
// Set expectation
expects_.StartObject("")
- ->RenderDouble("double_value", 1.0)
- ->RenderFloat("float_value", 0.0)
- ->RenderInt64("int64_value", 0)
- ->RenderUint64("uint64_value", 0)
- ->RenderInt32("int32_value", 0)
- ->RenderUint32("uint32_value", 0)
- ->RenderBool("bool_value", false)
- ->RenderString("string_value", "")
+ ->RenderDouble("doubleValue", 1.0)
+ ->RenderFloat("floatValue", 0.0)
+ ->RenderInt64("int64Value", 0)
+ ->RenderUint64("uint64Value", 0)
+ ->RenderInt32("int32Value", 0)
+ ->RenderUint32("uint32Value", 0)
+ ->RenderBool("boolValue", false)
+ ->RenderString("stringValue", "")
->RenderString("unknown", "abc")
- ->StartObject("unknown_object")
+ ->StartObject("unknownObject")
->RenderString("unknown", "def")
->EndObject()
->EndObject();
// Actual testing
testing_->StartObject("")
- ->RenderDouble("double_value", 1.0)
+ ->RenderDouble("doubleValue", 1.0)
->RenderString("unknown", "abc")
- ->StartObject("unknown_object")
+ ->StartObject("unknownObject")
->RenderString("unknown", "def")
->EndObject()
->EndObject();
diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h
index 9b907df5..2699684d 100644
--- a/src/google/protobuf/util/internal/error_listener.h
+++ b/src/google/protobuf/util/internal/error_listener.h
@@ -37,7 +37,9 @@
#endif
#include <string>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/util/internal/location_tracker.h>
#include <google/protobuf/stubs/stringpiece.h>
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
index 92468959..f0e8fc88 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ b/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -34,7 +34,6 @@
#include <google/protobuf/stubs/status_macros.h>
namespace google {
-
namespace protobuf {
namespace util {
namespace converter {
@@ -138,7 +137,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
}
// Un-escaped '"' must be followed with a ']'.
if (i >= length - 1 || paths[i + 1] != ']') {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Map keys should be represented as [\"some_key\"]."));
@@ -150,7 +149,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
// Checks whether the key ends at the end of a path segment.
if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
paths[i + 1] != ')' && paths[i + 1] != '(') {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Map keys should be at the end of a path segment."));
@@ -162,7 +161,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
// We are not in a map key, look for the start of one.
if (paths[i] == '[') {
if (i >= length - 1 || paths[i + 1] != '\"') {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Map keys should be represented as [\"some_key\"]."));
@@ -198,7 +197,7 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
// Removes the last prefix after seeing a ')'.
if (i < length && paths[i] == ')') {
if (prefix.empty()) {
- return CreatePublicError(
+ return util::Status(
util::error::INVALID_ARGUMENT,
StrCat("Invalid FieldMask '", paths,
"'. Cannot find matching '(' for all ')'."));
@@ -208,16 +207,14 @@ util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
previous_position = i + 1;
}
if (in_map_key) {
- return CreatePublicError(
- util::error::INVALID_ARGUMENT,
- StrCat("Invalid FieldMask '", paths,
- "'. Cannot find matching ']' for all '['."));
+ return util::Status(util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Cannot find matching ']' for all '['."));
}
if (!prefix.empty()) {
- return CreatePublicError(
- util::error::INVALID_ARGUMENT,
- StrCat("Invalid FieldMask '", paths,
- "'. Cannot find matching ')' for all '('."));
+ return util::Status(util::error::INVALID_ARGUMENT,
+ StrCat("Invalid FieldMask '", paths,
+ "'. Cannot find matching ')' for all '('."));
}
return util::Status::OK;
}
diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
index 5ac23421..36dc8ef9 100644
--- a/src/google/protobuf/util/internal/json_escaping.cc
+++ b/src/google/protobuf/util/internal/json_escaping.cc
@@ -30,6 +30,7 @@
#include <google/protobuf/util/internal/json_escaping.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
namespace google {
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index 0c41515f..d88a81f9 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -33,6 +33,7 @@
#include <math.h>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/util/internal/json_escaping.h>
@@ -142,7 +143,7 @@ JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name,
StringPiece value) {
WritePrefix(name);
string base64;
- WebSafeBase64EscapeWithPadding(value, &base64);
+ Base64Escape(value, &base64);
WriteChar('"');
// TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
// directly to the stream, rather than first putting them
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
index df9a133e..dcd60601 100644
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -47,7 +47,8 @@ class JsonObjectWriterTest : public ::testing::Test {
JsonObjectWriterTest()
: str_stream_(new StringOutputStream(&output_)),
out_stream_(new CodedOutputStream(str_stream_)),
- ow_(NULL) {}
+ ow_(NULL) {
+ }
virtual ~JsonObjectWriterTest() {
delete ow_;
@@ -63,34 +64,36 @@ class JsonObjectWriterTest : public ::testing::Test {
TEST_F(JsonObjectWriterTest, EmptyRootObject) {
ow_ = new JsonObjectWriter("", out_stream_);
- ow_->StartObject("")->EndObject();
+ ow_->StartObject("")
+ ->EndObject();
EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, EmptyObject) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->RenderString("test", "value")
- ->StartObject("empty")
- ->EndObject()
- ->EndObject();
+ ->RenderString("test", "value")
+ ->StartObject("empty")
+ ->EndObject()
+ ->EndObject();
EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}",
output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, EmptyRootList) {
ow_ = new JsonObjectWriter("", out_stream_);
- ow_->StartList("")->EndList();
+ ow_->StartList("")
+ ->EndList();
EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, EmptyList) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->RenderString("test", "value")
- ->StartList("empty")
- ->EndList()
- ->EndObject();
+ ->RenderString("test", "value")
+ ->StartList("empty")
+ ->EndList()
+ ->EndObject();
EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -98,10 +101,10 @@ TEST_F(JsonObjectWriterTest, EmptyList) {
TEST_F(JsonObjectWriterTest, ObjectInObject) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->StartObject("nested")
- ->RenderString("field", "value")
- ->EndObject()
- ->EndObject();
+ ->StartObject("nested")
+ ->RenderString("field", "value")
+ ->EndObject()
+ ->EndObject();
EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -109,10 +112,10 @@ TEST_F(JsonObjectWriterTest, ObjectInObject) {
TEST_F(JsonObjectWriterTest, ListInObject) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->StartList("nested")
- ->RenderString("", "value")
- ->EndList()
- ->EndObject();
+ ->StartList("nested")
+ ->RenderString("", "value")
+ ->EndList()
+ ->EndObject();
EXPECT_EQ("{\"nested\":[\"value\"]}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -120,10 +123,10 @@ TEST_F(JsonObjectWriterTest, ListInObject) {
TEST_F(JsonObjectWriterTest, ObjectInList) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartList("")
- ->StartObject("")
- ->RenderString("field", "value")
- ->EndObject()
- ->EndList();
+ ->StartObject("")
+ ->RenderString("field", "value")
+ ->EndObject()
+ ->EndList();
EXPECT_EQ("[{\"field\":\"value\"}]",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -131,10 +134,10 @@ TEST_F(JsonObjectWriterTest, ObjectInList) {
TEST_F(JsonObjectWriterTest, ListInList) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartList("")
- ->StartList("")
- ->RenderString("", "value")
- ->EndList()
- ->EndList();
+ ->StartList("")
+ ->RenderString("", "value")
+ ->EndList()
+ ->EndList();
EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount()));
}
@@ -164,97 +167,95 @@ TEST_F(JsonObjectWriterTest, RenderPrimitives) {
output_.substr(0, out_stream_->ByteCount()));
}
-TEST_F(JsonObjectWriterTest, BytesEncodesAsWebSafeBase64) {
+TEST_F(JsonObjectWriterTest, BytesEncodesAsNonWebSafeBase64) {
string s;
s.push_back('\377');
s.push_back('\357');
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")->RenderBytes("bytes", s)->EndObject();
// Non-web-safe would encode this as "/+8="
- EXPECT_EQ("{\"bytes\":\"_-8=\"}",
+ EXPECT_EQ("{\"bytes\":\"/+8=\"}",
output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintList) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->StartList("items")
- ->RenderString("", "item1")
- ->RenderString("", "item2")
- ->RenderString("", "item3")
- ->EndList()
- ->StartList("empty")
- ->EndList()
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"items\": [\n"
- " \"item1\",\n"
- " \"item2\",\n"
- " \"item3\"\n"
- " ],\n"
- " \"empty\": []\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->StartList("items")
+ ->RenderString("", "item1")
+ ->RenderString("", "item2")
+ ->RenderString("", "item3")
+ ->EndList()
+ ->StartList("empty")
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"items\": [\n"
+ " \"item1\",\n"
+ " \"item2\",\n"
+ " \"item3\"\n"
+ " ],\n"
+ " \"empty\": []\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintObject) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->StartObject("items")
- ->RenderString("key1", "item1")
- ->RenderString("key2", "item2")
- ->RenderString("key3", "item3")
- ->EndObject()
- ->StartObject("empty")
- ->EndObject()
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"items\": {\n"
- " \"key1\": \"item1\",\n"
- " \"key2\": \"item2\",\n"
- " \"key3\": \"item3\"\n"
- " },\n"
- " \"empty\": {}\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->StartObject("items")
+ ->RenderString("key1", "item1")
+ ->RenderString("key2", "item2")
+ ->RenderString("key3", "item3")
+ ->EndObject()
+ ->StartObject("empty")
+ ->EndObject()
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"items\": {\n"
+ " \"key1\": \"item1\",\n"
+ " \"key2\": \"item2\",\n"
+ " \"key3\": \"item3\"\n"
+ " },\n"
+ " \"empty\": {}\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->StartList("list")
- ->StartObject("")
- ->EndObject()
- ->EndList()
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"list\": [\n"
- " {}\n"
- " ]\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->StartList("list")
+ ->StartObject("")
+ ->EndObject()
+ ->EndList()
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"list\": [\n"
+ " {}\n"
+ " ]\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) {
ow_ = new JsonObjectWriter(" ", out_stream_);
ow_->StartObject("")
- ->RenderBool("bool", true)
- ->RenderInt32("int", 42)
- ->EndObject();
- EXPECT_EQ(
- "{\n"
- " \"bool\": true,\n"
- " \"int\": 42\n"
- "}\n",
- output_.substr(0, out_stream_->ByteCount()));
+ ->RenderBool("bool", true)
+ ->RenderInt32("int", 42)
+ ->EndObject();
+ EXPECT_EQ("{\n"
+ " \"bool\": true,\n"
+ " \"int\": 42\n"
+ "}\n",
+ output_.substr(0, out_stream_->ByteCount()));
}
TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
ow_ = new JsonObjectWriter("", out_stream_);
- ow_->StartObject("")->RenderString("string", "'<>&amp;\\\"\r\n")->EndObject();
+ ow_->StartObject("")
+ ->RenderString("string", "'<>&amp;\\\"\r\n")
+ ->EndObject();
EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&amp;\\\\\\\"\\r\\n\"}",
output_.substr(0, out_stream_->ByteCount()));
}
@@ -262,13 +263,13 @@ TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
TEST_F(JsonObjectWriterTest, Stringification) {
ow_ = new JsonObjectWriter("", out_stream_);
ow_->StartObject("")
- ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
- ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
- ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
- ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
- ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
- ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
- ->EndObject();
+ ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
+ ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
+ ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
+ ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
+ ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
+ ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
+ ->EndObject();
EXPECT_EQ(
"{\"double_nan\":\"NaN\","
"\"float_nan\":\"NaN\","
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index d439a221..a7ef7fe2 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -40,6 +40,7 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/internal/object_writer.h>
@@ -104,16 +105,42 @@ JsonStreamParser::JsonStreamParser(ObjectWriter* ow)
parsed_(),
parsed_storage_(),
string_open_(0),
- utf8_storage_(),
- utf8_length_(0) {
+ chunk_storage_(),
+ coerce_to_utf8_(false) {
// Initialize the stack with a single value to be parsed.
stack_.push(VALUE);
}
JsonStreamParser::~JsonStreamParser() {}
+
util::Status JsonStreamParser::Parse(StringPiece json) {
- return ParseChunk(json);
+ StringPiece chunk = json;
+ // If we have leftovers from a previous chunk, append the new chunk to it
+ // and create a new StringPiece pointing at the string's data. This could
+ // be large but we rely on the chunks to be small, assuming they are
+ // fragments of a Cord.
+ if (!leftover_.empty()) {
+ // Don't point chunk to leftover_ because leftover_ will be updated in
+ // ParseChunk(chunk).
+ chunk_storage_.swap(leftover_);
+ json.AppendToString(&chunk_storage_);
+ chunk = StringPiece(chunk_storage_);
+ }
+
+ // Find the structurally valid UTF8 prefix and parse only that.
+ int n = internal::UTF8SpnStructurallyValid(chunk);
+ if (n > 0) {
+ util::Status status = ParseChunk(chunk.substr(0, n));
+
+ // Any leftover characters are stashed in leftover_ for later parsing when
+ // there is more data available.
+ chunk.substr(n).AppendToString(&leftover_);
+ return status;
+ } else {
+ chunk.CopyToString(&leftover_);
+ return util::Status::OK;
+ }
}
util::Status JsonStreamParser::FinishParse() {
@@ -122,9 +149,22 @@ util::Status JsonStreamParser::FinishParse() {
if (stack_.empty() && leftover_.empty()) {
return util::Status::OK;
}
+
+ // Storage for UTF8-coerced string.
+ google::protobuf::scoped_array<char> utf8;
+ if (coerce_to_utf8_) {
+ utf8.reset(new char[leftover_.size()]);
+ char* coerced = internal::UTF8CoerceToStructurallyValid(leftover_, utf8.get(), ' ');
+ p_ = json_ = StringPiece(coerced, leftover_.size());
+ } else {
+ if (!internal::IsStructurallyValidUTF8(leftover_)) {
+ return ReportFailure("Encountered non UTF-8 code points.");
+ }
+ p_ = json_ = leftover_;
+ }
+
// Parse the remainder in finishing mode, which reports errors for things like
// unterminated strings or unknown tokens that would normally be retried.
- p_ = json_ = StringPiece(leftover_);
finishing_ = true;
util::Status result = RunParser();
if (result.ok()) {
@@ -137,16 +177,10 @@ util::Status JsonStreamParser::FinishParse() {
}
util::Status JsonStreamParser::ParseChunk(StringPiece chunk) {
- // If we have leftovers from a previous chunk, append the new chunk to it and
- // create a new StringPiece pointing at the string's data. This could be
- // large but we rely on the chunks to be small, assuming they are fragments
- // of a Cord.
- if (!leftover_.empty()) {
- chunk.AppendToString(&leftover_);
- p_ = json_ = StringPiece(leftover_);
- } else {
- p_ = json_ = chunk;
- }
+ // Do not do any work if the chunk is empty.
+ if (chunk.empty()) return util::Status::OK;
+
+ p_ = json_ = chunk;
finishing_ = false;
util::Status result = RunParser();
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index 17b094ae..0278c28f 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -75,12 +75,14 @@ class LIBPROTOBUF_EXPORT JsonStreamParser {
explicit JsonStreamParser(ObjectWriter* ow);
virtual ~JsonStreamParser();
- // Parse a JSON string (UTF-8 encoded).
+ // Parses a UTF-8 encoded JSON string from a StringPiece.
util::Status Parse(StringPiece json);
+
// Finish parsing the JSON string.
util::Status FinishParse();
+
private:
enum TokenType {
BEGIN_STRING, // " or '
@@ -239,11 +241,11 @@ class LIBPROTOBUF_EXPORT JsonStreamParser {
// A value of 0 indicates that string parsing is not in process.
char string_open_;
- // Storage for utf8-coerced bytes.
- google::protobuf::scoped_array<char> utf8_storage_;
+ // Storage for the chunk that are being parsed in ParseChunk().
+ string chunk_storage_;
- // Length of the storage for utf8-coerced bytes.
- int utf8_length_;
+ // Whether to allow non UTF-8 encoded input and replace invalid code points.
+ bool coerce_to_utf8_;
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser);
};
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index b0775a2f..c833ed1f 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -30,6 +30,7 @@
#include <google/protobuf/util/internal/json_stream_parser.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/time.h>
#include <google/protobuf/util/internal/expecting_objectwriter.h>
@@ -85,7 +86,7 @@ class JsonStreamParserTest : public ::testing::Test {
JsonStreamParserTest() : mock_(), ow_(&mock_) {}
virtual ~JsonStreamParserTest() {}
- util::Status RunTest(StringPiece json, int split) {
+ util::Status RunTest(StringPiece json, int split, bool coerce_utf8 = false) {
JsonStreamParser parser(&mock_);
// Special case for split == length, test parsing one character at a time.
@@ -115,8 +116,8 @@ class JsonStreamParserTest : public ::testing::Test {
return result;
}
- void DoTest(StringPiece json, int split) {
- util::Status result = RunTest(json, split);
+ void DoTest(StringPiece json, int split, bool coerce_utf8 = false) {
+ util::Status result = RunTest(json, split, coerce_utf8);
if (!result.ok()) {
GOOGLE_LOG(WARNING) << result;
}
@@ -337,14 +338,26 @@ TEST_F(JsonStreamParserTest, ObjectValues) {
}
}
+
+TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
+ StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}";
+ for (int i = 0; i <= json.length(); ++i) {
+ DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+ }
+ json = "{\"address\": \"חרושת 23,\xFFרעננה, ישראל\"}";
+ for (int i = 0; i <= json.length(); ++i) {
+ DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+ }
+}
+
#ifndef _MSC_VER
// - unicode handling in strings
TEST_F(JsonStreamParserTest, UnicodeEscaping) {
StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
for (int i = 0; i <= str.length(); ++i) {
// TODO(xiaofeng): Figure out what default encoding to use for JSON strings.
- // In protobuf we use UTF-8 for strings, but for JSON we probably should allow
- // different encodings?
+ // In protobuf we use UTF-8 for strings, but for JSON we probably should
+ // allow different encodings?
ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList();
DoTest(str, i);
}
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 53a0e47a..18bb2772 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -33,6 +33,7 @@
#include <utility>
#include <google/protobuf/stubs/casts.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/stubs/time.h>
@@ -96,7 +97,7 @@ ProtoStreamObjectSource::ProtoStreamObjectSource(
}
ProtoStreamObjectSource::ProtoStreamObjectSource(
- google::protobuf::io::CodedInputStream* stream, TypeInfo* typeinfo,
+ google::protobuf::io::CodedInputStream* stream, const TypeInfo* typeinfo,
const google::protobuf::Type& type)
: stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) {
GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
@@ -156,7 +157,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
last_tag = tag;
field = FindAndVerifyField(type, tag);
if (field != NULL) {
- field_name = field->name();
+ field_name = field->json_name();
}
}
if (field == NULL) {
@@ -214,7 +215,7 @@ StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
const google::protobuf::Field* field, StringPiece name, uint32 list_tag,
ObjectWriter* ow) const {
const google::protobuf::Type* field_type =
- typeinfo_->GetType(field->type_url());
+ typeinfo_->GetTypeByTypeUrl(field->type_url());
uint32 tag_to_return = 0;
if (IsPackable(*field) &&
list_tag ==
@@ -784,7 +785,8 @@ Status ProtoStreamObjectSource::RenderField(
// Get the nested enum type for this field.
// TODO(skarvaje): Avoid string manipulation. Find ways to speed this
// up.
- const google::protobuf::Enum* en = typeinfo_->GetEnum(field->type_url());
+ const google::protobuf::Enum* en =
+ typeinfo_->GetEnumByTypeUrl(field->type_url());
// Lookup the name of the enum, and render that. Skips unknown enums.
if (en != NULL) {
const google::protobuf::EnumValue* enum_value =
@@ -819,7 +821,7 @@ Status ProtoStreamObjectSource::RenderField(
int old_limit = stream_->PushLimit(buffer32);
// Get the nested message type for this field.
const google::protobuf::Type* type =
- typeinfo_->GetType(field->type_url());
+ typeinfo_->GetTypeByTypeUrl(field->type_url());
if (type == NULL) {
return Status(util::error::INTERNAL,
StrCat("Invalid configuration. Could not find the type: ",
@@ -928,7 +930,8 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString(
// Get the nested enum type for this field.
// TODO(skarvaje): Avoid string manipulation. Find ways to speed this
// up.
- const google::protobuf::Enum* en = typeinfo_->GetEnum(field.type_url());
+ const google::protobuf::Enum* en =
+ typeinfo_->GetEnumByTypeUrl(field.type_url());
// Lookup the name of the enum, and render that. Skips unknown enums.
if (en != NULL) {
const google::protobuf::EnumValue* enum_value =
@@ -962,7 +965,7 @@ const string ProtoStreamObjectSource::ReadFieldValueAsString(
bool ProtoStreamObjectSource::IsMap(
const google::protobuf::Field& field) const {
const google::protobuf::Type* field_type =
- typeinfo_->GetType(field.type_url());
+ typeinfo_->GetTypeByTypeUrl(field.type_url());
// TODO(xiaofeng): Unify option names.
return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE &&
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 4a4e6bbf..845437f5 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -46,7 +46,6 @@
#include <google/protobuf/stubs/statusor.h>
-
namespace google {
namespace protobuf {
class Field;
@@ -61,7 +60,10 @@ namespace converter {
class TypeInfo;
// An ObjectSource that can parse a stream of bytes as a protocol buffer.
-// This implementation uses a tech Type for tag lookup.
+// Its WriteTo() method can be given an ObjectWriter.
+// This implementation uses a google.protobuf.Type for tag and name lookup.
+// The field names are converted into lower camel-case when writing to the
+// ObjectWriter.
//
// Sample usage: (suppose input is: string proto)
// ArrayInputStream arr_stream(proto.data(), proto.size());
@@ -93,7 +95,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
private:
ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream,
- TypeInfo* typeinfo,
+ const TypeInfo* typeinfo,
const google::protobuf::Type& type);
// Function that renders a well known type with a modified behavior.
typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*,
@@ -226,7 +228,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
// Type information for all the types used in the descriptor. Used to find
// google::protobuf::Type of nested messages/enums.
- TypeInfo* typeinfo_;
+ const TypeInfo* typeinfo_;
// Whether this class owns the typeinfo_ object. If true the typeinfo_ object
// should be deleted in the destructor.
bool own_typeinfo_;
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 4cc62410..f6e5ee7a 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -117,61 +117,61 @@ class ProtostreamObjectSourceTest
void PrepareExpectingObjectWriterForRepeatedPrimitive() {
ow_.StartObject("")
- ->StartList("rep_fix32")
+ ->StartList("repFix32")
->RenderUint32("", bit_cast<uint32>(3201))
->RenderUint32("", bit_cast<uint32>(0))
->RenderUint32("", bit_cast<uint32>(3202))
->EndList()
- ->StartList("rep_u32")
+ ->StartList("repU32")
->RenderUint32("", bit_cast<uint32>(3203))
->RenderUint32("", bit_cast<uint32>(0))
->EndList()
- ->StartList("rep_i32")
+ ->StartList("repI32")
->RenderInt32("", 0)
->RenderInt32("", 3204)
->RenderInt32("", 3205)
->EndList()
- ->StartList("rep_sf32")
+ ->StartList("repSf32")
->RenderInt32("", 3206)
->RenderInt32("", 0)
->EndList()
- ->StartList("rep_s32")
+ ->StartList("repS32")
->RenderInt32("", 0)
->RenderInt32("", 3207)
->RenderInt32("", 3208)
->EndList()
- ->StartList("rep_fix64")
+ ->StartList("repFix64")
->RenderUint64("", bit_cast<uint64>(6401LL))
->RenderUint64("", bit_cast<uint64>(0LL))
->EndList()
- ->StartList("rep_u64")
+ ->StartList("repU64")
->RenderUint64("", bit_cast<uint64>(0LL))
->RenderUint64("", bit_cast<uint64>(6402LL))
->RenderUint64("", bit_cast<uint64>(6403LL))
->EndList()
- ->StartList("rep_i64")
+ ->StartList("repI64")
->RenderInt64("", 6404L)
->RenderInt64("", 0L)
->EndList()
- ->StartList("rep_sf64")
+ ->StartList("repSf64")
->RenderInt64("", 0L)
->RenderInt64("", 6405L)
->RenderInt64("", 6406L)
->EndList()
- ->StartList("rep_s64")
+ ->StartList("repS64")
->RenderInt64("", 6407L)
->RenderInt64("", 0L)
->EndList()
- ->StartList("rep_float")
+ ->StartList("repFloat")
->RenderFloat("", 0.0f)
->RenderFloat("", 32.1f)
->RenderFloat("", 32.2f)
->EndList()
- ->StartList("rep_double")
+ ->StartList("repDouble")
->RenderDouble("", 64.1L)
->RenderDouble("", 0.0L)
->EndList()
- ->StartList("rep_bool")
+ ->StartList("repBool")
->RenderBool("", true)
->RenderBool("", false)
->EndList()
@@ -317,11 +317,11 @@ TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
primitive.add_rep_str("String Two");
primitive.add_rep_bytes("Some Bytes");
- ow_.StartList("rep_str")
+ ow_.StartList("repStr")
->RenderString("", "String One")
->RenderString("", "String Two")
->EndList()
- ->StartList("rep_bytes")
+ ->StartList("repBytes")
->RenderBytes("", "Some Bytes")
->EndList();
DoTest(primitive, Primitive::descriptor());
@@ -794,16 +794,16 @@ TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
ow_.StartObject("")
->RenderString("id", "1")
- ->RenderString("single_mask", "path1,snakeCasePath2")
- ->StartList("repeated_mask")
+ ->RenderString("singleMask", "path1,snakeCasePath2")
+ ->StartList("repeatedMask")
->RenderString("", "path3")
->RenderString("", "snakeCasePath4,path5")
->EndList()
- ->StartList("nested_mask")
+ ->StartList("nestedMask")
->StartObject("")
->RenderString("data", "data")
- ->RenderString("single_mask", "nested.path1,nestedField.snakeCasePath2")
- ->StartList("repeated_mask")
+ ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
+ ->StartList("repeatedMask")
->RenderString("", "nestedField.path3,nested.snakeCasePath4")
->RenderString("", "nested.path5")
->RenderString("",
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index f9ddbf32..87f504e0 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -74,7 +74,7 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter(
tracker_(new ObjectLocationTracker()) {}
ProtoStreamObjectWriter::ProtoStreamObjectWriter(
- TypeInfo* typeinfo, const google::protobuf::Type& type,
+ const TypeInfo* typeinfo, const google::protobuf::Type& type,
strings::ByteSink* output, ErrorListener* listener)
: master_type_(type),
typeinfo_(typeinfo),
@@ -91,14 +91,19 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter(
tracker_(new ObjectLocationTracker()) {}
ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
- // Cleanup explicitly in order to avoid destructor stack overflow when input
- // is deeply nested.
- while (element_ != NULL) {
- element_.reset(element_->pop());
- }
if (own_typeinfo_) {
delete typeinfo_;
}
+ if (element_ == NULL) return;
+ // Cleanup explicitly in order to avoid destructor stack overflow when input
+ // is deeply nested.
+ // Cast to BaseElement to avoid doing additional checks (like missing fields)
+ // during pop().
+ google::protobuf::scoped_ptr<BaseElement> element(
+ static_cast<BaseElement*>(element_.get())->pop<BaseElement>());
+ while (element != NULL) {
+ element.reset(element->pop<BaseElement>());
+ }
}
namespace {
@@ -454,7 +459,7 @@ void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
}
ProtoStreamObjectWriter::ProtoElement::ProtoElement(
- TypeInfo* typeinfo, const google::protobuf::Type& type,
+ const TypeInfo* typeinfo, const google::protobuf::Type& type,
ProtoStreamObjectWriter* enclosing)
: BaseElement(NULL),
ow_(enclosing),
@@ -586,6 +591,14 @@ string ProtoStreamObjectWriter::ProtoElement::ToString() const {
return loc.empty() ? "." : loc;
}
+bool ProtoStreamObjectWriter::ProtoElement::OneofIndexTaken(int32 index) {
+ return ContainsKey(oneof_indices_, index);
+}
+
+void ProtoStreamObjectWriter::ProtoElement::TakeOneofIndex(int32 index) {
+ InsertIfNotPresent(&oneof_indices_, index);
+}
+
inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name,
StringPiece message) {
listener_->InvalidName(location(), ToSnakeCase(unknown_name), message);
@@ -655,6 +668,13 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
return this;
}
+ // Check to see if this field is a oneof and that no oneof in that group has
+ // already been set.
+ if (!ValidOneof(*field, name)) {
+ ++invalid_depth_;
+ return this;
+ }
+
if (field->type_url() == GetFullTypeWithUrl(kStructType)) {
// Start a struct object.
StartStruct(field);
@@ -932,6 +952,14 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) {
// Also we ignore if the field is not found here as it is caught later.
field = typeinfo_->FindField(&element_->type(), name);
+ // Only check for oneof collisions on the first StartList call. We identify
+ // the first call with !name.empty() check. Subsequent list element calls
+ // will not have the name filled.
+ if (!name.empty() && field && !ValidOneof(*field, name)) {
+ ++invalid_depth_;
+ return this;
+ }
+
// It is an error to try to bind to map, which behind the scenes is a list.
if (field && IsMap(*field)) {
// Push field to stack for error location tracking & reporting.
@@ -1080,9 +1108,9 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
data.ValueAsStringOrDefault("")));
}
- // TODO(tsun): figure out how to do proto descriptor based snake case
- // conversions as much as possible. Because ToSnakeCase sometimes returns the
- // wrong value.
+// TODO(tsun): figure out how to do proto descriptor based snake case
+// conversions as much as possible. Because ToSnakeCase sometimes returns the
+// wrong value.
google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
NewPermanentCallback(&RenderOneFieldPath, ow));
return DecodeCompactFieldMaskPaths(data.str(), callback.get());
@@ -1154,6 +1182,7 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
const google::protobuf::Field* field = NULL;
string type_url;
bool is_map_entry = false;
+ // We are at the root when element_ == NULL.
if (element_ == NULL) {
type_url = GetFullTypeWithUrl(master_type_.name());
} else {
@@ -1166,6 +1195,11 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
if (field == NULL) {
return this;
}
+
+ // Check to see if this field is a oneof and that no oneof in that group has
+ // already been set.
+ if (!ValidOneof(*field, name)) return this;
+
type_url = field->type_url();
}
@@ -1314,7 +1348,8 @@ void ProtoStreamObjectWriter::RenderSimpleDataPiece(
}
case google::protobuf::Field_Kind_TYPE_ENUM: {
status = WriteEnum(field.number(), data,
- typeinfo_->GetEnum(field.type_url()), stream_.get());
+ typeinfo_->GetEnumByTypeUrl(field.type_url()),
+ stream_.get());
break;
}
default: // TYPE_GROUP or TYPE_MESSAGE
@@ -1401,6 +1436,24 @@ ProtoStreamObjectWriter::GetElementType(const google::protobuf::Type& type) {
}
}
+bool ProtoStreamObjectWriter::ValidOneof(const google::protobuf::Field& field,
+ StringPiece unnormalized_name) {
+ if (element_ == NULL) return true;
+
+ if (field.oneof_index() > 0) {
+ if (element_->OneofIndexTaken(field.oneof_index())) {
+ InvalidValue(
+ "oneof",
+ StrCat("oneof field '",
+ element_->type().oneofs(field.oneof_index() - 1),
+ "' is already set. Cannot set '", unnormalized_name, "'"));
+ return false;
+ }
+ element_->TakeOneofIndex(field.oneof_index());
+ }
+ return true;
+}
+
const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed(
StringPiece name, bool is_list) {
if (invalid_depth_ > 0) {
@@ -1450,7 +1503,7 @@ const google::protobuf::Field* ProtoStreamObjectWriter::Lookup(
const google::protobuf::Type* ProtoStreamObjectWriter::LookupType(
const google::protobuf::Field* field) {
return (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE
- ? typeinfo_->GetType(field->type_url())
+ ? typeinfo_->GetTypeByTypeUrl(field->type_url())
: &element_->type());
}
@@ -1539,7 +1592,7 @@ bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) {
return false;
}
const google::protobuf::Type* field_type =
- typeinfo_->GetType(field.type_url());
+ typeinfo_->GetTypeByTypeUrl(field.type_url());
return GetBoolOptionOrDefault(field_type->options(),
"google.protobuf.MessageOptions.map_entry", false);
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
index eb4a59f9..f11c47c0 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -71,7 +71,7 @@ class ObjectLocationTracker;
// It also supports streaming.
class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter {
public:
- // Constructor. Does not take ownership of any parameter passed in.
+// Constructor. Does not take ownership of any parameter passed in.
ProtoStreamObjectWriter(TypeResolver* type_resolver,
const google::protobuf::Type& type,
strings::ByteSink* output, ErrorListener* listener);
@@ -82,20 +82,17 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
virtual ProtoStreamObjectWriter* EndObject();
virtual ProtoStreamObjectWriter* StartList(StringPiece name);
virtual ProtoStreamObjectWriter* EndList();
- virtual ProtoStreamObjectWriter* RenderBool(StringPiece name,
- bool value) {
+ virtual ProtoStreamObjectWriter* RenderBool(StringPiece name, bool value) {
return RenderDataPiece(name, DataPiece(value));
}
- virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name,
- int32 value) {
+ virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name, int32 value) {
return RenderDataPiece(name, DataPiece(value));
}
virtual ProtoStreamObjectWriter* RenderUint32(StringPiece name,
uint32 value) {
return RenderDataPiece(name, DataPiece(value));
}
- virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name,
- int64 value) {
+ virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name, int64 value) {
return RenderDataPiece(name, DataPiece(value));
}
virtual ProtoStreamObjectWriter* RenderUint64(StringPiece name,
@@ -106,8 +103,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
double value) {
return RenderDataPiece(name, DataPiece(value));
}
- virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name,
- float value) {
+ virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name, float value) {
return RenderDataPiece(name, DataPiece(value));
}
virtual ProtoStreamObjectWriter* RenderString(StringPiece name,
@@ -217,7 +213,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
};
// Constructor for the root element. No parent nor field.
- ProtoElement(TypeInfo* typeinfo, const google::protobuf::Type& type,
+ ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type,
ProtoStreamObjectWriter* enclosing);
// Constructor for a field of an element.
@@ -256,6 +252,13 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
return static_cast<ProtoElement*>(BaseElement::parent());
}
+ // Returns true if the index is already taken by a preceeding oneof input.
+ bool OneofIndexTaken(int32 index);
+
+ // Marks the oneof 'index' as taken. Future inputs to this oneof will
+ // generate an error.
+ void TakeOneofIndex(int32 index);
+
private:
// Used for access to variables of the enclosing instance of
// ProtoStreamObjectWriter.
@@ -269,7 +272,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
const google::protobuf::Field* field_;
// TypeInfo to lookup types.
- TypeInfo* typeinfo_;
+ const TypeInfo* typeinfo_;
// Additional variables if this element is a message:
// (Root element is always a message).
@@ -289,6 +292,10 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
// The type of this element, see enum for permissible types.
ElementType element_type_;
+ // Set of oneof indices already seen for the type_. Used to validate
+ // incoming messages so no more than one oneof is set.
+ hash_set<int32> oneof_indices_;
+
GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
};
@@ -298,7 +305,7 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
int size;
};
- ProtoStreamObjectWriter(TypeInfo* typeinfo,
+ ProtoStreamObjectWriter(const TypeInfo* typeinfo,
const google::protobuf::Type& type,
strings::ByteSink* output, ErrorListener* listener);
@@ -407,11 +414,19 @@ class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter
static ProtoElement::ElementType GetElementType(
const google::protobuf::Type& type);
+ // Returns true if the field for type_ can be set as a oneof. If field is not
+ // a oneof type, this function does nothing and returns true.
+ // If another field for this oneof is already set, this function returns
+ // false. It also calls the appropriate error callback.
+ // unnormalized_name is used for error string.
+ bool ValidOneof(const google::protobuf::Field& field,
+ StringPiece unnormalized_name);
+
// Variables for describing the structure of the input tree:
// master_type_: descriptor for the whole protobuf message.
// typeinfo_ : the TypeInfo object to lookup types.
const google::protobuf::Type& master_type_;
- TypeInfo* typeinfo_;
+ const TypeInfo* typeinfo_;
// Whether we own the typeinfo_ object.
bool own_typeinfo_;
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
index bd4f29f5..96e5ccfb 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -49,6 +49,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/util/internal/testdata/anys.pb.h>
#include <google/protobuf/util/internal/testdata/maps.pb.h>
+#include <google/protobuf/util/internal/testdata/oneofs.pb.h>
#include <google/protobuf/util/internal/testdata/struct.pb.h>
#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
#include <gtest/gtest.h>
@@ -75,6 +76,7 @@ using ::testing::_;
using ::testing::Args;
using google::protobuf::testing::anys::AnyM;
using google::protobuf::testing::anys::AnyOut;
+using google::protobuf::testing::oneofs::OneOfsRequest;
using google::protobuf::testing::FieldMaskTest;
using google::protobuf::testing::maps::MapIn;
using google::protobuf::testing::structs::StructType;
@@ -143,7 +145,7 @@ class BaseProtoStreamObjectWriterTest
void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
const google::protobuf::Type* GetType(const Descriptor* descriptor) {
- return helper_.GetTypeInfo()->GetType(GetTypeUrl(descriptor));
+ return helper_.GetTypeInfo()->GetTypeByTypeUrl(GetTypeUrl(descriptor));
}
testing::TypeInfoTestHelper helper_;
@@ -854,11 +856,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
- StringPiece(
- "Field 'ts', Illegal timestamp format; timestamps "
- "must end with 'Z'")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Illegal timestamp format; timestamps "
+ "must end with 'Z'")));
ow_->StartObject("")->RenderString("ts", "")->EndObject();
CheckOutput(timestamp);
@@ -883,11 +884,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
- StringPiece(
- "Field 'ts', Invalid time format, failed to parse nano "
- "seconds")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
+ StringPiece("Field 'ts', Invalid time format, failed to parse nano "
+ "seconds")));
ow_->StartObject("")
->RenderString("ts", "1970-01-01T00:00:00.ABZ")
@@ -919,11 +919,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Duration"),
- StringPiece(
- "Field 'dur', Illegal duration format; duration must "
- "end with 's'")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece("Field 'dur', Illegal duration format; duration must "
+ "end with 's'")));
ow_->StartObject("")->RenderString("dur", "")->EndObject();
CheckOutput(duration);
@@ -934,11 +933,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Duration"),
- StringPiece(
- "Field 'dur', Invalid duration format, failed to parse "
- "seconds")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece("Field 'dur', Invalid duration format, failed to parse "
+ "seconds")));
ow_->StartObject("")->RenderString("dur", "s")->EndObject();
CheckOutput(duration);
@@ -949,11 +947,10 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.Duration"),
- StringPiece(
- "Field 'dur', Invalid duration format, failed to "
- "parse nanos seconds")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
+ StringPiece("Field 'dur', Invalid duration format, failed to "
+ "parse nanos seconds")));
ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
CheckOutput(duration);
@@ -1174,10 +1171,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
AnyOut any;
- EXPECT_CALL(listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Missing or invalid @type for any field in "
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece("Missing or invalid @type for any field in "
"google.protobuf.testing.anys.AnyOut")));
ow_->StartObject("")
@@ -1192,10 +1189,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
AnyOut any;
- EXPECT_CALL(listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Missing or invalid @type for any field in "
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece("Missing or invalid @type for any field in "
"google.protobuf.testing.anys.AnyOut")));
ow_->StartObject("")
@@ -1210,10 +1207,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
AnyOut any;
- EXPECT_CALL(listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Missing or invalid @type for any field in "
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(_, StringPiece("Any"),
+ StringPiece("Missing or invalid @type for any field in "
"google.protobuf.testing.anys.AnyOut")));
ow_->StartObject("")
@@ -1227,13 +1224,12 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) {
AnyOut any;
- EXPECT_CALL(
- listener_,
- InvalidValue(_, StringPiece("Any"),
- StringPiece(
- "Invalid type URL, type URLs must be of the form "
- "'type.googleapis.com/<typename>', got: "
- "type.other.com/some.Type")));
+ EXPECT_CALL(listener_,
+ InvalidValue(
+ _, StringPiece("Any"),
+ StringPiece("Invalid type URL, type URLs must be of the form "
+ "'type.googleapis.com/<typename>', got: "
+ "type.other.com/some.Type")));
ow_->StartObject("")
->StartObject("any")
@@ -1401,11 +1397,10 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) {
TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
- "Cannot find matching '(' for all ')'.")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
+ "Cannot find matching '(' for all ')'.")));
ow_->StartObject("");
ow_->RenderString("id", "1");
@@ -1448,12 +1443,11 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest,
MapKeyMustBeAtTheEndOfAPathSegment) {
EXPECT_CALL(
listener_,
- InvalidValue(_,
- StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask "
- "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
- "Map keys should be at the end of a path segment.")));
+ InvalidValue(
+ _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
+ StringPiece("Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
+ "Map keys should be at the end of a path segment.")));
ow_->StartObject("");
ow_->RenderString("single_mask",
@@ -1466,10 +1460,9 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) {
listener_,
InvalidValue(_,
StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask "
- "'path.to.map[\"key1\"'. Map keys should be "
- "represented as [\"some_key\"].")));
+ StringPiece("Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"key1\"'. Map keys should be "
+ "represented as [\"some_key\"].")));
ow_->StartObject("");
ow_->RenderString("single_mask", "path.to.map[\"key1\"");
@@ -1481,10 +1474,9 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) {
listener_,
InvalidValue(_,
StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
- StringPiece(
- "Field 'single_mask', Invalid FieldMask "
- "'path.to.map[\"ke\"y1\"]'. Map keys should be "
- "represented as [\"some_key\"].")));
+ StringPiece("Field 'single_mask', Invalid FieldMask "
+ "'path.to.map[\"ke\"y1\"]'. Map keys should be "
+ "represented as [\"some_key\"].")));
ow_->StartObject("");
ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]");
@@ -1507,6 +1499,192 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) {
CheckOutput(expected);
}
+class ProtoStreamObjectWriterOneOfsTest
+ : public BaseProtoStreamObjectWriterTest {
+ protected:
+ ProtoStreamObjectWriterOneOfsTest() {
+ vector<const Descriptor*> descriptors;
+ descriptors.push_back(OneOfsRequest::descriptor());
+ descriptors.push_back(google::protobuf::Struct::descriptor());
+ ResetTypeInfo(descriptors);
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
+ ProtoStreamObjectWriterOneOfsTest,
+ ::testing::Values(
+ testing::USE_TYPE_RESOLVER));
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForPrimitiveTypesTest) {
+ EXPECT_CALL(
+ listener_,
+ InvalidValue(
+ _, StringPiece("oneof"),
+ StringPiece(
+ "oneof field 'data' is already set. Cannot set 'intData'")));
+
+ ow_->StartObject("");
+ ow_->RenderString("strData", "blah");
+ ow_->RenderString("intData", "123");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForMessageTypesPrimitiveFirstTest) {
+ // Test for setting primitive oneof field first and then message field.
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'messageData'")));
+
+ // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } }
+ ow_->StartObject("");
+ ow_->RenderString("strData", "blah");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForMessageTypesMessageFirstTest) {
+ // Test for setting message oneof field first and then primitive field.
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'strData'")));
+
+ // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" }
+ ow_->StartObject("");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->RenderString("strData", "blah");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForStructTypesPrimitiveFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'structData'")));
+
+ // JSON: { "strData": "blah", "structData": { "a": "b" } }
+ ow_->StartObject("");
+ ow_->RenderString("strData", "blah");
+ ow_->StartObject("structData");
+ ow_->RenderString("a", "b");
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForStructTypesStructFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'strData'")));
+
+ // JSON: { "structData": { "a": "b" }, "strData": "blah" }
+ ow_->StartObject("");
+ ow_->StartObject("structData");
+ ow_->RenderString("a", "b");
+ ow_->EndObject();
+ ow_->RenderString("strData", "blah");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForStructValueTypesTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'valueData'")));
+
+ // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } }
+ ow_->StartObject("");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->StartObject("valueData");
+ ow_->RenderString("a", "b");
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'tsData'")));
+
+ // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" }
+ ow_->StartObject("");
+ ow_->RenderInt32("intData", 123);
+ ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForWellKnownTypesWktFirstTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'intData'")));
+
+ // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 }
+ ow_->StartObject("");
+ ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+ ow_->RenderInt32("intData", 123);
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForWellKnownTypesAndMessageTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'messageData'")));
+
+ // JSON: { "tsData": "1970-01-02T01:00:00.000Z",
+ // "messageData": { "dataValue": 123 } }
+ ow_->StartObject("");
+ ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
+ ow_->StartObject("messageData");
+ ow_->RenderInt32("dataValue", 123);
+ ow_->EndObject();
+ ow_->EndObject();
+}
+
+TEST_P(ProtoStreamObjectWriterOneOfsTest,
+ MultipleOneofsFailForOneofWithinAnyTest) {
+ EXPECT_CALL(listener_,
+ InvalidValue(_, StringPiece("oneof"),
+ StringPiece("oneof field 'data' is already set. "
+ "Cannot set 'intData'")));
+
+ using google::protobuf::testing::oneofs::OneOfsRequest;
+ // JSON:
+ // { "anyData":
+ // { "@type":
+ // "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest",
+ // "strData": "blah",
+ // "intData": 123
+ // }
+ // }
+ ow_->StartObject("");
+ ow_->StartObject("anyData");
+ ow_->RenderString(
+ "@type",
+ "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest");
+ ow_->RenderString("strData", "blah");
+ ow_->RenderInt32("intData", 123);
+ ow_->EndObject();
+}
+
} // namespace converter
} // namespace util
} // namespace protobuf
diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter.h b/src/google/protobuf/util/internal/snake2camel_objectwriter.h
index 1a32bc56..9b4ab8a3 100644
--- a/src/google/protobuf/util/internal/snake2camel_objectwriter.h
+++ b/src/google/protobuf/util/internal/snake2camel_objectwriter.h
@@ -58,9 +58,7 @@ class Snake2CamelObjectWriter : public ObjectWriter {
// ObjectWriter methods.
virtual Snake2CamelObjectWriter* StartObject(StringPiece name) {
- ow_->StartObject(ShouldNormalizeCase(name)
- ? StringPiece(StringPiece(ToCamelCase(name)))
- : name);
+ ow_->StartObject(name);
return this;
}
@@ -70,8 +68,7 @@ class Snake2CamelObjectWriter : public ObjectWriter {
}
virtual Snake2CamelObjectWriter* StartList(StringPiece name) {
- ow_->StartList(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name))
- : name);
+ ow_->StartList(name);
return this;
}
@@ -81,76 +78,57 @@ class Snake2CamelObjectWriter : public ObjectWriter {
}
virtual Snake2CamelObjectWriter* RenderBool(StringPiece name, bool value) {
- ow_->RenderBool(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderBool(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderInt32(StringPiece name, int32 value) {
- ow_->RenderInt32(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderInt32(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderUint32(StringPiece name,
uint32 value) {
- ow_->RenderUint32(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderUint32(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderInt64(StringPiece name, int64 value) {
- ow_->RenderInt64(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderInt64(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderUint64(StringPiece name,
uint64 value) {
- ow_->RenderUint64(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderUint64(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderDouble(StringPiece name,
double value) {
- ow_->RenderDouble(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderDouble(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderFloat(StringPiece name, float value) {
- ow_->RenderFloat(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderFloat(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderString(StringPiece name,
StringPiece value) {
- ow_->RenderString(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderString(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderBytes(StringPiece name,
StringPiece value) {
- ow_->RenderBytes(
- ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name,
- value);
+ ow_->RenderBytes(name, value);
return this;
}
virtual Snake2CamelObjectWriter* RenderNull(StringPiece name) {
- ow_->RenderNull(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name))
- : name);
+ ow_->RenderNull(name);
return this;
}
diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
index 67388c3b..e5db844c 100644
--- a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc
@@ -47,263 +47,9 @@ class Snake2CamelObjectWriterTest : public ::testing::Test {
Snake2CamelObjectWriter testing_;
};
-TEST_F(Snake2CamelObjectWriterTest, Empty) {
- // Set expectation
- expects_.StartObject("")->EndObject();
-
- // Actual testing
- testing_.StartObject("")->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, UnderscoresOnly) {
- // Set expectation
- expects_.StartObject("")
- ->RenderInt32("", 1)
- ->RenderInt32("", 2)
- ->RenderInt32("", 3)
- ->RenderInt32("", 4)
- ->RenderInt32("", 5)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderInt32("_", 1)
- ->RenderInt32("__", 2)
- ->RenderInt32("___", 3)
- ->RenderInt32("____", 4)
- ->RenderInt32("_____", 5)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, LowercaseOnly) {
- // Set expectation
- expects_.StartObject("")
- ->RenderString("key", "value")
- ->RenderString("abracadabra", "magic")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("key", "value")
- ->RenderString("abracadabra", "magic")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, UppercaseOnly) {
- // Set expectation
- expects_.StartObject("")
- ->RenderString("key", "VALUE")
- ->RenderString("abracadabra", "MAGIC")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("KEY", "VALUE")
- ->RenderString("ABRACADABRA", "MAGIC")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, CamelCase) {
- // Set expectation
- expects_.StartObject("")
- ->RenderString("camelCase", "camelCase")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "theQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("camelCase", "camelCase")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "theQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, FirstCapCamelCase) {
- // Sets expectation
- expects_.StartObject("camel")
- ->RenderString("camelCase", "CamelCase")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "TheQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("Camel")
- ->RenderString("CamelCase", "CamelCase")
- ->RenderString("TheQuickBrownFoxJumpsOverTheLazyDog",
- "TheQuickBrownFoxJumpsOverTheLazyDog")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, LastCapCamelCase) {
- // Sets expectation
- expects_.StartObject("lastCapCamelCasE")->EndObject();
-
- // Actual testing
- testing_.StartObject("lastCapCamelCasE")->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, MixedCapCamelCase) {
- // Sets expectation
- expects_.StartObject("googleIsTheBest")
- ->RenderFloat("iLoveGOOGLE", 1.61803f)
- ->RenderFloat("goGoogleGO", 2.71828f)
- ->RenderFloat("gBikeISCool", 3.14159f)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("GOOGLEIsTheBest")
- ->RenderFloat("ILoveGOOGLE", 1.61803f)
- ->RenderFloat("GOGoogleGO", 2.71828f)
- ->RenderFloat("GBikeISCool", 3.14159f)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, MixedCase) {
- // Sets expectation
- expects_.StartObject("snakeCaseCamelCase")
- ->RenderBool("camelCaseSnakeCase", false)
- ->RenderBool("mixedCamelAndUnderScores", false)
- ->RenderBool("goGOOGLEGo", true)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("snake_case_camelCase")
- ->RenderBool("camelCase_snake_case", false)
- ->RenderBool("MixedCamel_And_UnderScores", false)
- ->RenderBool("Go_GOOGLEGo", true)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, SnakeCase) {
- // Sets expectation
- expects_.StartObject("")
- ->RenderString("snakeCase", "snake_case")
- ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog",
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("snake_case", "snake_case")
- ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog",
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, FirstCapSnakeCase) {
- // Sets expectation
- expects_.StartObject("firstCapSnakeCase")
- ->RenderBool("helloWorld", true)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("First_Cap_Snake_Case")
- ->RenderBool("Hello_World", true)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, AllCapSnakeCase) {
- // Sets expectation
- expects_.StartObject("allCAPSNAKECASE")
- ->RenderDouble("nyseGOOGL", 600.0L)
- ->RenderDouble("aBCDE", 1.0L)
- ->RenderDouble("klMNOP", 2.0L)
- ->RenderDouble("abcIJKPQRXYZ", 3.0L)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("ALL_CAP_SNAKE_CASE")
- ->RenderDouble("NYSE_GOOGL", 600.0L)
- ->RenderDouble("A_B_C_D_E", 1.0L)
- ->RenderDouble("KL_MN_OP", 2.0L)
- ->RenderDouble("ABC_IJK_PQR_XYZ", 3.0L)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, RepeatedUnderScoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("")
- ->RenderInt32("doubleUnderscoreSnakeCase", 2)
- ->RenderInt32("tripleUnderscoreFirstCap", 3)
- ->RenderInt32("quadrupleUNDERSCOREALLCAP", 4)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderInt32("double__underscore__snake__case", 2)
- ->RenderInt32("Triple___Underscore___First___Cap", 3)
- ->RenderInt32("QUADRUPLE____UNDERSCORE____ALL____CAP", 4)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, LeadingUnderscoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("leadingUnderscoreSnakeCase")
- ->RenderUint32("leadingDoubleUnderscore", 2)
- ->RenderUint32("leadingTripleUnderscoreFirstCap", 3)
- ->RenderUint32("leadingQUADRUPLEUNDERSCOREALLCAP", 4)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("_leading_underscore_snake_case")
- ->RenderUint32("__leading_double_underscore", 2)
- ->RenderUint32("___Leading_Triple_Underscore_First_Cap", 3)
- ->RenderUint32("____LEADING_QUADRUPLE_UNDERSCORE_ALL_CAP", 4)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, TrailingUnderscoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("trailingUnderscoreSnakeCase")
- ->RenderInt64("trailingDoubleUnderscore", 2L)
- ->RenderInt64("trailingTripleUnderscoreFirstCap", 3L)
- ->RenderInt64("trailingQUADRUPLEUNDERSCOREALLCAP", 4L)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("trailing_underscore_snake_case")
- ->RenderInt64("trailing_double_underscore__", 2L)
- ->RenderInt64("Trailing_Triple_Underscore_First_Cap___", 3L)
- ->RenderInt64("TRAILING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, EnclosingUnderscoreSnakeCase) {
- // Sets expectation
- expects_.StartObject("enclosingUnderscoreSnakeCase")
- ->RenderUint64("enclosingDoubleUnderscore", 2L)
- ->RenderUint64("enclosingTripleUnderscoreFirstCap", 3L)
- ->RenderUint64("enclosingQUADRUPLEUNDERSCOREALLCAP", 4L)
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("_enclosing_underscore_snake_case_")
- ->RenderUint64("__enclosing_double_underscore__", 2L)
- ->RenderUint64("___Enclosing_Triple_Underscore_First_Cap___", 3L)
- ->RenderUint64("____ENCLOSING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L)
- ->EndObject();
-}
-
-TEST_F(Snake2CamelObjectWriterTest, DisableCaseNormalizationOnlyDisablesFirst) {
- // Sets expectation
- expects_.StartObject("")
- ->RenderString("snakeCase", "snake_case")
- ->RenderString(
- "the_quick_brown_fox_jumps_over_the_lazy_dog", // case retained
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->RenderBool("theSlowFox", true) // disable case not in effect
- ->EndObject();
-
- // Actual testing
- testing_.StartObject("")
- ->RenderString("snake_case", "snake_case")
- ->DisableCaseNormalizationForNextKey()
- ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog",
- "the_quick_brown_fox_jumps_over_the_lazy_dog")
- ->RenderBool("the_slow_fox", true)
- ->EndObject();
-}
+// All tests are deleted as they are no longer needed. This file will be removed
+// after the component dependecies are cleaned up.
+// TODO(skarvaje): Remove this file.
} // namespace converter
} // namespace util
diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto
index ecfc8119..ebbdf6ab 100644
--- a/src/google/protobuf/util/internal/testdata/default_value.proto
+++ b/src/google/protobuf/util/internal/testdata/default_value.proto
@@ -43,6 +43,7 @@ message DefaultValueTestCases {
DoubleMessage repeated_double = 4;
DoubleMessage nested_message = 5;
DoubleMessage repeated_nested_message = 6;
+ DoubleMessage double_message_with_oneof = 7;
StructMessage empty_struct = 201;
StructMessage empty_struct2 = 202;
StructMessage struct_with_null_value = 203;
@@ -75,6 +76,8 @@ message DefaultValueTestCases {
MixedMap mixed1 = 404;
MixedMap2 mixed2 = 405;
MessageMap map_of_objects = 406;
+ MixedMap mixed_empty = 407;
+ MessageMap message_map_empty = 408;
DoubleValueMessage double_value = 501;
DoubleValueMessage double_value_default = 502;
}
@@ -85,6 +88,10 @@ message DoubleMessage {
DoubleMessage nested_message = 3;
repeated DoubleMessage repeated_nested_message = 4;
google.protobuf.DoubleValue double_wrapper = 100;
+ oneof value {
+ string str_value = 112;
+ int64 num_value = 113;
+ }
}
message StructMessage {
diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
index 6392e18c..a45a76e3 100644
--- a/src/google/protobuf/util/internal/type_info.cc
+++ b/src/google/protobuf/util/internal/type_info.cc
@@ -35,11 +35,11 @@
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/type.pb.h>
+#include <google/protobuf/util/internal/utility.h>
#include <google/protobuf/stubs/stringpiece.h>
#include <google/protobuf/stubs/map_util.h>
#include <google/protobuf/stubs/status.h>
#include <google/protobuf/stubs/statusor.h>
-#include <google/protobuf/util/internal/utility.h>
namespace google {
namespace protobuf {
@@ -47,7 +47,6 @@ namespace util {
namespace converter {
namespace {
-
// A TypeInfo that looks up information provided by a TypeResolver.
class TypeInfoForTypeResolver : public TypeInfo {
public:
@@ -60,7 +59,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
}
virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
- StringPiece type_url) {
+ StringPiece type_url) const {
map<StringPiece, StatusOrType>::iterator it = cached_types_.find(type_url);
if (it != cached_types_.end()) {
return it->second;
@@ -78,12 +77,14 @@ class TypeInfoForTypeResolver : public TypeInfo {
return result;
}
- virtual const google::protobuf::Type* GetType(StringPiece type_url) {
+ virtual const google::protobuf::Type* GetTypeByTypeUrl(
+ StringPiece type_url) const {
StatusOrType result = ResolveTypeUrl(type_url);
return result.ok() ? result.ValueOrDie() : NULL;
}
- virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) {
+ virtual const google::protobuf::Enum* GetEnumByTypeUrl(
+ StringPiece type_url) const {
map<StringPiece, StatusOrEnum>::iterator it = cached_enums_.find(type_url);
if (it != cached_enums_.end()) {
return it->second.ok() ? it->second.ValueOrDie() : NULL;
@@ -103,7 +104,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
}
virtual const google::protobuf::Field* FindField(
- const google::protobuf::Type* type, StringPiece camel_case_name) {
+ const google::protobuf::Type* type, StringPiece camel_case_name) const {
if (indexed_types_.find(type) == indexed_types_.end()) {
PopulateNameLookupTable(type);
indexed_types_.insert(type);
@@ -131,7 +132,7 @@ class TypeInfoForTypeResolver : public TypeInfo {
}
}
- void PopulateNameLookupTable(const google::protobuf::Type* type) {
+ void PopulateNameLookupTable(const google::protobuf::Type* type) const {
for (int i = 0; i < type->fields_size(); ++i) {
const google::protobuf::Field& field = type->fields(i);
StringPiece name = field.name();
@@ -151,13 +152,13 @@ class TypeInfoForTypeResolver : public TypeInfo {
// Stores string values that will be referenced by StringPieces in
// cached_types_, cached_enums_ and camel_case_name_table_.
- set<string> string_storage_;
+ mutable set<string> string_storage_;
- map<StringPiece, StatusOrType> cached_types_;
- map<StringPiece, StatusOrEnum> cached_enums_;
+ mutable map<StringPiece, StatusOrType> cached_types_;
+ mutable map<StringPiece, StatusOrEnum> cached_enums_;
- set<const google::protobuf::Type*> indexed_types_;
- map<StringPiece, StringPiece> camel_case_name_table_;
+ mutable set<const google::protobuf::Type*> indexed_types_;
+ mutable map<StringPiece, StringPiece> camel_case_name_table_;
};
} // namespace
diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
index 67403fff..e394e8cf 100644
--- a/src/google/protobuf/util/internal/type_info.h
+++ b/src/google/protobuf/util/internal/type_info.h
@@ -44,7 +44,7 @@ namespace util {
namespace converter {
// Internal helper class for type resolving. Note that this class is not
// thread-safe and should only be accessed in one thread.
-class LIBPROTOBUF_EXPORT TypeInfo {
+class TypeInfo {
public:
TypeInfo() {}
virtual ~TypeInfo() {}
@@ -55,24 +55,29 @@ class LIBPROTOBUF_EXPORT TypeInfo {
//
// This TypeInfo class retains the ownership of the returned pointer.
virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
- StringPiece type_url) = 0;
+ StringPiece type_url) const = 0;
// Resolves a type url into a Type. Like ResolveTypeUrl() but returns
// NULL if the type url is invalid or the type cannot be found.
//
// This TypeInfo class retains the ownership of the returned pointer.
- virtual const google::protobuf::Type* GetType(StringPiece type_url) = 0;
+ virtual const google::protobuf::Type* GetTypeByTypeUrl(
+ StringPiece type_url) const = 0;
// Resolves a type url for an enum. Returns NULL if the type url is
// invalid or the type cannot be found.
//
// This TypeInfo class retains the ownership of the returned pointer.
- virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) = 0;
+ virtual const google::protobuf::Enum* GetEnumByTypeUrl(
+ StringPiece type_url) const = 0;
// Looks up a field in the specified type given a CamelCase name.
virtual const google::protobuf::Field* FindField(
- const google::protobuf::Type* type, StringPiece camel_case_name) = 0;
+ const google::protobuf::Type* type,
+ StringPiece camel_case_name) const = 0;
+ // Creates a TypeInfo object that looks up type information from a
+ // TypeResolver. Caller takes ownership of the returned pointer.
static TypeInfo* NewTypeInfo(TypeResolver* type_resolver);
private:
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
index 177b96e2..1b9c5154 100644
--- a/src/google/protobuf/util/internal/type_info_test_helper.cc
+++ b/src/google/protobuf/util/internal/type_info_test_helper.cc
@@ -36,6 +36,7 @@
#endif
#include <vector>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/internal/default_value_objectwriter.h>
@@ -89,7 +90,7 @@ TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); }
ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
io::CodedInputStream* coded_input, const string& type_url) {
- const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) {
case USE_TYPE_RESOLVER: {
return new ProtoStreamObjectSource(coded_input, type_resolver_.get(),
@@ -103,7 +104,7 @@ ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
const string& type_url, strings::ByteSink* output,
ErrorListener* listener) {
- const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) {
case USE_TYPE_RESOLVER: {
return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
@@ -116,7 +117,7 @@ ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter(
const string& type_url, ObjectWriter* writer) {
- const google::protobuf::Type* type = typeinfo_->GetType(type_url);
+ const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
switch (type_) {
case USE_TYPE_RESOLVER: {
return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer);
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 794777d4..2d63de00 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -34,7 +34,9 @@
#include <algorithm>
#include <utility>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/wrappers.pb.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
@@ -303,7 +305,7 @@ bool IsMap(const google::protobuf::Field& field,
string DoubleAsString(double value) {
if (value == std::numeric_limits<double>::infinity()) return "Infinity";
if (value == -std::numeric_limits<double>::infinity()) return "-Infinity";
- if (google::protobuf::MathLimits<double>::IsNaN(value)) return "NaN";
+ if (MathLimits<double>::IsNaN(value)) return "NaN";
return SimpleDtoa(value);
}
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
index d0d88c19..87f7602a 100644
--- a/src/google/protobuf/util/internal/utility.h
+++ b/src/google/protobuf/util/internal/utility.h
@@ -39,6 +39,7 @@
#include <utility>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/type.pb.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/stubs/stringpiece.h>
@@ -117,23 +118,23 @@ LIBPROTOBUF_EXPORT const string GetFullTypeWithUrl(StringPiece simple_type);
// Finds and returns option identified by name and option_name within the
// provided map. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::Option* FindOptionOrNull(
+const google::protobuf::Option* FindOptionOrNull(
const google::protobuf::RepeatedPtrField<google::protobuf::Option>& options,
const string& option_name);
// Finds and returns the field identified by field_name in the passed tech Type
// object. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::Field* FindFieldInTypeOrNull(
+const google::protobuf::Field* FindFieldInTypeOrNull(
const google::protobuf::Type* type, StringPiece field_name);
// Finds and returns the EnumValue identified by enum_name in the passed tech
// Enum object. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
+const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
const google::protobuf::Enum* enum_type, StringPiece enum_name);
// Finds and returns the EnumValue identified by value in the passed tech
// Enum object. Returns NULL if none found.
-LIBPROTOBUF_EXPORT const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
+const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
const google::protobuf::Enum* enum_type, int32 value);
// Converts input to camel-case and returns it.
@@ -153,7 +154,7 @@ LIBPROTOBUF_EXPORT bool IsWellKnownType(const string& type_name);
LIBPROTOBUF_EXPORT bool IsValidBoolString(const string& bool_string);
// Returns true if "field" is a protobuf map field based on its type.
-bool IsMap(const google::protobuf::Field& field,
+LIBPROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field,
const google::protobuf::Type& type);
// Infinity/NaN-aware conversion to string.
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
index 6796ea08..614564cc 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -44,7 +44,7 @@ class ZeroCopyOutputStream;
} // namespace io
namespace util {
-struct LIBPROTOBUF_EXPORT JsonOptions {
+struct JsonOptions {
// Whether to add spaces, line breaks and indentation to make the JSON output
// easy to read.
bool add_whitespace;
@@ -65,7 +65,7 @@ struct LIBPROTOBUF_EXPORT JsonOptions {
// 2. input is not valid protobuf wire format, or conflicts with the type
// information returned by TypeResolver.
// Note that unknown fields will be discarded silently.
-LIBPROTOBUF_EXPORT util::Status BinaryToJsonStream(
+util::Status BinaryToJsonStream(
TypeResolver* resolver,
const string& type_url,
io::ZeroCopyInputStream* binary_input,
@@ -80,7 +80,7 @@ inline util::Status BinaryToJsonStream(
JsonOptions());
}
-LIBPROTOBUF_EXPORT util::Status BinaryToJsonString(
+util::Status BinaryToJsonString(
TypeResolver* resolver,
const string& type_url,
const string& binary_input,
@@ -101,13 +101,13 @@ inline util::Status BinaryToJsonString(TypeResolver* resolver,
// 2. input is not valid JSON format, or conflicts with the type
// information returned by TypeResolver.
// 3. input has unknown fields.
-LIBPROTOBUF_EXPORT util::Status JsonToBinaryStream(
+util::Status JsonToBinaryStream(
TypeResolver* resolver,
const string& type_url,
io::ZeroCopyInputStream* json_input,
io::ZeroCopyOutputStream* binary_output);
-LIBPROTOBUF_EXPORT util::Status JsonToBinaryString(
+util::Status JsonToBinaryString(
TypeResolver* resolver,
const string& type_url,
const string& json_input,
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index 8399b408..7f88e672 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -98,27 +98,28 @@ TEST_F(JsonUtilTest, TestWhitespaces) {
ToJson(m, options));
}
-TEST_F(JsonUtilTest, TestDefaultValues) {
- TestMessage m;
- JsonOptions options;
- EXPECT_EQ("{}", ToJson(m, options));
- options.always_print_primitive_fields = true;
- EXPECT_EQ(
- "{\"boolValue\":false,"
- "\"int32Value\":0,"
- "\"int64Value\":\"0\","
- "\"uint32Value\":0,"
- "\"uint64Value\":\"0\","
- "\"floatValue\":0,"
- "\"doubleValue\":0,"
- "\"stringValue\":\"\","
- "\"bytesValue\":\"\","
- // TODO(xiaofeng): The default enum value should be FOO. I believe
- // this is a bug in DefaultValueObjectWriter.
- "\"enumValue\":null"
- "}",
- ToJson(m, options));
-}
+// TODO(skarvaje): Uncomment after cl/96232915 is submitted.
+// TEST_F(JsonUtilTest, TestDefaultValues) {
+ // TestMessage m;
+ // JsonOptions options;
+ // EXPECT_EQ("{}", ToJson(m, options));
+ // options.always_print_primitive_fields = true;
+ // EXPECT_EQ(
+ // "{\"boolValue\":false,"
+ // "\"int32Value\":0,"
+ // "\"int64Value\":\"0\","
+ // "\"uint32Value\":0,"
+ // "\"uint64Value\":\"0\","
+ // "\"floatValue\":0,"
+ // "\"doubleValue\":0,"
+ // "\"stringValue\":\"\","
+ // "\"bytesValue\":\"\","
+ // // TODO(xiaofeng): The default enum value should be FOO. I believe
+ // // this is a bug in DefaultValueObjectWriter.
+ // "\"enumValue\":null"
+ // "}",
+ // ToJson(m, options));
+// }
TEST_F(JsonUtilTest, ParseMessage) {
// Some random message but good enough to verify that the parsing warpper
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 057b414a..d709da57 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -45,6 +45,7 @@
#endif
#include <utility>
+#include <google/protobuf/stubs/callback.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/any.h>
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index bd19f695..701b94ae 100755
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -52,6 +52,7 @@
#include <google/protobuf/map_test_util.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/testing/googletest.h>
@@ -131,7 +132,7 @@ TEST(MessageDifferencerTest, MapFieldEqualityTest) {
unittest::TestMap msg1;
unittest::TestMap msg2;
- MapTestUtil::MapReflectionTester tester(unittest::TestMap::descriptor());
+ MapReflectionTester tester(unittest::TestMap::descriptor());
tester.SetMapFieldsViaReflection(&msg1);
tester.SetMapFieldsViaReflection(&msg2);
tester.SwapMapsViaReflection(&msg1);
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index 053a4ed7..908634eb 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/util/type_resolver.h>
+#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/status.h>
namespace google {
@@ -64,6 +65,47 @@ bool SplitTypeUrl(const string& type_url,
return true;
}
+// This code is originally defined in
+// //google/protobuf/util/converter/utility.h. Copied here due to component
+// dependency.
+// TODO(xiaofeng): Remove this when converter code is in components.
+string ToCamelCase(const StringPiece input) {
+ bool capitalize_next = false;
+ bool was_cap = true;
+ bool is_cap = false;
+ bool first_word = true;
+ string result;
+ result.reserve(input.size());
+
+ for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) {
+ is_cap = ascii_isupper(input[i]);
+ if (input[i] == '_') {
+ capitalize_next = true;
+ if (!result.empty()) first_word = false;
+ continue;
+ } else if (first_word) {
+ // Consider when the current character B is capitalized,
+ // first word ends when:
+ // 1) following a lowercase: "...aB..."
+ // 2) followed by a lowercase: "...ABc..."
+ if (!result.empty() && is_cap &&
+ (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) {
+ first_word = false;
+ } else {
+ result.push_back(ascii_tolower(input[i]));
+ continue;
+ }
+ } else if (capitalize_next) {
+ capitalize_next = false;
+ if (ascii_islower(input[i])) {
+ result.push_back(ascii_toupper(input[i]));
+ continue;
+ }
+ }
+ result.push_back(input[i]);
+ }
+ return result;
+}
class DescriptorPoolTypeResolver : public TypeResolver {
public:
@@ -155,6 +197,7 @@ class DescriptorPoolTypeResolver : public TypeResolver {
}
field->set_number(descriptor->number());
field->set_name(descriptor->name());
+ field->set_json_name(ToCamelCase(descriptor->name()));
if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
field->set_type_url(GetTypeUrl(descriptor->message_type()));
} else if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
diff --git a/src/google/protobuf/util/type_resolver_util.h b/src/google/protobuf/util/type_resolver_util.h
index c0ef3c1a..00cf9c13 100644
--- a/src/google/protobuf/util/type_resolver_util.h
+++ b/src/google/protobuf/util/type_resolver_util.h
@@ -42,7 +42,7 @@ class TypeResolver;
// Creates a TypeResolver that serves type information in the given descriptor
// pool. Caller takes ownership of the returned TypeResolver.
-LIBPROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool(
+TypeResolver* NewTypeResolverForDescriptorPool(
const string& url_prefix, const DescriptorPool* pool);
} // namespace util
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index c5db963b..8fbd116b 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -38,6 +38,7 @@
#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
#include <google/protobuf/descriptor.h>
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 2ce4920c..dade41af 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -37,6 +37,7 @@
#include <stack>
#include <string>
#include <vector>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream_inl.h>
#include <google/protobuf/io/zero_copy_stream.h>
@@ -484,9 +485,9 @@ void WireFormatLite::WriteMessageMaybeToArray(int field_number,
}
}
-static inline bool ReadBytesToString(io::CodedInputStream* input,
- string* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
-static inline bool ReadBytesToString(io::CodedInputStream* input,
+GOOGLE_ATTRIBUTE_ALWAYS_INLINE static bool ReadBytesToString(
+ io::CodedInputStream* input, string* value);
+inline static bool ReadBytesToString(io::CodedInputStream* input,
string* value) {
uint32 length;
return input->ReadVarint32(&length) &&
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index ac83abdc..19fbc2c5 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -250,17 +250,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// For primitive fields, we just use a templatized routine parameterized by
// the represented type and the FieldType. These are specialized with the
// appropriate definition for each declared type.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadPrimitive(input, CType* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static bool ReadPrimitive(input, CType* value);
// Reads repeated primitive values, with optimizations for repeats.
// tag_size and tag should both be compile-time constants provided by the
// protocol compiler.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadRepeatedPrimitive(int tag_size,
- uint32 tag,
- input,
- RepeatedField<CType>* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static bool ReadRepeatedPrimitive(int tag_size,
+ uint32 tag,
+ input,
+ RepeatedField<CType>* value);
// Identical to ReadRepeatedPrimitive, except will not inline the
// implementation.
@@ -275,16 +275,14 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
//
// This is only implemented for the types with fixed wire size, e.g.
// float, double, and the (s)fixed* types.
- template <typename CType, enum FieldType DeclaredType>
- static inline const uint8* ReadPrimitiveFromArray(const uint8* buffer,
- CType* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static const uint8* ReadPrimitiveFromArray(const uint8* buffer, CType* value);
// Reads a primitive packed field.
//
// This is only implemented for packable types.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadPackedPrimitive(input,
- RepeatedField<CType>* value) INL;
+ template <typename CType, enum FieldType DeclaredType> INL
+ static bool ReadPackedPrimitive(input, RepeatedField<CType>* value);
// Identical to ReadPackedPrimitive, except will not inline the
// implementation.
@@ -344,23 +342,23 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// Write a tag. The Write*() functions typically include the tag, so
// normally there's no need to call this unless using the Write*NoTag()
// variants.
- static inline void WriteTag(field_number, WireType type, output) INL;
+ INL static void WriteTag(field_number, WireType type, output);
// Write fields, without tags.
- static inline void WriteInt32NoTag (int32 value, output) INL;
- static inline void WriteInt64NoTag (int64 value, output) INL;
- static inline void WriteUInt32NoTag (uint32 value, output) INL;
- static inline void WriteUInt64NoTag (uint64 value, output) INL;
- static inline void WriteSInt32NoTag (int32 value, output) INL;
- static inline void WriteSInt64NoTag (int64 value, output) INL;
- static inline void WriteFixed32NoTag (uint32 value, output) INL;
- static inline void WriteFixed64NoTag (uint64 value, output) INL;
- static inline void WriteSFixed32NoTag(int32 value, output) INL;
- static inline void WriteSFixed64NoTag(int64 value, output) INL;
- static inline void WriteFloatNoTag (float value, output) INL;
- static inline void WriteDoubleNoTag (double value, output) INL;
- static inline void WriteBoolNoTag (bool value, output) INL;
- static inline void WriteEnumNoTag (int value, output) INL;
+ INL static void WriteInt32NoTag (int32 value, output);
+ INL static void WriteInt64NoTag (int64 value, output);
+ INL static void WriteUInt32NoTag (uint32 value, output);
+ INL static void WriteUInt64NoTag (uint64 value, output);
+ INL static void WriteSInt32NoTag (int32 value, output);
+ INL static void WriteSInt64NoTag (int64 value, output);
+ INL static void WriteFixed32NoTag (uint32 value, output);
+ INL static void WriteFixed64NoTag (uint64 value, output);
+ INL static void WriteSFixed32NoTag(int32 value, output);
+ INL static void WriteSFixed64NoTag(int64 value, output);
+ INL static void WriteFloatNoTag (float value, output);
+ INL static void WriteDoubleNoTag (double value, output);
+ INL static void WriteBoolNoTag (bool value, output);
+ INL static void WriteEnumNoTag (int value, output);
// Write fields, including tags.
static void WriteInt32 (field_number, int32 value, output);
@@ -410,73 +408,59 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
#define output uint8* target
// Like above, but use only *ToArray methods of CodedOutputStream.
- static inline uint8* WriteTagToArray(field_number, WireType type, output) INL;
+ INL static uint8* WriteTagToArray(field_number, WireType type, output);
// Write fields, without tags.
- static inline uint8* WriteInt32NoTagToArray (int32 value, output) INL;
- static inline uint8* WriteInt64NoTagToArray (int64 value, output) INL;
- static inline uint8* WriteUInt32NoTagToArray (uint32 value, output) INL;
- static inline uint8* WriteUInt64NoTagToArray (uint64 value, output) INL;
- static inline uint8* WriteSInt32NoTagToArray (int32 value, output) INL;
- static inline uint8* WriteSInt64NoTagToArray (int64 value, output) INL;
- static inline uint8* WriteFixed32NoTagToArray (uint32 value, output) INL;
- static inline uint8* WriteFixed64NoTagToArray (uint64 value, output) INL;
- static inline uint8* WriteSFixed32NoTagToArray(int32 value, output) INL;
- static inline uint8* WriteSFixed64NoTagToArray(int64 value, output) INL;
- static inline uint8* WriteFloatNoTagToArray (float value, output) INL;
- static inline uint8* WriteDoubleNoTagToArray (double value, output) INL;
- static inline uint8* WriteBoolNoTagToArray (bool value, output) INL;
- static inline uint8* WriteEnumNoTagToArray (int value, output) INL;
+ INL static uint8* WriteInt32NoTagToArray (int32 value, output);
+ INL static uint8* WriteInt64NoTagToArray (int64 value, output);
+ INL static uint8* WriteUInt32NoTagToArray (uint32 value, output);
+ INL static uint8* WriteUInt64NoTagToArray (uint64 value, output);
+ INL static uint8* WriteSInt32NoTagToArray (int32 value, output);
+ INL static uint8* WriteSInt64NoTagToArray (int64 value, output);
+ INL static uint8* WriteFixed32NoTagToArray (uint32 value, output);
+ INL static uint8* WriteFixed64NoTagToArray (uint64 value, output);
+ INL static uint8* WriteSFixed32NoTagToArray(int32 value, output);
+ INL static uint8* WriteSFixed64NoTagToArray(int64 value, output);
+ INL static uint8* WriteFloatNoTagToArray (float value, output);
+ INL static uint8* WriteDoubleNoTagToArray (double value, output);
+ INL static uint8* WriteBoolNoTagToArray (bool value, output);
+ INL static uint8* WriteEnumNoTagToArray (int value, output);
// Write fields, including tags.
- static inline uint8* WriteInt32ToArray(
- field_number, int32 value, output) INL;
- static inline uint8* WriteInt64ToArray(
- field_number, int64 value, output) INL;
- static inline uint8* WriteUInt32ToArray(
- field_number, uint32 value, output) INL;
- static inline uint8* WriteUInt64ToArray(
- field_number, uint64 value, output) INL;
- static inline uint8* WriteSInt32ToArray(
- field_number, int32 value, output) INL;
- static inline uint8* WriteSInt64ToArray(
- field_number, int64 value, output) INL;
- static inline uint8* WriteFixed32ToArray(
- field_number, uint32 value, output) INL;
- static inline uint8* WriteFixed64ToArray(
- field_number, uint64 value, output) INL;
- static inline uint8* WriteSFixed32ToArray(
- field_number, int32 value, output) INL;
- static inline uint8* WriteSFixed64ToArray(
- field_number, int64 value, output) INL;
- static inline uint8* WriteFloatToArray(
- field_number, float value, output) INL;
- static inline uint8* WriteDoubleToArray(
- field_number, double value, output) INL;
- static inline uint8* WriteBoolToArray(
- field_number, bool value, output) INL;
- static inline uint8* WriteEnumToArray(
- field_number, int value, output) INL;
-
- static inline uint8* WriteStringToArray(
- field_number, const string& value, output) INL;
- static inline uint8* WriteBytesToArray(
- field_number, const string& value, output) INL;
-
- static inline uint8* WriteGroupToArray(
- field_number, const MessageLite& value, output) INL;
- static inline uint8* WriteMessageToArray(
- field_number, const MessageLite& value, output) INL;
+ INL static uint8* WriteInt32ToArray(field_number, int32 value, output);
+ INL static uint8* WriteInt64ToArray(field_number, int64 value, output);
+ INL static uint8* WriteUInt32ToArray(field_number, uint32 value, output);
+ INL static uint8* WriteUInt64ToArray(field_number, uint64 value, output);
+ INL static uint8* WriteSInt32ToArray(field_number, int32 value, output);
+ INL static uint8* WriteSInt64ToArray(field_number, int64 value, output);
+ INL static uint8* WriteFixed32ToArray(field_number, uint32 value, output);
+ INL static uint8* WriteFixed64ToArray(field_number, uint64 value, output);
+ INL static uint8* WriteSFixed32ToArray(field_number, int32 value, output);
+ INL static uint8* WriteSFixed64ToArray(field_number, int64 value, output);
+ INL static uint8* WriteFloatToArray(field_number, float value, output);
+ INL static uint8* WriteDoubleToArray(field_number, double value, output);
+ INL static uint8* WriteBoolToArray(field_number, bool value, output);
+ INL static uint8* WriteEnumToArray(field_number, int value, output);
+
+ INL static uint8* WriteStringToArray(
+ field_number, const string& value, output);
+ INL static uint8* WriteBytesToArray(
+ field_number, const string& value, output);
+
+ INL static uint8* WriteGroupToArray(
+ field_number, const MessageLite& value, output);
+ INL static uint8* WriteMessageToArray(
+ field_number, const MessageLite& value, output);
// Like above, but de-virtualize the call to SerializeWithCachedSizes(). The
// pointer must point at an instance of MessageType, *not* a subclass (or
// the subclass must not override SerializeWithCachedSizes()).
template<typename MessageType>
- static inline uint8* WriteGroupNoVirtualToArray(
- field_number, const MessageType& value, output) INL;
+ INL static uint8* WriteGroupNoVirtualToArray(
+ field_number, const MessageType& value, output);
template<typename MessageType>
- static inline uint8* WriteMessageNoVirtualToArray(
- field_number, const MessageType& value, output) INL;
+ INL static uint8* WriteMessageNoVirtualToArray(
+ field_number, const MessageType& value, output);
#undef output
#undef input
@@ -527,18 +511,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite {
// A helper method for the repeated primitive reader. This method has
// optimizations for primitive types that have fixed size on the wire, and
// can be read using potentially faster paths.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadRepeatedFixedSizePrimitive(
+ template <typename CType, enum FieldType DeclaredType> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static bool ReadRepeatedFixedSizePrimitive(
int tag_size,
uint32 tag,
google::protobuf::io::CodedInputStream* input,
- RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ RepeatedField<CType>* value);
// Like ReadRepeatedFixedSizePrimitive but for packed primitive fields.
- template <typename CType, enum FieldType DeclaredType>
- static inline bool ReadPackedFixedSizePrimitive(
- google::protobuf::io::CodedInputStream* input,
- RepeatedField<CType>* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE;
+ template <typename CType, enum FieldType DeclaredType> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+ static bool ReadPackedFixedSizePrimitive(google::protobuf::io::CodedInputStream* input,
+ RepeatedField<CType>* value);
static const CppType kFieldTypeToCppTypeMap[];
static const WireFormatLite::WireType kWireTypeForFieldType[];
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index d073ff92..991c3d04 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -43,6 +43,7 @@
#include <string>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/message_lite.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/wire_format_lite.h>
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index aef22b29..15c37556 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -40,8 +40,10 @@
#include <google/protobuf/unittest.pb.h>
#include <google/protobuf/unittest_proto3_arena.pb.h>
#include <google/protobuf/unittest_mset.pb.h>
+#include <google/protobuf/unittest_mset_wire_format.pb.h>
#include <google/protobuf/test_util.h>
+#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
@@ -419,7 +421,7 @@ const int kUnknownTypeId = 1550055;
TEST(WireFormatTest, SerializeMessageSet) {
// Set up a TestMessageSet with two known messages and an unknown one.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
message_set.MutableExtension(
unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
message_set.MutableExtension(
@@ -462,7 +464,7 @@ TEST(WireFormatTest, SerializeMessageSetVariousWaysAreEqual) {
// Set up a TestMessageSet with two known messages and an unknown one, as
// above.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
message_set.MutableExtension(
unittest::TestMessageSetExtension1::message_set_extension)->set_i(123);
message_set.MutableExtension(
@@ -539,7 +541,7 @@ TEST(WireFormatTest, ParseMessageSet) {
ASSERT_TRUE(raw.SerializeToString(&data));
// Parse as a TestMessageSet and check the contents.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
ASSERT_TRUE(message_set.ParseFromString(data));
EXPECT_EQ(123, message_set.GetExtension(
@@ -553,7 +555,7 @@ TEST(WireFormatTest, ParseMessageSet) {
EXPECT_EQ("bar", message_set.unknown_fields().field(0).length_delimited());
// Also parse using WireFormat.
- unittest::TestMessageSet dynamic_message_set;
+ proto2_wireformat_unittest::TestMessageSet dynamic_message_set;
io::CodedInputStream input(reinterpret_cast<const uint8*>(data.data()),
data.size());
ASSERT_TRUE(WireFormat::ParseAndMergePartial(&input, &dynamic_message_set));
@@ -583,7 +585,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
coded_output.WriteTag(WireFormatLite::kMessageSetItemEndTag);
}
{
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
ASSERT_TRUE(message_set.ParseFromString(data));
EXPECT_EQ(123, message_set.GetExtension(
@@ -591,7 +593,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
}
{
// Test parse the message via Reflection.
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
io::CodedInputStream input(
reinterpret_cast<const uint8*>(data.data()), data.size());
EXPECT_TRUE(WireFormat::ParseAndMergePartial(&input, &message_set));
@@ -603,7 +605,7 @@ TEST(WireFormatTest, ParseMessageSetWithReverseTagOrder) {
}
TEST(WireFormatTest, ParseBrokenMessageSet) {
- unittest::TestMessageSet message_set;
+ proto2_wireformat_unittest::TestMessageSet message_set;
string input("goodbye"); // Invalid wire format data.
EXPECT_FALSE(message_set.ParseFromString(input));
}