diff --git a/BUILD b/BUILD index 92e4091db3..1124321602 100644 --- a/BUILD +++ b/BUILD @@ -164,6 +164,7 @@ cc_library( # AUTOGEN(protobuf_lite_srcs) "src/google/protobuf/any_lite.cc", "src/google/protobuf/arena.cc", + "src/google/protobuf/arenastring.cc", "src/google/protobuf/extension_set.cc", "src/google/protobuf/generated_enum_util.cc", "src/google/protobuf/generated_message_table_driven_lite.cc", diff --git a/CHANGES.txt b/CHANGES.txt index 511d84e882..3fa4e07aa6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,10 +3,13 @@ Unreleased Changes Protocol Compiler * The proto compiler no longer requires a .proto filename when it is not generating code. + * Added flag `--deterministic_output` to `protoc --encode=...`. + * Fixed deadlock when using google.protobuf.Any embedded in aggregate options. C++ * Arenas are now unconditionally enabled. cc_enable_arenas no longer has any effect. + * Removed inlined string support, which is incompatible with arenas. * Fix a memory corruption bug in reflection when mixing optional and non-optional fields. * Make SpaceUsed() calculation more thorough for map fields. @@ -20,9 +23,23 @@ Unreleased Changes * When running under ASAN, skip a test that makes huge allocations. * Fixed a crash that could happen when creating more than 256 extensions in a single message. + * Fix a crash in BuildFile when passing in invalid descriptor proto. + * Parser security fix when operating with CodedInputStream. + * Warn against the use of AllowUnknownExtension. + * Migrated to C++11 for-range loops instead of index-based loops where + possible. This fixes a lot of warnings when compiling with -Wsign-compare. Java * Bugfix in mergeFrom() when a oneof has multiple message fields. + * Fix RopeByteString.RopeInputStream.read() returning -1 when told to read + 0 bytes when not at EOF. + * Redefine remove(Object) on primitive repeated field Lists to avoid + autoboxing. + * Support "\u" escapes in textformat string literals. + * Trailing empty spaces are no longer ignored for FieldMask. + * Fix FieldMaskUtil.subtract to recursively remove mask. + * Mark enums with `@java.lang.Deprecated` if the proto enum has option + `deprecated = true;`. Python * Print google.protobuf.NullValue as null instead of "NULL_VALUE" when it is diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in index 007cc80669..5c5799efa1 100644 --- a/cmake/extract_includes.bat.in +++ b/cmake/extract_includes.bat.in @@ -53,7 +53,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tab copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\implicit_weak_message.h" include\google\protobuf\implicit_weak_message.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\inlined_string_field.h" include\google\protobuf\inlined_string_field.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h" include\google\protobuf\io\gzip_stream.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\io_win32.h" include\google\protobuf\io\io_win32.h @@ -88,7 +87,6 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" i copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" include\google\protobuf\stubs\casts.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h" include\google\protobuf\stubs\common.h -copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h" include\google\protobuf\stubs\fastmem.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h" include\google\protobuf\stubs\hash.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h" include\google\protobuf\stubs\logging.h copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h" include\google\protobuf\stubs\macros.h diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake index ea85333cef..6d325d5dca 100644 --- a/cmake/libprotobuf-lite.cmake +++ b/cmake/libprotobuf-lite.cmake @@ -1,6 +1,7 @@ set(libprotobuf_lite_files ${protobuf_source_dir}/src/google/protobuf/any_lite.cc ${protobuf_source_dir}/src/google/protobuf/arena.cc + ${protobuf_source_dir}/src/google/protobuf/arenastring.cc ${protobuf_source_dir}/src/google/protobuf/extension_set.cc ${protobuf_source_dir}/src/google/protobuf/generated_enum_util.cc ${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven_lite.cc diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in index 74c5488729..810256e54c 100644 --- a/cmake/protobuf-module.cmake.in +++ b/cmake/protobuf-module.cmake.in @@ -97,6 +97,10 @@ function(_protobuf_find_libraries name filename) else() get_target_property(${name}_LIBRARY_RELEASE protobuf::lib${filename} LOCATION_RELEASE) + get_target_property(${name}_LIBRARY_RELWITHDEBINFO protobuf::lib${filename} + LOCATION_RELWITHDEBINFO) + get_target_property(${name}_LIBRARY_MINSIZEREL protobuf::lib${filename} + LOCATION_MINSIZEREL) get_target_property(${name}_LIBRARY_DEBUG protobuf::lib${filename} LOCATION_DEBUG) @@ -146,6 +150,14 @@ get_target_property(Protobuf_INCLUDE_DIRS protobuf::libprotobuf # Set the protoc Executable get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc IMPORTED_LOCATION_RELEASE) +if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") + get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc + IMPORTED_LOCATION_RELWITHDEBINFO) +endif() +if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") + get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc + IMPORTED_LOCATION_MINSIZEREL) +endif() if(NOT EXISTS "${Protobuf_PROTOC_EXECUTABLE}") get_target_property(Protobuf_PROTOC_EXECUTABLE protobuf::protoc IMPORTED_LOCATION_DEBUG) diff --git a/conformance/Makefile.am b/conformance/Makefile.am index 6815c733a5..5b82a4241e 100644 --- a/conformance/Makefile.am +++ b/conformance/Makefile.am @@ -333,7 +333,7 @@ conformance-php-c: # Targets for actually running tests. test_cpp: protoc_middleman conformance-test-runner conformance-cpp - ./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt ./conformance-cpp + ./conformance-test-runner --enforce_recommended --failure_list failure_list_cpp.txt --text_format_failure_list text_format_failure_list_cpp.txt ./conformance-cpp test_java: protoc_middleman conformance-test-runner conformance-java ./conformance-test-runner --enforce_recommended --failure_list failure_list_java.txt --text_format_failure_list text_format_failure_list_java.txt ./conformance-java @@ -359,10 +359,24 @@ test_php_c_32: protoc_middleman conformance-test-runner conformance-php-c $(othe # These depend on library paths being properly set up. The easiest way to # run them is to just use "tox" from the python dir. test_python: protoc_middleman conformance-test-runner - ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python.txt ./conformance_python.py + VERSION="$(shell python --version 2>&1)"; \ + if [[ "$$VERSION" == "Python 2.7"* ]]; then \ + echo "Using Python 2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python_2.7.txt ./conformance_python.py; \ + else \ + echo "Using Python >2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python.txt --text_format_failure_list text_format_failure_list_python.txt ./conformance_python.py; \ + fi test_python_cpp: protoc_middleman conformance-test-runner - ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt ./conformance_python.py + VERSION="$(shell python --version 2>&1)"; \ + if [[ "$$VERSION" == "Python 2.7"* ]]; then \ + echo "Using Python 2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp_2.7.txt ./conformance_python.py; \ + else \ + echo "Using Python >2.7 failure list."; \ + ./conformance-test-runner --enforce_recommended --failure_list failure_list_python_cpp.txt --text_format_failure_list text_format_failure_list_python_cpp.txt ./conformance_python.py; \ + fi test_nodejs: protoc_middleman conformance-test-runner $(other_language_protoc_outputs) NODE_PATH=../js:. ./conformance-test-runner --enforce_recommended --failure_list failure_list_js.txt ./conformance_nodejs.js diff --git a/conformance/failure_list_js.txt b/conformance/failure_list_js.txt index 8b13789179..e69de29bb2 100644 --- a/conformance/failure_list_js.txt +++ b/conformance/failure_list_js.txt @@ -1 +0,0 @@ - diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc index 6574b10c50..4c9dc7dbe0 100644 --- a/conformance/text_format_conformance_suite.cc +++ b/conformance/text_format_conformance_suite.cc @@ -258,6 +258,84 @@ void TextFormatConformanceTestSuite::RunSuiteImpl() { RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED, "optional_float: 18446744073709551616"); + // String literals x {Strings, Bytes} + for (const auto& field_type : std::vector{"String", "Bytes"}) { + const std::string field_name = + field_type == "String" ? "optional_string" : "optional_bytes"; + RunValidTextFormatTest( + StrCat("StringLiteralConcat", field_type), REQUIRED, + StrCat(field_name, ": 'first' \"second\"\n'third'")); + RunValidTextFormatTest( + StrCat("StringLiteralBasicEscapes", field_type), REQUIRED, + StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'")); + RunValidTextFormatTest( + StrCat("StringLiteralOctalEscapes", field_type), REQUIRED, + StrCat(field_name, ": '\\341\\210\\264'")); + RunValidTextFormatTest(StrCat("StringLiteralHexEscapes", field_type), + REQUIRED, + StrCat(field_name, ": '\\xe1\\x88\\xb4'")); + RunValidTextFormatTest( + StrCat("StringLiteralShortUnicodeEscape", field_type), + RECOMMENDED, StrCat(field_name, ": '\\u1234'")); + RunValidTextFormatTest( + StrCat("StringLiteralLongUnicodeEscapes", field_type), + RECOMMENDED, StrCat(field_name, ": '\\U00001234\\U00010437'")); + // String literals don't include line feeds. + ExpectParseFailure(StrCat("StringLiteralIncludesLF", field_type), + REQUIRED, + StrCat(field_name, ": 'first line\nsecond line'")); + // Unicode escapes don't include code points that lie beyond the planes + // (> 0x10ffff). + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type), + REQUIRED, StrCat(field_name, ": '\\U00110000'")); + // Unicode escapes don't include surrogates. + ExpectParseFailure( + StrCat("StringLiteralShortUnicodeEscapeSurrogatePair", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\ud801\\udc37'")); + ExpectParseFailure( + StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\ud800'")); + ExpectParseFailure( + StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\udc00'")); + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000d800'")); + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000dc00'")); + ExpectParseFailure( + StrCat("StringLiteralLongUnicodeEscapeSurrogatePair", field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\U00000dc37'")); + ExpectParseFailure( + StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\U0000d801\\udc37'")); + ExpectParseFailure( + StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong", + field_type), + RECOMMENDED, StrCat(field_name, ": '\\ud801\\U0000dc37'")); + + // The following method depend on the type of field, as strings have extra + // validation. + const auto test_method = + field_type == "String" + ? &TextFormatConformanceTestSuite::ExpectParseFailure + : &TextFormatConformanceTestSuite::RunValidTextFormatTest; + + // String fields reject invalid UTF-8 byte sequences; bytes fields don't. + (this->*test_method)(StrCat(field_type, "FieldBadUTF8Octal"), + REQUIRED, StrCat(field_name, ": '\\300'")); + (this->*test_method)(StrCat(field_type, "FieldBadUTF8Hex"), REQUIRED, + StrCat(field_name, ": '\\xc0'")); + } + // Group fields RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED, "Data { group_int32: 1 }"); diff --git a/conformance/text_format_failure_list_cpp.txt b/conformance/text_format_failure_list_cpp.txt new file mode 100644 index 0000000000..a25f04faf2 --- /dev/null +++ b/conformance/text_format_failure_list_cpp.txt @@ -0,0 +1,20 @@ +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex +Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString diff --git a/conformance/text_format_failure_list_java.txt b/conformance/text_format_failure_list_java.txt index 81433b441a..71e32429ec 100644 --- a/conformance/text_format_failure_list_java.txt +++ b/conformance/text_format_failure_list_java.txt @@ -4,3 +4,10 @@ Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput Required.Proto3.TextFormatInput.AnyField.ProtobufOutput Required.Proto3.TextFormatInput.AnyField.TextFormatOutput + +Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex +Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput diff --git a/conformance/text_format_failure_list_python.txt b/conformance/text_format_failure_list_python.txt index b2db95e7de..6bf7c1aa63 100644 --- a/conformance/text_format_failure_list_python.txt +++ b/conformance/text_format_failure_list_python.txt @@ -3,3 +3,32 @@ # TODO: These should be fixed. Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput + +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput diff --git a/conformance/text_format_failure_list_python_2.7.txt b/conformance/text_format_failure_list_python_2.7.txt new file mode 100644 index 0000000000..cada2bc03b --- /dev/null +++ b/conformance/text_format_failure_list_python_2.7.txt @@ -0,0 +1,36 @@ +# This is the list of text format conformance tests that are known to fail right +# now. +# TODO: These should be fixed. +Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput +Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput + +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString diff --git a/conformance/text_format_failure_list_python_cpp.txt b/conformance/text_format_failure_list_python_cpp.txt new file mode 100644 index 0000000000..91fc2ea3cd --- /dev/null +++ b/conformance/text_format_failure_list_python_cpp.txt @@ -0,0 +1,28 @@ +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput diff --git a/conformance/text_format_failure_list_python_cpp_2.7.txt b/conformance/text_format_failure_list_python_cpp_2.7.txt new file mode 100644 index 0000000000..ba2089bcaa --- /dev/null +++ b/conformance/text_format_failure_list_python_cpp_2.7.txt @@ -0,0 +1,30 @@ +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapesString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeBytes.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.ProtobufOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeString.TextFormatOutput +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes +Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes +Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput +Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes +Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString diff --git a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs index 0ef8d8f4e7..adbbc3ef54 100644 --- a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs +++ b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs @@ -110,6 +110,18 @@ namespace Google.Protobuf Assert.AreEqual(10, bs[0]); } + [Test] + public void CopyFromReadOnlySpanCopiesContents() + { + byte[] data = new byte[1]; + data[0] = 10; + ReadOnlySpan byteSpan = data; + var bs = ByteString.CopyFrom(byteSpan); + Assert.AreEqual(10, bs[0]); + data[0] = 5; + Assert.AreEqual(10, bs[0]); + } + [Test] public void ToByteArrayCopiesContents() { diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index 2a52ae58be..d893602095 100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -245,6 +245,7 @@ namespace Google.Protobuf /// are copied, so further modifications to the span will not /// be reflected in the returned . /// + [SecuritySafeCritical] public static ByteString CopyFrom(ReadOnlySpan bytes) { return new ByteString(bytes.ToArray()); diff --git a/editors/proto.vim b/editors/proto.vim index 7f1aeb730a..bdc60ce7f8 100644 --- a/editors/proto.vim +++ b/editors/proto.vim @@ -69,10 +69,10 @@ syn keyword pbBool true false syn match pbInt /-\?\<\d\+\>/ syn match pbInt /\<0[xX]\x+\>/ syn match pbFloat /\<-\?\d*\(\.\d*\)\?/ -syn region pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp -syn region pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp -syn region pbString start=/"/ skip=/\\./ end=/"/ -syn region pbString start=/'/ skip=/\\./ end=/'/ +syn region pbComment start="\/\*" end="\*\/" contains=@pbCommentGrp,@Spell +syn region pbComment start="//" skip="\\$" end="$" keepend contains=@pbCommentGrp,@Spell +syn region pbString start=/"/ skip=/\\./ end=/"/ contains=@Spell +syn region pbString start=/'/ skip=/\\./ end=/'/ contains=@Spell if version >= 508 || !exists("did_proto_syn_inits") if version < 508 diff --git a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java index 3220f64072..e792d7d981 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java +++ b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java @@ -142,7 +142,12 @@ abstract class AbstractProtobufList extends AbstractList implements Protob @Override public boolean remove(Object o) { ensureIsMutable(); - return super.remove(o); + int index = indexOf(o); + if (index == -1) { + return false; + } + remove(index); + return true; } @Override diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java index f023baa9a0..451fce1e84 100644 --- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java @@ -267,20 +267,6 @@ final class BooleanArrayList extends AbstractProtobufList return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i - 1); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Boolean remove(int index) { ensureIsMutable(); diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java index e20a8858c2..ff81e0032f 100644 --- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java +++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java @@ -41,6 +41,7 @@ import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; @@ -2009,14 +2010,14 @@ public abstract class CodedInputStream { int prevPos = buffer.position(); int prevLimit = buffer.limit(); try { - buffer.position(bufferPos(begin)); - buffer.limit(bufferPos(end)); + ((Buffer) buffer).position(bufferPos(begin)); + ((Buffer) buffer).limit(bufferPos(end)); return buffer.slice(); } catch (IllegalArgumentException e) { throw InvalidProtocolBufferException.truncatedMessage(); } finally { - buffer.position(prevPos); - buffer.limit(prevLimit); + ((Buffer) buffer).position(prevPos); + ((Buffer) buffer).limit(prevLimit); } } } @@ -3910,14 +3911,14 @@ public abstract class CodedInputStream { int prevPos = currentByteBuffer.position(); int prevLimit = currentByteBuffer.limit(); try { - currentByteBuffer.position(begin); - currentByteBuffer.limit(end); + ((Buffer) currentByteBuffer).position(begin); + ((Buffer) currentByteBuffer).limit(end); return currentByteBuffer.slice(); } catch (IllegalArgumentException e) { throw InvalidProtocolBufferException.truncatedMessage(); } finally { - currentByteBuffer.position(prevPos); - currentByteBuffer.limit(prevLimit); + ((Buffer) currentByteBuffer).position(prevPos); + ((Buffer) currentByteBuffer).limit(prevLimit); } } } diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java index f27602aeb2..c30b00ddf7 100644 --- a/java/core/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java @@ -764,7 +764,10 @@ public final class Descriptors { /** * Finds a field by name. * - * @param name The unqualified name of the field (e.g. "foo"). + * @param name The unqualified name of the field (e.g. "foo"). For protocol buffer messages that + * follow Google's + * guidance on naming this will be a snake case string, such as
song_name
. * @return The field's descriptor, or {@code null} if not found. */ public FieldDescriptor findFieldByName(final String name) { diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java index 12824abe66..4085653437 100644 --- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java @@ -267,20 +267,6 @@ final class DoubleArrayList extends AbstractProtobufList return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i - 1); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Double remove(int index) { ensureIsMutable(); diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java index 241fcbd932..0a63fad187 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java @@ -46,7 +46,6 @@ final class ExtensionRegistryFactory { @Nullable */ static final Class EXTENSION_REGISTRY_CLASS = reflectExtensionRegistry(); - /* @Nullable */ static Class reflectExtensionRegistry() { try { return Class.forName(FULL_REGISTRY_CLASS_NAME); @@ -77,7 +76,6 @@ final class ExtensionRegistryFactory { && EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass()); } - /* @Nullable */ private static final ExtensionRegistryLite invokeSubclassFactory(String methodName) { if (EXTENSION_REGISTRY_CLASS == null) { return null; diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java index 0c4b20ed74..caa58e1ada 100644 --- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java +++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java @@ -84,10 +84,8 @@ public class ExtensionRegistryLite { static final String EXTENSION_CLASS_NAME = "com.google.protobuf.Extension"; private static class ExtensionClassHolder { - /* @Nullable */ static final Class INSTANCE = resolveExtensionClass(); - /* @Nullable */ static Class resolveExtensionClass() { try { return Class.forName(EXTENSION_CLASS_NAME); diff --git a/java/core/src/main/java/com/google/protobuf/FieldType.java b/java/core/src/main/java/com/google/protobuf/FieldType.java index 1b8f9e5da2..72327537fd 100644 --- a/java/core/src/main/java/com/google/protobuf/FieldType.java +++ b/java/core/src/main/java/com/google/protobuf/FieldType.java @@ -204,7 +204,6 @@ public enum FieldType { * * @return the {@link FieldType} or {@code null} if not found. */ - /* @Nullable */ public static FieldType forId(int id) { if (id < 0 || id >= VALUES.length) { return null; @@ -228,7 +227,6 @@ public enum FieldType { * * @return the generic super class/interface, or {@code null} if not found. */ - /* @Nullable */ private static Type getGenericSuperList(Class clazz) { // First look at interfaces. Type[] genericInterfaces = clazz.getGenericInterfaces(); diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java index 9589816f8e..e6feba8a35 100644 --- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java @@ -266,20 +266,6 @@ final class FloatArrayList extends AbstractProtobufList return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i - 1); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Float remove(int index) { ensureIsMutable(); diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java index e9c3b1aee0..9daeebed99 100644 --- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java @@ -266,20 +266,6 @@ final class IntArrayList extends AbstractProtobufList return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i - 1); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Integer remove(int index) { ensureIsMutable(); diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java index 0826351bcb..90643b8abb 100644 --- a/java/core/src/main/java/com/google/protobuf/Internal.java +++ b/java/core/src/main/java/com/google/protobuf/Internal.java @@ -30,7 +30,6 @@ package com.google.protobuf; -import java.io.IOException; import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.charset.Charset; diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java index 04f44756c4..bda43a41bb 100644 --- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java +++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java @@ -266,20 +266,6 @@ final class LongArrayList extends AbstractProtobufList return true; } - @Override - public boolean remove(Object o) { - ensureIsMutable(); - for (int i = 0; i < size; i++) { - if (o.equals(array[i])) { - System.arraycopy(array, i + 1, array, i, size - i - 1); - size--; - modCount++; - return true; - } - } - return false; - } - @Override public Long remove(int index) { ensureIsMutable(); diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java index 28879d7785..33c8e914b2 100644 --- a/java/core/src/main/java/com/google/protobuf/MessageSchema.java +++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java @@ -2572,7 +2572,7 @@ final class MessageSchema implements Schema { int presenceMaskAndOffset = 0; int presenceMask = 0; - if (!proto3 && fieldType <= 17) { + if (fieldType <= 17) { presenceMaskAndOffset = buffer[pos + 2]; final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK; if (presenceFieldOffset != currentPresenceFieldOffset) { diff --git a/java/core/src/main/java/com/google/protobuf/NioByteString.java b/java/core/src/main/java/com/google/protobuf/NioByteString.java index 64c46be689..1e594ff878 100644 --- a/java/core/src/main/java/com/google/protobuf/NioByteString.java +++ b/java/core/src/main/java/com/google/protobuf/NioByteString.java @@ -37,6 +37,7 @@ import java.io.InputStream; import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.OutputStream; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.InvalidMarkException; @@ -109,7 +110,7 @@ final class NioByteString extends ByteString.LeafByteString { protected void copyToInternal( byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { ByteBuffer slice = buffer.slice(); - slice.position(sourceOffset); + ((Buffer) slice).position(sourceOffset); slice.get(target, targetOffset, numberToCopy); } @@ -285,8 +286,8 @@ final class NioByteString extends ByteString.LeafByteString { } ByteBuffer slice = buffer.slice(); - slice.position(beginIndex - buffer.position()); - slice.limit(endIndex - buffer.position()); + ((Buffer) slice).position(beginIndex - buffer.position()); + ((Buffer) slice).limit(endIndex - buffer.position()); return slice; } } diff --git a/java/core/src/main/java/com/google/protobuf/Protobuf.java b/java/core/src/main/java/com/google/protobuf/Protobuf.java index adaa7fa8f2..0affac5f0a 100644 --- a/java/core/src/main/java/com/google/protobuf/Protobuf.java +++ b/java/core/src/main/java/com/google/protobuf/Protobuf.java @@ -76,11 +76,8 @@ final class Protobuf { schemaFor(message).makeImmutable(message); } - /** - * Checks if all required fields are set. TODO(xiaofeng): Make this package private when the tests - * are moved to protobuf package. - */ - public boolean isInitialized(T message) { + /** Checks if all required fields are set. */ + boolean isInitialized(T message) { return schemaFor(message).isInitialized(message); } diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java index 54d4180595..cc6e0445b0 100644 --- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java +++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java @@ -845,7 +845,10 @@ final class RopeByteString extends ByteString { throw new IndexOutOfBoundsException(); } int bytesRead = readSkipInternal(b, offset, length); - if (bytesRead == 0) { + if (bytesRead == 0 && (length > 0 || availableInternal() == 0)) { + // Modeling ByteArrayInputStream.read(byte[], int, int) behavior noted above: + // It's ok to read 0 bytes on purpose (length == 0) from a stream that isn't at EOF. + // It's not ok to try to read bytes (even 0 bytes) from a stream that is at EOF. return -1; } else { return bytesRead; @@ -905,8 +908,7 @@ final class RopeByteString extends ByteString { @Override public int available() throws IOException { - int bytesRead = currentPieceOffsetInRope + currentPieceIndex; - return RopeByteString.this.size() - bytesRead; + return availableInternal(); } @Override @@ -955,5 +957,11 @@ final class RopeByteString extends ByteString { } } } + + /** Computes the number of bytes still available to read. */ + private int availableInternal() { + int bytesRead = currentPieceOffsetInRope + currentPieceIndex; + return RopeByteString.this.size() - bytesRead; + } } } diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java index 7f744ddba7..bbc0f8dd94 100644 --- a/java/core/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java @@ -30,6 +30,8 @@ package com.google.protobuf; +import static java.nio.charset.StandardCharsets.UTF_8; + import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.EnumDescriptor; import com.google.protobuf.Descriptors.EnumValueDescriptor; @@ -2375,6 +2377,73 @@ public final class TextFormat { result[pos++] = (byte) code; break; + case 'u': + // Unicode escape + ++i; + if (i + 3 < input.size() + && isHex(input.byteAt(i)) + && isHex(input.byteAt(i + 1)) + && isHex(input.byteAt(i + 2)) + && isHex(input.byteAt(i + 3))) { + char ch = + (char) + (digitValue(input.byteAt(i)) << 12 + | digitValue(input.byteAt(i + 1)) << 8 + | digitValue(input.byteAt(i + 2)) << 4 + | digitValue(input.byteAt(i + 3))); + if (Character.isSurrogate(ch)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\u' refers to a surrogate"); + } + byte[] chUtf8 = Character.toString(ch).getBytes(UTF_8); + System.arraycopy(chUtf8, 0, result, pos, chUtf8.length); + pos += chUtf8.length; + i += 3; + } else { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\u' with too few hex chars"); + } + break; + + case 'U': + // Unicode escape + ++i; + if (i + 7 >= input.size()) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U' with too few hex chars"); + } + int codepoint = 0; + for (int offset = i; offset < i + 8; offset++) { + byte b = input.byteAt(offset); + if (!isHex(b)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U' with too few hex chars"); + } + codepoint = (codepoint << 4) | digitValue(b); + } + if (!Character.isValidCodePoint(codepoint)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U" + + input.substring(i, i + 8).toStringUtf8() + + "' is not a valid code point value"); + } + Character.UnicodeBlock unicodeBlock = Character.UnicodeBlock.of(codepoint); + if (unicodeBlock.equals(Character.UnicodeBlock.LOW_SURROGATES) + || unicodeBlock.equals(Character.UnicodeBlock.HIGH_SURROGATES) + || unicodeBlock.equals(Character.UnicodeBlock.HIGH_PRIVATE_USE_SURROGATES)) { + throw new InvalidEscapeSequenceException( + "Invalid escape sequence: '\\U" + + input.substring(i, i + 8).toStringUtf8() + + "' refers to a surrogate code unit"); + } + int[] codepoints = new int[1]; + codepoints[0] = codepoint; + byte[] chUtf8 = new String(codepoints, 0, 1).getBytes(UTF_8); + System.arraycopy(chUtf8, 0, result, pos, chUtf8.length); + pos += chUtf8.length; + i += 7; + break; + default: throw new InvalidEscapeSequenceException( "Invalid escape sequence: '\\" + (char) c + '\''); diff --git a/java/core/src/main/java/com/google/protobuf/TypeRegistry.java b/java/core/src/main/java/com/google/protobuf/TypeRegistry.java index 47d798bfe6..422ff1f870 100644 --- a/java/core/src/main/java/com/google/protobuf/TypeRegistry.java +++ b/java/core/src/main/java/com/google/protobuf/TypeRegistry.java @@ -70,7 +70,6 @@ public class TypeRegistry { /** * Find a type by its typeUrl. Returns null if it cannot be found in this {@link TypeRegistry}. */ - /* @Nullable */ public final Descriptor getDescriptorForTypeUrl(String typeUrl) throws InvalidProtocolBufferException { return find(getTypeName(typeUrl)); diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java index b435327ab8..471238ae43 100644 --- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java +++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java @@ -41,7 +41,6 @@ import java.util.logging.Logger; /** Utility class for working with unsafe operations. */ final class UnsafeUtil { - private static final Logger logger = Logger.getLogger(UnsafeUtil.class.getName()); private static final sun.misc.Unsafe UNSAFE = getUnsafe(); private static final Class MEMORY_CLASS = Android.getMemoryClass(); private static final boolean IS_ANDROID_64 = determineAndroidSupportByAddressSize(long.class); @@ -363,9 +362,13 @@ final class UnsafeUtil { return true; } catch (Throwable e) { - logger.log( - Level.WARNING, - "platform method missing - proto runtime falling back to safer methods: " + e); + // Because log statements are fairly sparse in this class, this logger is initialized + // non-statically. Static initialization adds undue runtime costs to the first client to + // initialize this class. + Logger.getLogger(UnsafeUtil.class.getName()) + .log( + Level.WARNING, + "platform method missing - proto runtime falling back to safer methods: " + e); } return false; } @@ -397,9 +400,13 @@ final class UnsafeUtil { clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class); return true; } catch (Throwable e) { - logger.log( - Level.WARNING, - "platform method missing - proto runtime falling back to safer methods: " + e); + // Because log statements are fairly sparse in this class, this logger is initialized + // non-statically. Static initialization adds undue runtime costs to the first client to + // initialize this class. + Logger.getLogger(UnsafeUtil.class.getName()) + .log( + Level.WARNING, + "platform method missing - proto runtime falling back to safer methods: " + e); } return false; } diff --git a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java index 9f64b6baba..4177a47e67 100644 --- a/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java +++ b/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java @@ -514,6 +514,20 @@ public class LiteralByteStringTest extends TestCase { assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read()); } + public void testNewInput_readZeroBytes() throws IOException { + InputStream input = stringUnderTest.newInput(); + assertEquals( + classUnderTest + " InputStream.read() returns 0 when told to read 0 bytes and not at EOF", + 0, + input.read(new byte[0])); + + input.skip(input.available()); + assertEquals( + classUnderTest + " InputStream.read() returns -1 when told to read 0 bytes at EOF", + -1, + input.read(new byte[0])); + } + public void testNewInput_skip() throws IOException { InputStream input = stringUnderTest.newInput(); int stringSize = stringUnderTest.size(); diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java index adca1d51b6..9994ad067a 100644 --- a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java @@ -77,44 +77,44 @@ public final class MapForProto2LiteTest extends TestCase { 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()); + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); } private void assertMapValuesSet(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(11, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(22, message.getInt32ToInt32Field().get(2).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("11", message.getInt32ToStringField().get(1)); - assertEquals("22", message.getInt32ToStringField().get(2)); - assertEquals("33", message.getInt32ToStringField().get(3)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("11", message.getInt32ToStringFieldMap().get(1)); + assertEquals("22", message.getInt32ToStringFieldMap().get(2)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(11, message.getStringToInt32Field().get("1").intValue()); - assertEquals(22, message.getStringToInt32Field().get("2").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); } private void updateMapValues(TestMap.Builder builder) { @@ -152,35 +152,35 @@ public final class MapForProto2LiteTest extends TestCase { } private void assertMapValuesUpdated(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(4).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("111", message.getInt32ToStringField().get(1)); - assertEquals("33", message.getInt32ToStringField().get(3)); - assertEquals("44", message.getInt32ToStringField().get(4)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(111, message.getStringToInt32Field().get("1").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); - assertEquals(44, message.getStringToInt32Field().get("4").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); } private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { @@ -206,13 +206,13 @@ public final class MapForProto2LiteTest extends TestCase { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); builder.putInt32ToInt32Field(1, 2); - assertTrue(message.getInt32ToInt32Field().isEmpty()); + assertTrue(message.getInt32ToInt32FieldMap().isEmpty()); message = builder.build(); - assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); - assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); builder.putInt32ToInt32Field(2, 3); - assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); - assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); } public void testGetMapIsImmutable() { @@ -254,30 +254,31 @@ public final class MapForProto2LiteTest extends TestCase { public void testMutableMapLifecycle() { TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2); - assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); - assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); builder.putInt32ToInt32Field(2, 3); - assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR); - assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); - assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField()); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumFieldMap()); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumFieldMap()); builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO); assertEquals( - newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField()); + newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), + builder.getInt32ToEnumFieldMap()); builder.putInt32ToStringField(1, "1"); - assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); - assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); + assertEquals(newMap(1, "1"), builder.build().getInt32ToStringFieldMap()); + assertEquals(newMap(1, "1"), builder.getInt32ToStringFieldMap()); builder.putInt32ToStringField(2, "2"); - assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringField()); + assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringFieldMap()); builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance()); assertEquals( newMap(1, TestMap.MessageValue.getDefaultInstance()), - builder.build().getInt32ToMessageField()); + builder.build().getInt32ToMessageFieldMap()); assertEquals( - newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField()); + newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageFieldMap()); builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance()); assertEquals( newMap( @@ -285,7 +286,7 @@ public final class MapForProto2LiteTest extends TestCase { TestMap.MessageValue.getDefaultInstance(), 2, TestMap.MessageValue.getDefaultInstance()), - builder.getInt32ToMessageField()); + builder.getInt32ToMessageFieldMap()); } public void testGettersAndSetters() throws Exception { @@ -415,7 +416,7 @@ public final class MapForProto2LiteTest extends TestCase { } catch (InvalidProtocolBufferException expected) { assertTrue(expected.getUnfinishedMessage() instanceof TestMap); map = (TestMap) expected.getUnfinishedMessage(); - assertTrue(map.getInt32ToMessageField().isEmpty()); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); } map = @@ -476,14 +477,14 @@ public final class MapForProto2LiteTest extends TestCase { TestMap message = TestMap.parseFrom(data); // Entries with unknown enum values will be stored into UnknownFieldSet so // there is only one entry in the map. - assertEquals(1, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); + assertEquals(1, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); // Serializing and parsing should preserve the unknown entry. data = message.toByteString(); TestUnknownEnumValue messageWithUnknownEnums = TestUnknownEnumValue.parseFrom(data); - assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size()); - assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue()); - assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue()); + assertEquals(2, messageWithUnknownEnums.getInt32ToInt32FieldMap().size()); + assertEquals(1, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(2).intValue()); } public void testIterationOrder() throws Exception { @@ -493,7 +494,7 @@ public final class MapForProto2LiteTest extends TestCase { assertEquals( Arrays.asList("1", "2", "3"), - new ArrayList(message.getStringToInt32Field().keySet())); + new ArrayList(message.getStringToInt32FieldMap().keySet())); } private static Map newMap(K key1, V value1) { @@ -513,10 +514,10 @@ public final class MapForProto2LiteTest extends TestCase { TestMap.Builder builder = TestMap.newBuilder(); setMapValues(builder); TestMap message = builder.build(); - assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap()); - assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap()); - assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap()); - assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap()); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); } public void testContains() { diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java index bb706326c4..b995802b4f 100644 --- a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java +++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java @@ -119,12 +119,12 @@ public class MapForProto2Test extends TestCase { 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()); + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); } private void assertMapValuesSet(TestMapOrBuilder message) { @@ -236,35 +236,35 @@ public class MapForProto2Test extends TestCase { } private void assertMapValuesUpdated(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(4).intValue()); - - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("111", message.getInt32ToStringField().get(1)); - assertEquals("33", message.getInt32ToStringField().get(3)); - assertEquals("44", message.getInt32ToStringField().get(4)); - - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); - - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); - - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); - - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(111, message.getStringToInt32Field().get("1").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); - assertEquals(44, message.getStringToInt32Field().get("4").intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); + + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); + + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); + + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); + + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); + + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); } private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { @@ -563,7 +563,7 @@ public class MapForProto2Test extends TestCase { } catch (InvalidProtocolBufferException expected) { assertTrue(expected.getUnfinishedMessage() instanceof TestMap); map = (TestMap) expected.getUnfinishedMessage(); - assertTrue(map.getInt32ToMessageField().isEmpty()); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); } map = @@ -698,8 +698,8 @@ public class MapForProto2Test extends TestCase { builder.clearField(f("int32_to_int32_field")); builder.clearField(f("int32_to_message_field")); message = builder.build(); - assertEquals(0, message.getInt32ToInt32Field().size()); - assertEquals(0, message.getInt32ToMessageField().size()); + assertEquals(0, message.getInt32ToInt32FieldMap().size()); + assertEquals(0, message.getInt32ToMessageFieldMap().size()); // Test setField() setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44)); @@ -710,10 +710,10 @@ public class MapForProto2Test extends TestCase { 111, MessageValue.newBuilder().setValue(222).build(), 333, MessageValue.newBuilder().setValue(444).build())); message = builder.build(); - assertEquals(22, message.getInt32ToInt32Field().get(11).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(33).intValue()); - assertEquals(222, message.getInt32ToMessageField().get(111).getValue()); - assertEquals(444, message.getInt32ToMessageField().get(333).getValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(11).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(33).intValue()); + assertEquals(222, message.getInt32ToMessageFieldMap().get(111).getValue()); + assertEquals(444, message.getInt32ToMessageFieldMap().get(333).getValue()); // Test addRepeatedField builder.addRepeatedField( @@ -726,8 +726,8 @@ public class MapForProto2Test extends TestCase { 555, MessageValue.newBuilder().setValue(666).build())); message = builder.build(); - assertEquals(66, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(666, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(66, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(666, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test addRepeatedField (overriding existing values) builder.addRepeatedField( @@ -740,8 +740,8 @@ public class MapForProto2Test extends TestCase { 555, MessageValue.newBuilder().setValue(555).build())); message = builder.build(); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(555, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(555, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test setRepeatedField for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) { @@ -755,9 +755,9 @@ public class MapForProto2Test extends TestCase { builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build()); } message = builder.build(); - assertEquals(11, message.getInt32ToInt32Field().get(22).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(44).intValue()); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(22).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(44).intValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); } // See additional coverage in TextFormatTest.java. @@ -844,16 +844,16 @@ public class MapForProto2Test extends TestCase { TestMap message = TestMap.parseFrom(data); // Entries with unknown enum values will be stored into UnknownFieldSet so // there is only one entry in the map. - assertEquals(1, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); + assertEquals(1, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); // UnknownFieldSet should not be empty. assertFalse(message.getUnknownFields().asMap().isEmpty()); // Serializing and parsing should preserve the unknown entry. data = message.toByteString(); TestUnknownEnumValue messageWithUnknownEnums = TestUnknownEnumValue.parseFrom(data); - assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size()); - assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue()); - assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue()); + assertEquals(2, messageWithUnknownEnums.getInt32ToInt32FieldMap().size()); + assertEquals(1, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32FieldMap().get(2).intValue()); } public void testRequiredMessage() throws Exception { @@ -885,7 +885,7 @@ public class MapForProto2Test extends TestCase { assertEquals( Arrays.asList("1", "2", "3"), - new ArrayList(message.getStringToInt32Field().keySet())); + new ArrayList(message.getStringToInt32FieldMap().keySet())); } public void testContains() { @@ -1172,9 +1172,9 @@ public class MapForProto2Test extends TestCase { setMapValuesUsingAccessors(builder); assertMapValuesSet(builder); TestMap message = builder.build(); - assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap()); - assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap()); - assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap()); - assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap()); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); } } diff --git a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java index d18fd13e0a..40bb7893b3 100644 --- a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java @@ -84,44 +84,44 @@ public final class MapLiteTest extends TestCase { 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()); + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); } private void assertMapValuesSet(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(11, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(22, message.getInt32ToInt32Field().get(2).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("11", message.getInt32ToStringField().get(1)); - assertEquals("22", message.getInt32ToStringField().get(2)); - assertEquals("33", message.getInt32ToStringField().get(3)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("11", message.getInt32ToStringFieldMap().get(1)); + assertEquals("22", message.getInt32ToStringFieldMap().get(2)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(11, message.getStringToInt32Field().get("1").intValue()); - assertEquals(22, message.getStringToInt32Field().get("2").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); } private void updateMapValues(TestMap.Builder builder) { @@ -159,35 +159,35 @@ public final class MapLiteTest extends TestCase { } private void assertMapValuesUpdated(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(4).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("111", message.getInt32ToStringField().get(1)); - assertEquals("33", message.getInt32ToStringField().get(3)); - assertEquals("44", message.getInt32ToStringField().get(4)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(111, message.getStringToInt32Field().get("1").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); - assertEquals(44, message.getStringToInt32Field().get("4").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); } private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { @@ -213,12 +213,12 @@ public final class MapLiteTest extends TestCase { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); builder.putInt32ToInt32Field(1, 2); - assertTrue(message.getInt32ToInt32Field().isEmpty()); - assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertTrue(message.getInt32ToInt32FieldMap().isEmpty()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); message = builder.build(); builder.putInt32ToInt32Field(2, 3); - assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); - assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), message.getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); } public void testGetMapIsImmutable() { @@ -266,30 +266,31 @@ public final class MapLiteTest extends TestCase { public void testMutableMapLifecycle() { TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2); - assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); - assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32FieldMap()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32FieldMap()); builder.putInt32ToInt32Field(2, 3); - assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32FieldMap()); builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR); - assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); - assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField()); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumFieldMap()); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumFieldMap()); builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO); assertEquals( - newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), builder.getInt32ToEnumField()); + newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), + builder.getInt32ToEnumFieldMap()); builder.putInt32ToStringField(1, "1"); - assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); - assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); + assertEquals(newMap(1, "1"), builder.build().getInt32ToStringFieldMap()); + assertEquals(newMap(1, "1"), builder.getInt32ToStringFieldMap()); builder.putInt32ToStringField(2, "2"); - assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringField()); + assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringFieldMap()); builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance()); assertEquals( newMap(1, TestMap.MessageValue.getDefaultInstance()), - builder.build().getInt32ToMessageField()); + builder.build().getInt32ToMessageFieldMap()); assertEquals( - newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageField()); + newMap(1, TestMap.MessageValue.getDefaultInstance()), builder.getInt32ToMessageFieldMap()); builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance()); assertEquals( newMap( @@ -297,7 +298,7 @@ public final class MapLiteTest extends TestCase { TestMap.MessageValue.getDefaultInstance(), 2, TestMap.MessageValue.getDefaultInstance()), - builder.getInt32ToMessageField()); + builder.getInt32ToMessageFieldMap()); } public void testGettersAndSetters() throws Exception { @@ -342,12 +343,12 @@ public final class MapLiteTest extends TestCase { TestMap source = sourceBuilder.build(); TestMap.Builder destinationBuilder = TestMap.newBuilder(); - destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue()); + destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap()); 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()); + assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue()); + assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue()); + assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue()); assertEquals(3, destination.getInt32ToEnumFieldCount()); } @@ -459,7 +460,7 @@ public final class MapLiteTest extends TestCase { } catch (InvalidProtocolBufferException expected) { assertTrue(expected.getUnfinishedMessage() instanceof TestMap); map = (TestMap) expected.getUnfinishedMessage(); - assertTrue(map.getInt32ToMessageField().isEmpty()); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); } map = @@ -524,24 +525,24 @@ public final class MapLiteTest extends TestCase { .putInt32ToEnumFieldValue(2, 1000); // unknown value. TestMap message = builder.build(); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(0)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2)); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2)); builder.putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value. message = builder.build(); - assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2)); + assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2)); // Unknown enum values should be preserved after: // 1. Serialization and parsing. // 2. toBuild(). // 3. mergeFrom(). message = TestMap.parseFrom(message.toByteString()); - assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue()); builder = message.toBuilder(); - assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); builder = TestMap.newBuilder().mergeFrom(message); - assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); // hashCode()/equals() should take unknown enum values into account. builder.putAllInt32ToEnumFieldValue(newMap(2, 1001)); @@ -550,7 +551,7 @@ public final class MapLiteTest extends TestCase { assertFalse(message.equals(message2)); // Unknown values will be converted to UNRECOGNIZED so the resulted enum map // should be the same. - assertEquals(message2.getInt32ToEnumField(), message.getInt32ToEnumField()); + assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); } public void testIterationOrder() throws Exception { @@ -559,18 +560,18 @@ public final class MapLiteTest extends TestCase { TestMap message = builder.build(); assertEquals( - Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32Field().keySet())); + Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet())); } public void testGetMap() { TestMap.Builder builder = TestMap.newBuilder(); setMapValues(builder); TestMap message = builder.build(); - assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap()); - assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap()); - assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap()); - assertEquals(message.getInt32ToEnumFieldValue(), message.getInt32ToEnumFieldValueMap()); - assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap()); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); } public void testContains() { diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java index 9f1ebaed69..f3458dd235 100644 --- a/java/core/src/test/java/com/google/protobuf/MapTest.java +++ b/java/core/src/test/java/com/google/protobuf/MapTest.java @@ -122,44 +122,44 @@ public class MapTest extends TestCase { 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()); + .putAllInt32ToInt32Field(source.getInt32ToInt32FieldMap()) + .putAllInt32ToStringField(source.getInt32ToStringFieldMap()) + .putAllInt32ToBytesField(source.getInt32ToBytesFieldMap()) + .putAllInt32ToEnumField(source.getInt32ToEnumFieldMap()) + .putAllInt32ToMessageField(source.getInt32ToMessageFieldMap()) + .putAllStringToInt32Field(source.getStringToInt32FieldMap()); } private void assertMapValuesSet(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(11, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(22, message.getInt32ToInt32Field().get(2).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(2).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("11", message.getInt32ToStringField().get(1)); - assertEquals("22", message.getInt32ToStringField().get(2)); - assertEquals("33", message.getInt32ToStringField().get(3)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("11", message.getInt32ToStringFieldMap().get(1)); + assertEquals("22", message.getInt32ToStringFieldMap().get(2)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesFieldMap().get(2)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(11, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(22, message.getInt32ToMessageField().get(2).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(11, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(22, message.getInt32ToMessageFieldMap().get(2).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(11, message.getStringToInt32Field().get("1").intValue()); - assertEquals(22, message.getStringToInt32Field().get("2").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(11, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(22, message.getStringToInt32FieldMap().get("2").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); } private void updateMapValuesUsingMutableMap(TestMap.Builder builder) { @@ -239,35 +239,35 @@ public class MapTest extends TestCase { } private void assertMapValuesUpdated(TestMap message) { - assertEquals(3, message.getInt32ToInt32Field().size()); - assertEquals(111, message.getInt32ToInt32Field().get(1).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(3).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(4).intValue()); + assertEquals(3, message.getInt32ToInt32FieldMap().size()); + assertEquals(111, message.getInt32ToInt32FieldMap().get(1).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(3).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(4).intValue()); - assertEquals(3, message.getInt32ToStringField().size()); - assertEquals("111", message.getInt32ToStringField().get(1)); - assertEquals("33", message.getInt32ToStringField().get(3)); - assertEquals("44", message.getInt32ToStringField().get(4)); + assertEquals(3, message.getInt32ToStringFieldMap().size()); + assertEquals("111", message.getInt32ToStringFieldMap().get(1)); + assertEquals("33", message.getInt32ToStringFieldMap().get(3)); + assertEquals("44", message.getInt32ToStringFieldMap().get(4)); - assertEquals(3, message.getInt32ToBytesField().size()); - assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1)); - assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3)); - assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4)); + assertEquals(3, message.getInt32ToBytesFieldMap().size()); + assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesFieldMap().get(1)); + assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesFieldMap().get(3)); + assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesFieldMap().get(4)); - assertEquals(3, message.getInt32ToEnumField().size()); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3)); - assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4)); + assertEquals(3, message.getInt32ToEnumFieldMap().size()); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumFieldMap().get(3)); + assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumFieldMap().get(4)); - assertEquals(3, message.getInt32ToMessageField().size()); - assertEquals(111, message.getInt32ToMessageField().get(1).getValue()); - assertEquals(33, message.getInt32ToMessageField().get(3).getValue()); - assertEquals(44, message.getInt32ToMessageField().get(4).getValue()); + assertEquals(3, message.getInt32ToMessageFieldMap().size()); + assertEquals(111, message.getInt32ToMessageFieldMap().get(1).getValue()); + assertEquals(33, message.getInt32ToMessageFieldMap().get(3).getValue()); + assertEquals(44, message.getInt32ToMessageFieldMap().get(4).getValue()); - assertEquals(3, message.getStringToInt32Field().size()); - assertEquals(111, message.getStringToInt32Field().get("1").intValue()); - assertEquals(33, message.getStringToInt32Field().get("3").intValue()); - assertEquals(44, message.getStringToInt32Field().get("4").intValue()); + assertEquals(3, message.getStringToInt32FieldMap().size()); + assertEquals(111, message.getStringToInt32FieldMap().get("1").intValue()); + assertEquals(33, message.getStringToInt32FieldMap().get("3").intValue()); + assertEquals(44, message.getStringToInt32FieldMap().get("4").intValue()); } private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) { @@ -468,11 +468,13 @@ public class MapTest extends TestCase { .build(); TestMap destination = - TestMap.newBuilder().putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue()).build(); + TestMap.newBuilder() + .putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValueMap()) + .build(); - assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue()); - assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue()); - assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(0, destination.getInt32ToEnumFieldValueMap().get(0).intValue()); + assertEquals(1, destination.getInt32ToEnumFieldValueMap().get(1).intValue()); + assertEquals(1000, destination.getInt32ToEnumFieldValueMap().get(2).intValue()); assertEquals(3, destination.getInt32ToEnumFieldCount()); } @@ -583,7 +585,7 @@ public class MapTest extends TestCase { } catch (InvalidProtocolBufferException expected) { assertTrue(expected.getUnfinishedMessage() instanceof TestMap); map = (TestMap) expected.getUnfinishedMessage(); - assertTrue(map.getInt32ToMessageField().isEmpty()); + assertTrue(map.getInt32ToMessageFieldMap().isEmpty()); } map = @@ -644,14 +646,14 @@ public class MapTest extends TestCase { TestOnChangeEventPropagation.Builder parent = TestOnChangeEventPropagation.newBuilder(); parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2); TestOnChangeEventPropagation message = parent.build(); - assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(2, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Make a change using nested builder. parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3); // Should be able to observe the change. message = parent.build(); - assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(3, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Make another change using mergeFrom() TestMap other = TestMap.newBuilder().putInt32ToInt32Field(1, 4).build(); @@ -659,14 +661,14 @@ public class MapTest extends TestCase { // Should be able to observe the change. message = parent.build(); - assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Make yet another change by clearing the nested builder. parent.getOptionalMessageBuilder().clear(); // Should be able to observe the change. message = parent.build(); - assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size()); + assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size()); } public void testNestedBuilderOnChangeEventPropagationReflection() { @@ -683,7 +685,7 @@ public class MapTest extends TestCase { // Should be able to observe the change. TestOnChangeEventPropagation message = parentBuilder.build(); - assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size()); + assertEquals(1, message.getOptionalMessage().getInt32ToInt32FieldMap().size()); // Change the entry value. entryBuilder.putInt32ToInt32Field(1, 4); @@ -692,7 +694,7 @@ public class MapTest extends TestCase { // Should be able to observe the change. message = parentBuilder.build(); - assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue()); + assertEquals(4, message.getOptionalMessage().getInt32ToInt32FieldMap().get(1).intValue()); // Clear the nested builder. testMapBuilder = parentBuilder.getOptionalMessageBuilder(); @@ -700,7 +702,7 @@ public class MapTest extends TestCase { // Should be able to observe the change. message = parentBuilder.build(); - assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size()); + assertEquals(0, message.getOptionalMessage().getInt32ToInt32FieldMap().size()); } // The following methods are used to test reflection API. @@ -789,8 +791,8 @@ public class MapTest extends TestCase { builder.clearField(f("int32_to_int32_field")); builder.clearField(f("int32_to_message_field")); message = builder.build(); - assertEquals(0, message.getInt32ToInt32Field().size()); - assertEquals(0, message.getInt32ToMessageField().size()); + assertEquals(0, message.getInt32ToInt32FieldMap().size()); + assertEquals(0, message.getInt32ToMessageFieldMap().size()); // Test setField() setMapValues(builder, "int32_to_int32_field", mapForValues(11, 22, 33, 44)); @@ -801,10 +803,10 @@ public class MapTest extends TestCase { 111, MessageValue.newBuilder().setValue(222).build(), 333, MessageValue.newBuilder().setValue(444).build())); message = builder.build(); - assertEquals(22, message.getInt32ToInt32Field().get(11).intValue()); - assertEquals(44, message.getInt32ToInt32Field().get(33).intValue()); - assertEquals(222, message.getInt32ToMessageField().get(111).getValue()); - assertEquals(444, message.getInt32ToMessageField().get(333).getValue()); + assertEquals(22, message.getInt32ToInt32FieldMap().get(11).intValue()); + assertEquals(44, message.getInt32ToInt32FieldMap().get(33).intValue()); + assertEquals(222, message.getInt32ToMessageFieldMap().get(111).getValue()); + assertEquals(444, message.getInt32ToMessageFieldMap().get(333).getValue()); // Test addRepeatedField builder.addRepeatedField( @@ -817,8 +819,8 @@ public class MapTest extends TestCase { 555, MessageValue.newBuilder().setValue(666).build())); message = builder.build(); - assertEquals(66, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(666, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(66, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(666, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test addRepeatedField (overriding existing values) builder.addRepeatedField( @@ -831,8 +833,8 @@ public class MapTest extends TestCase { 555, MessageValue.newBuilder().setValue(555).build())); message = builder.build(); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); - assertEquals(555, message.getInt32ToMessageField().get(555).getValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); + assertEquals(555, message.getInt32ToMessageFieldMap().get(555).getValue()); // Test setRepeatedField for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) { @@ -846,9 +848,9 @@ public class MapTest extends TestCase { builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build()); } message = builder.build(); - assertEquals(11, message.getInt32ToInt32Field().get(22).intValue()); - assertEquals(33, message.getInt32ToInt32Field().get(44).intValue()); - assertEquals(55, message.getInt32ToInt32Field().get(55).intValue()); + assertEquals(11, message.getInt32ToInt32FieldMap().get(22).intValue()); + assertEquals(33, message.getInt32ToInt32FieldMap().get(44).intValue()); + assertEquals(55, message.getInt32ToInt32FieldMap().get(55).intValue()); } // See additional coverage in TextFormatTest.java. @@ -937,21 +939,21 @@ public class MapTest extends TestCase { 2, 1000)); // unknown value. TestMap message = builder.build(); - assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(0)); - assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1)); - assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2)); - assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumFieldMap().get(0)); + assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumFieldMap().get(1)); + assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumFieldMap().get(2)); + assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue()); // Unknown enum values should be preserved after: // 1. Serialization and parsing. // 2. toBuild(). // 3. mergeFrom(). message = TestMap.parseFrom(message.toByteString()); - assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, message.getInt32ToEnumFieldValueMap().get(2).intValue()); builder = message.toBuilder(); - assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); builder = TestMap.newBuilder().mergeFrom(message); - assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue()); + assertEquals(1000, builder.getInt32ToEnumFieldValueMap().get(2).intValue()); // hashCode()/equals() should take unknown enum values into account. builder.putAllInt32ToEnumFieldValue(newMap(2, 1001)); @@ -960,7 +962,7 @@ public class MapTest extends TestCase { assertFalse(message.equals(message2)); // Unknown values will be converted to UNRECOGNIZED so the resulted enum map // should be the same. - assertEquals(message2.getInt32ToEnumField(), message.getInt32ToEnumField()); + assertEquals(message2.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); } public void testUnknownEnumValuesInReflectionApi() throws Exception { @@ -991,7 +993,7 @@ public class MapTest extends TestCase { // Verify that enum values have been successfully updated. TestMap message = builder.build(); - for (Map.Entry entry : message.getInt32ToEnumFieldValue().entrySet()) { + for (Map.Entry entry : message.getInt32ToEnumFieldValueMap().entrySet()) { assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue()); } } @@ -1002,18 +1004,18 @@ public class MapTest extends TestCase { TestMap message = builder.build(); assertEquals( - Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32Field().keySet())); + Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32FieldMap().keySet())); } public void testGetMap() { TestMap.Builder builder = TestMap.newBuilder(); setMapValuesUsingAccessors(builder); TestMap message = builder.build(); - assertEquals(message.getStringToInt32Field(), message.getStringToInt32FieldMap()); - assertEquals(message.getInt32ToBytesField(), message.getInt32ToBytesFieldMap()); - assertEquals(message.getInt32ToEnumField(), message.getInt32ToEnumFieldMap()); - assertEquals(message.getInt32ToEnumFieldValue(), message.getInt32ToEnumFieldValueMap()); - assertEquals(message.getInt32ToMessageField(), message.getInt32ToMessageFieldMap()); + assertEquals(message.getStringToInt32FieldMap(), message.getStringToInt32FieldMap()); + assertEquals(message.getInt32ToBytesFieldMap(), message.getInt32ToBytesFieldMap()); + assertEquals(message.getInt32ToEnumFieldMap(), message.getInt32ToEnumFieldMap()); + assertEquals(message.getInt32ToEnumFieldValueMap(), message.getInt32ToEnumFieldValueMap()); + assertEquals(message.getInt32ToMessageFieldMap(), message.getInt32ToMessageFieldMap()); } public void testContains() { diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java index e229facace..915dddf392 100644 --- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java @@ -30,6 +30,7 @@ package com.google.protobuf; +import static com.google.common.truth.Truth.assertThat; import static com.google.protobuf.TestUtil.TEST_REQUIRED_INITIALIZED; import static com.google.protobuf.TestUtil.TEST_REQUIRED_UNINITIALIZED; @@ -866,6 +867,12 @@ public class TextFormatTest extends TestCase { assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\341\\210\\264")); assertEquals("\u1234", TextFormat.unescapeText("\\xe1\\x88\\xb4")); assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\xe1\\x88\\xb4")); + assertEquals("\u1234", TextFormat.unescapeText("\\u1234")); + assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\u1234")); + assertEquals(bytes(0xe1, 0x88, 0xb4), TextFormat.unescapeBytes("\\U00001234")); + assertEquals( + new String(new int[] {0x10437}, 0, 1), TextFormat.unescapeText("\\xf0\\x90\\x90\\xb7")); + assertEquals(bytes(0xf0, 0x90, 0x90, 0xb7), TextFormat.unescapeBytes("\\U00010437")); // Handling of strings with unescaped Unicode characters > 255. final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c"; @@ -893,6 +900,87 @@ public class TextFormatTest extends TestCase { } catch (TextFormat.InvalidEscapeSequenceException e) { // success } + + try { + TextFormat.unescapeText("\\u"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' with too few hex chars"); + } + + try { + TextFormat.unescapeText("\\ud800"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\ud800\\u1234"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\udc00"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\ud801\\udc37"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\u' refers to a surrogate"); + } + + try { + TextFormat.unescapeText("\\U1234"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars"); + } + + try { + TextFormat.unescapeText("\\U1234no more hex"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U' with too few hex chars"); + } + + try { + TextFormat.unescapeText("\\U00110000"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U00110000' is not a valid code point value"); + } + + try { + TextFormat.unescapeText("\\U0000d801\\U00000dc37"); + fail("Should have thrown an exception."); + } catch (TextFormat.InvalidEscapeSequenceException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo("Invalid escape sequence: '\\U0000d801' refers to a surrogate code unit"); + } } public void testParseInteger() throws Exception { diff --git a/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java index 57e933f3a4..a17dda5c1f 100644 --- a/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java +++ b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java @@ -174,8 +174,9 @@ public final class Proto2MessageLiteInfoFactory implements MessageInfoFactory { "fieldRequiredSint6487_", "fieldRequiredGroup88_", }; - // To update this after a proto change, run protoc on proto2_message_lite.proto and copy over - // the content of the generated buildMessageInfo() method here. + // To update this after a proto change, run blaze build on proto2_message_lite.proto and copy + // over the String info from the proto2_message_lite_proto-lite-src.jar file in the + // blaze-genfiles directory. java.lang.String info = "\u0001U\u0001\u0002\u0001XU\u0000 \u0015\u0001\u1000\u0000\u0002\u1001\u0001\u0003" + "\u1002\u0002\u0004\u1003\u0003\u0005\u1004\u0004\u0006\u1005\u0005\u0007\u1006\u0006\b\u1007\u0007" diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java index 4092b30683..352376e015 100644 --- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java +++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java @@ -137,11 +137,19 @@ final class FieldMaskTree { } /** - * Remove {@code path} from the tree. + * Removes {@code path} from the tree. * - *

When removing a field path from the tree, all sub-paths will be removed. That is, after - * removing "foo.bar" from the tree, "foo.bar.baz" will be removed. Likewise, if the field path to - * remove is a non-exist sub-path, nothing will be changed. + *

    + * When removing a field path from the tree: + *
  • All sub-paths will be removed. That is, after removing "foo.bar" from the tree, + * "foo.bar.baz" will be removed. + *
  • If all children of a node has been removed, the node itself will be removed as well. + * That is, if "foo" only has one child "bar" and "foo.bar" only has one child "baz", + * removing "foo.bar.barz" would remove both "foo" and "foo.bar". + * If "foo" has both "bar" and "qux" as children, removing "foo.bar" would leave the path + * "foo.qux" intact. + *
  • If the field path to remove is a non-exist sub-path, nothing will be changed. + *
*/ @CanIgnoreReturnValue FieldMaskTree removeFieldPath(String path) { @@ -149,23 +157,35 @@ final class FieldMaskTree { if (parts.isEmpty()) { return this; } - Node node = root; - for (int i = 0; i < parts.size(); i++) { - String key = parts.get(i); - if (!node.children.containsKey(key)) { - // Path does not exist. - return this; - } - if (i == parts.size() - 1) { - // Remove path. - node.children.remove(key); - return this; - } - node = node.children.get(key); - } + removeFieldPath(root, parts, 0); return this; } + /** + * Removes {@code parts} from {@code node} recursively. + * + * @return a boolean value indicating whether current {@code node} should be removed. + */ + @CanIgnoreReturnValue + private static boolean removeFieldPath(Node node, List parts, int index) { + String key = parts.get(index); + + // Base case 1: path not match. + if (!node.children.containsKey(key)) { + return false; + } + // Base case 2: last element in parts. + if (index == parts.size() - 1) { + node.children.remove(key); + return node.children.isEmpty(); + } + // Recursive remove sub-path. + if (removeFieldPath(node.children.get(key), parts, index + 1)) { + node.children.remove(key); + } + return node.children.isEmpty(); + } + /** Removes all field paths in {@code mask} from this tree. */ @CanIgnoreReturnValue FieldMaskTree removeFromFieldMask(FieldMask mask) { @@ -187,10 +207,8 @@ final class FieldMaskTree { return FieldMask.newBuilder().addAllPaths(paths).build(); } - /** - * Gathers all field paths in a sub-tree. - */ - private void getFieldPaths(Node node, String path, List paths) { + /** Gathers all field paths in a sub-tree. */ + private static void getFieldPaths(Node node, String path, List paths) { if (node.children.isEmpty()) { paths.add(path); return; @@ -247,10 +265,8 @@ final class FieldMaskTree { merge(root, "", source, destination, options); } - /** - * Merges all fields specified by a sub-tree from {@code source} to {@code destination}. - */ - private void merge( + /** Merges all fields specified by a sub-tree from {@code source} to {@code destination}. */ + private static void merge( Node node, String path, Message source, diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java index 0c2f90c91e..c32d10a263 100644 --- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java +++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java @@ -276,7 +276,13 @@ public final class FieldMaskUtil { return maskTree.toFieldMask(); } - /** Subtracts {@code secondMask} and {@code otherMasks} from {@code firstMask}. */ + /** + * Subtracts {@code secondMask} and {@code otherMasks} from {@code firstMask}. + * + *

This method disregards proto structure. That is, if {@code firstMask} is "foo" and {@code + * secondMask} is "foo.bar", the response will always be "foo" without considering the internal + * proto structure of message "foo". + */ public static FieldMask subtract( FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) { FieldMaskTree maskTree = new FieldMaskTree(firstMask).removeFromFieldMask(secondMask); diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java index cc3f5f658f..4f2fe3fcfa 100644 --- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java +++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java @@ -525,7 +525,6 @@ public class JsonFormat { return types.get(name); } - /* @Nullable */ Descriptor getDescriptorForTypeUrl(String typeUrl) throws InvalidProtocolBufferException { return find(getTypeName(typeUrl)); } diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java index 7ec37d097b..c8297226f7 100644 --- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java @@ -77,25 +77,37 @@ public class FieldMaskTreeTest extends TestCase { public void testRemoveFieldPath() throws Exception { String initialTreeString = "bar.baz,bar.quz.bar,foo"; - FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); + FieldMaskTree tree; + // Empty path. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); tree.removeFieldPath(""); assertEquals(initialTreeString, tree.toString()); + // Non-exist sub-path of an existing leaf. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); tree.removeFieldPath("foo.bar"); assertEquals(initialTreeString, tree.toString()); + // Non-exist path. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); tree.removeFieldPath("bar.foo"); assertEquals(initialTreeString, tree.toString()); - // Match an existing leaf node. + + // Match an existing leaf node -> remove leaf node. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); tree.removeFieldPath("foo"); assertEquals("bar.baz,bar.quz.bar", tree.toString()); - // Match sub-path of an existing leaf node. + + // Match sub-path of an existing leaf node -> recursive removal. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); tree.removeFieldPath("bar.quz.bar"); - assertEquals("bar.baz,bar.quz", tree.toString()); - // Match a non-leaf node. + assertEquals("bar.baz,foo", tree.toString()); + + // Match a non-leaf node -> remove all children. + tree = new FieldMaskTree(FieldMaskUtil.fromString(initialTreeString)); tree.removeFieldPath("bar"); - assertThat(tree.toString()).isEmpty(); + assertEquals("foo", tree.toString()); } public void testRemoveFromFieldMask() throws Exception { diff --git a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java index 796020eaf2..28e43a7bf7 100644 --- a/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java @@ -239,7 +239,7 @@ public class FieldMaskUtilTest extends TestCase { FieldMask mask3 = FieldMaskUtil.fromString("bar.quz"); FieldMask mask4 = FieldMaskUtil.fromString("foo,bar.baz"); FieldMask result = FieldMaskUtil.subtract(mask1, mask2, mask3, mask4); - assertEquals("bar", FieldMaskUtil.toString(result)); + assertThat(FieldMaskUtil.toString(result)).isEmpty(); } public void testIntersection() throws Exception { diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java index f9358e5221..46d3cc4c35 100644 --- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java +++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java @@ -722,8 +722,8 @@ public class JsonFormatTest extends TestCase { mergeFromJson( "{\n" + " int32ToInt32Map: {1: 2},\n" + " stringToInt32Map: {hello: 3}\n" + "}", builder); TestMap message = builder.build(); - assertEquals(2, message.getInt32ToInt32Map().get(1).intValue()); - assertEquals(3, message.getStringToInt32Map().get("hello").intValue()); + assertEquals(2, message.getInt32ToInt32MapMap().get(1).intValue()); + assertEquals(3, message.getStringToInt32MapMap().get("hello").intValue()); } public void testWrappers() throws Exception { diff --git a/js/binary/constants.js b/js/binary/constants.js index f8b13a8b9e..d2e62e5b0f 100644 --- a/js/binary/constants.js +++ b/js/binary/constants.js @@ -31,6 +31,7 @@ /** * @fileoverview This file contains constants and typedefs used by * jspb.BinaryReader and BinaryWriter. + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * * @author aappleby@google.com (Austin Appleby) */ diff --git a/js/binary/decoder.js b/js/binary/decoder.js index 257c283f09..fb40ec99e3 100644 --- a/js/binary/decoder.js +++ b/js/binary/decoder.js @@ -40,6 +40,7 @@ * intact, you _must_ read them using one of the Hash64 methods, which return * an 8-character string. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ diff --git a/js/binary/reader.js b/js/binary/reader.js index e5f453d5a9..31bbfda438 100644 --- a/js/binary/reader.js +++ b/js/binary/reader.js @@ -41,6 +41,7 @@ * using the typed jspb code generator, but if you bypass that you'll need * to keep things in sync by hand. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ diff --git a/js/binary/utils.js b/js/binary/utils.js index 203eec14f2..6cd15e3644 100644 --- a/js/binary/utils.js +++ b/js/binary/utils.js @@ -32,6 +32,7 @@ * @fileoverview This file contains helper code used by jspb.BinaryReader * and BinaryWriter. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ diff --git a/js/binary/writer.js b/js/binary/writer.js index ab9a815056..1e2beee3e9 100644 --- a/js/binary/writer.js +++ b/js/binary/writer.js @@ -52,6 +52,7 @@ * Major caveat 3 - This class uses typed arrays and must not be used on older * browsers that do not support them. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ diff --git a/js/map.js b/js/map.js index 589a2938d5..61f0f3b63f 100644 --- a/js/map.js +++ b/js/map.js @@ -1,3 +1,4 @@ + // Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ @@ -28,6 +29,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/** + * @fileoverview + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed + */ goog.provide('jspb.Map'); goog.require('goog.asserts'); diff --git a/js/message.js b/js/message.js index f190894b26..905329fe44 100644 --- a/js/message.js +++ b/js/message.js @@ -31,6 +31,7 @@ /** * @fileoverview Definition of jspb.Message. * + * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author mwr@google.com (Mark Rawling) */ diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 7b1263fde9..20ae9aee98 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -71,6 +71,8 @@ static NSString *const kGPBDataCoderKey = @"GPBData"; @package GPBUnknownFieldSet *unknownFields_; NSMutableDictionary *extensionMap_; + // Readonly access to autocreatedExtensionMap_ is protected via + // readOnlySemaphore_. NSMutableDictionary *autocreatedExtensionMap_; // If the object was autocreated, we remember the creator so that if we get @@ -79,10 +81,10 @@ static NSString *const kGPBDataCoderKey = @"GPBData"; GPBFieldDescriptor *autocreatorField_; GPBExtensionDescriptor *autocreatorExtension_; - // A lock to provide mutual exclusion from internal data that can be modified - // by *read* operations such as getters (autocreation of message fields and - // message extensions, not setting of values). Used to guarantee thread safety - // for concurrent reads on the message. + // Message can only be mutated from one thread. But some *readonly* operations + // modifify internal state because they autocreate things. The + // autocreatedExtensionMap_ is one such structure. Access during readonly + // operations is protected via this semaphore. // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have // pointed out that they are vulnerable to live locking on iOS in cases of // priority inversion: @@ -583,19 +585,30 @@ static id GetOrCreateArrayIvarWithField(GPBMessage *self, // This is like GPBGetObjectIvarWithField(), but for arrays, it should // only be used to wire the method into the class. static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { - id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!array) { - // Check again after getting the lock. - GPBPrepareReadOnlySemaphore(self); - dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); - array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!array) { - array = CreateArrayForField(field, self); - GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array); - } - dispatch_semaphore_signal(self->readOnlySemaphore_); + uint8_t *storage = (uint8_t *)self->messageStorage_; + _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; + id array = atomic_load(typePtr); + if (array) { + return array; } - return array; + + id expected = nil; + id autocreated = CreateArrayForField(field, self); + if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { + // Value was set, return it. + return autocreated; + } + + // Some other thread set it, release the one created and return what got set. + if (GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedArray *autoArray = autocreated; + autoArray->_autocreator = nil; + } else { + GPBInt32Array *gpbArray = autocreated; + gpbArray->_autocreator = nil; + } + [autocreated release]; + return expected; } static id GetOrCreateMapIvarWithField(GPBMessage *self, @@ -613,19 +626,31 @@ static id GetOrCreateMapIvarWithField(GPBMessage *self, // This is like GPBGetObjectIvarWithField(), but for maps, it should // only be used to wire the method into the class. static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { - id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!dict) { - // Check again after getting the lock. - GPBPrepareReadOnlySemaphore(self); - dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); - dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!dict) { - dict = CreateMapForField(field, self); - GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); - } - dispatch_semaphore_signal(self->readOnlySemaphore_); + uint8_t *storage = (uint8_t *)self->messageStorage_; + _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; + id dict = atomic_load(typePtr); + if (dict) { + return dict; } - return dict; + + id expected = nil; + id autocreated = CreateMapForField(field, self); + if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { + // Value was set, return it. + return autocreated; + } + + // Some other thread set it, release the one created and return what got set. + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { + GPBAutocreatedDictionary *autoDict = autocreated; + autoDict->_autocreator = nil; + } else { + GPBInt32Int32Dictionary *gpbDict = autocreated; + gpbDict->_autocreator = nil; + } + [autocreated release]; + return expected; } #endif // !defined(__clang_analyzer__) @@ -3337,30 +3362,34 @@ id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); - if (GPBGetHasIvarField(self, field)) { - uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; - return *typePtr; - } - // Not set... - - // Non messages (string/data), get their default. if (!GPBFieldDataTypeIsMessage(field)) { + if (GPBGetHasIvarField(self, field)) { + uint8_t *storage = (uint8_t *)self->messageStorage_; + id *typePtr = (id *)&storage[field->description_->offset]; + return *typePtr; + } + // Not set...non messages (string/data), get their default. return field.defaultValue.valueMessage; } - GPBPrepareReadOnlySemaphore(self); - dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); - GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (!result) { - // For non repeated messages, create the object, set it and return it. - // This object will not initially be visible via GPBGetHasIvar, so - // we save its creator so it can become visible if it's mutated later. - result = GPBCreateMessageWithAutocreator(field.msgClass, self, field); - GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result); - } - dispatch_semaphore_signal(self->readOnlySemaphore_); - return result; + uint8_t *storage = (uint8_t *)self->messageStorage_; + _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; + id msg = atomic_load(typePtr); + if (msg) { + return msg; + } + + id expected = nil; + id autocreated = GPBCreateMessageWithAutocreator(field.msgClass, self, field); + if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { + // Value was set, return it. + return autocreated; + } + + // Some other thread set it, release the one created and return what got set. + GPBClearMessageAutocreator(autocreated); + [autocreated release]; + return expected; } #pragma clang diagnostic pop diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index e13210210d..08dd358225 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -504,15 +504,6 @@ static void GPBMaybeClearOneofPrivate(GPBMessage *self, // Object types are handled slightly differently, they need to be released // and retained. -void GPBSetAutocreatedRetainedObjectIvarWithField( - GPBMessage *self, GPBFieldDescriptor *field, - id __attribute__((ns_consumed)) value) { - uint8_t *storage = (uint8_t *)self->messageStorage_; - id *typePtr = (id *)&storage[field->description_->offset]; - NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once."); - *typePtr = value; -} - void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index a620288267..3d3d7349ec 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -289,10 +289,6 @@ void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, GPBFieldDescriptor *field); -void GPBSetAutocreatedRetainedObjectIvarWithField( - GPBMessage *self, GPBFieldDescriptor *field, - id __attribute__((ns_consumed)) value); - // Clears and releases the autocreated message ivar, if it's autocreated. If // it's not set as autocreated, this method does nothing. void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py index e8448e88a6..7592be4eed 100644 --- a/python/google/protobuf/internal/api_implementation.py +++ b/python/google/protobuf/internal/api_implementation.py @@ -60,11 +60,16 @@ if _api_version < 0: # Still unspecified? raise ImportError('_use_fast_cpp_protos import succeeded but was None') del _use_fast_cpp_protos _api_version = 2 + # Can not import both use_fast_cpp_protos and use_pure_python. + from google.protobuf import use_pure_python + raise RuntimeError( + 'Conflict depend on both use_fast_cpp_protos and use_pure_python') except ImportError: try: # pylint: disable=g-import-not-at-top - from google.protobuf.internal import use_pure_python + from google.protobuf import use_pure_python del use_pure_python # Avoids a pylint error and namespace pollution. + _api_version = 0 except ImportError: # TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default; # it can cause data loss if you have any Python-only extensions to any diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py index ecd28eefb1..c35b00d9fb 100644 --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -629,7 +629,8 @@ class MessageMap(MutableMapping): return repr(self._values) def MergeFrom(self, other): - for key in other: + # pylint: disable=protected-access + for key in other._values: # According to documentation: "When parsing from the wire or when merging, # if there are duplicate map keys the last key seen is used". if key in self: diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index a4d62a85b1..feff228fb6 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -2107,6 +2107,11 @@ class Proto3Test(unittest.TestCase): self.assertEqual(msg.map_int32_foreign_message[222].d, 20) self.assertNotEqual(msg.map_int32_foreign_message[222].c, 123) + # Merge a dict to map field is not accepted + with self.assertRaises(AttributeError): + m1.map_int32_all_types.MergeFrom( + {1: unittest_proto3_arena_pb2.TestAllTypes()}) + def testMergeFromBadType(self): msg = map_unittest_pb2.TestMap() with self.assertRaisesRegexp( diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc index 86b8720240..a0ee16fe86 100644 --- a/python/google/protobuf/pyext/map_container.cc +++ b/python/google/protobuf/pyext/map_container.cc @@ -339,6 +339,11 @@ PyObject* GetEntryClass(PyObject* _self) { PyObject* MapReflectionFriend::MergeFrom(PyObject* _self, PyObject* arg) { MapContainer* self = GetMap(_self); + if (!PyObject_TypeCheck(arg, ScalarMapContainer_Type) && + !PyObject_TypeCheck(arg, MessageMapContainer_Type)) { + PyErr_SetString(PyExc_AttributeError, "Not a map field"); + return nullptr; + } MapContainer* other_map = GetMap(arg); Message* message = self->GetMutableMessage(); const Message* other_message = other_map->parent->message; diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index b7d73859fa..0301e9634d 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -809,7 +809,7 @@ bool CheckAndSetString( return false; } - string value_string(value, value_len); + std::string value_string(value, value_len); if (append) { reflection->AddString(message, descriptor, std::move(value_string)); } else if (index < 0) { diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index 2a9a866420..9ebe8b46b1 100644 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -882,8 +882,11 @@ class _Parser(object): raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (expanded_any_end_token,)) self._MergeField(tokenizer, expanded_any_sub_message) + deterministic = False + message.Pack(expanded_any_sub_message, - type_url_prefix=type_url_prefix) + type_url_prefix=type_url_prefix, + deterministic=deterministic) return if tokenizer.TryConsume('['): diff --git a/src/Makefile.am b/src/Makefile.am index b8b1479fe9..855dd8908d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -68,7 +68,6 @@ nobase_include_HEADERS = \ google/protobuf/stubs/bytestream.h \ google/protobuf/stubs/casts.h \ google/protobuf/stubs/common.h \ - google/protobuf/stubs/fastmem.h \ google/protobuf/stubs/hash.h \ google/protobuf/stubs/logging.h \ google/protobuf/stubs/macros.h \ @@ -104,7 +103,6 @@ nobase_include_HEADERS = \ google/protobuf/generated_message_util.h \ google/protobuf/has_bits.h \ google/protobuf/implicit_weak_message.h \ - google/protobuf/inlined_string_field.h \ google/protobuf/io/io_win32.h \ google/protobuf/map_entry.h \ google/protobuf/map_entry_lite.h \ @@ -202,6 +200,7 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/stubs/time.h \ google/protobuf/any_lite.cc \ google/protobuf/arena.cc \ + google/protobuf/arenastring.cc \ google/protobuf/extension_set.cc \ google/protobuf/generated_enum_util.cc \ google/protobuf/generated_message_util.cc \ diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc index ebe9ba7e0a..d22d64d2e3 100644 --- a/src/google/protobuf/any.cc +++ b/src/google/protobuf/any.cc @@ -51,9 +51,8 @@ void AnyMetadata::PackFrom(const Message& message, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyString(), GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), nullptr); - message.SerializeToString(value_->Mutable( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), - nullptr)); + message.SerializeToString( + value_->Mutable(ArenaStringPtr::EmptyDefault{}, nullptr)); } bool AnyMetadata::UnpackTo(Message* message) const { diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h index 16a68ca687..e8f2cacf16 100644 --- a/src/google/protobuf/any.h +++ b/src/google/protobuf/any.h @@ -60,7 +60,8 @@ class PROTOBUF_EXPORT AnyMetadata { typedef ArenaStringPtr ValueType; public: // AnyMetadata does not take ownership of "type_url" and "value". - AnyMetadata(UrlType* type_url, ValueType* value); + constexpr AnyMetadata(UrlType* type_url, ValueType* value) + : type_url_(type_url), value_(value) {} // Packs a message using the default type URL prefix: "type.googleapis.com". // The resulted type URL will be "type.googleapis.com/". diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 802ecfd3be..557b610560 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -112,12 +112,12 @@ Any::Any(const Any& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_type_url().empty()) { - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_type_url(), + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(), GetArena()); } value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_value().empty()) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_value(), + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(), GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.Any) @@ -162,8 +162,8 @@ void Any::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + type_url_.ClearToEmpty(); + value_.ClearToEmpty(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index ec18f3aeb7..7c732564a6 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -272,7 +271,7 @@ class PROTOBUF_EXPORT Any PROTOBUF_FINAL : // string type_url = 1; inline void Any::clear_type_url() { - type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + type_url_.ClearToEmpty(); } inline const std::string& Any::type_url() const { // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url) @@ -291,31 +290,30 @@ inline const std::string& Any::_internal_type_url() const { } inline void Any::_internal_set_type_url(const std::string& value) { - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Any::set_type_url(std::string&& value) { type_url_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url) } inline void Any::set_type_url(const char* value) { GOOGLE_DCHECK(value != nullptr); - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url) } inline void Any::set_type_url(const char* value, size_t size) { - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url) } inline std::string* Any::_internal_mutable_type_url() { - return type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Any::release_type_url() { // @@protoc_insertion_point(field_release:google.protobuf.Any.type_url) @@ -334,7 +332,7 @@ inline void Any::set_allocated_type_url(std::string* type_url) { // bytes value = 2; inline void Any::clear_value() { - value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + value_.ClearToEmpty(); } inline const std::string& Any::value() const { // @@protoc_insertion_point(field_get:google.protobuf.Any.value) @@ -353,31 +351,30 @@ inline const std::string& Any::_internal_value() const { } inline void Any::_internal_set_value(const std::string& value) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Any::set_value(std::string&& value) { value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value) } inline void Any::set_value(const char* value) { GOOGLE_DCHECK(value != nullptr); - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value) } inline void Any::set_value(const void* value, size_t size) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value) } inline std::string* Any::_internal_mutable_value() { - return value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Any::release_value() { // @@protoc_insertion_point(field_release:google.protobuf.Any.value) diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc index 206b01fbd1..ffb2692135 100644 --- a/src/google/protobuf/any_lite.cc +++ b/src/google/protobuf/any_lite.cc @@ -53,16 +53,13 @@ const char kAnyFullTypeName[] = "google.protobuf.Any"; const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/"; -AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value) - : type_url_(type_url), value_(value) {} - void AnyMetadata::InternalPackFrom(const MessageLite& message, StringPiece type_url_prefix, StringPiece type_name) { type_url_->Set(&::google::protobuf::internal::GetEmptyString(), GetTypeUrl(type_name, type_url_prefix), nullptr); - message.SerializeToString(value_->Mutable( - &::google::protobuf::internal::GetEmptyStringAlreadyInited(), nullptr)); + message.SerializeToString( + value_->Mutable(ArenaStringPtr::EmptyDefault{}, nullptr)); } bool AnyMetadata::InternalUnpackTo(StringPiece type_name, diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc index 0d8893f7b8..8aeab7602b 100644 --- a/src/google/protobuf/any_test.cc +++ b/src/google/protobuf/any_test.cc @@ -33,10 +33,18 @@ #include +// Must be included last. +#include + namespace google { namespace protobuf { namespace { +TEST(AnyMetadataTest, ConstInit) { + PROTOBUF_CONSTINIT static internal::AnyMetadata metadata(nullptr, nullptr); + (void)metadata; +} + TEST(AnyTest, TestPackAndUnpack) { protobuf_unittest::TestAny submessage; submessage.set_int32_value(12345); diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index e3fb23da54..267f60f53a 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -204,12 +204,12 @@ Api::Api(const Api& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } version_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_version().empty()) { - version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_version(), + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_version(), GetArena()); } if (from._internal_has_source_context()) { @@ -268,8 +268,8 @@ void Api::Clear() { methods_.Clear(); options_.Clear(); mixins_.Clear(); - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - version_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); + version_.ClearToEmpty(); if (GetArena() == nullptr && source_context_ != nullptr) { delete source_context_; } @@ -614,17 +614,17 @@ Method::Method(const Method& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } request_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_request_type_url().empty()) { - request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_request_type_url(), + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_request_type_url(), GetArena()); } response_type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_response_type_url().empty()) { - response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_response_type_url(), + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_response_type_url(), GetArena()); } ::memcpy(&request_streaming_, &from.request_streaming_, @@ -679,9 +679,9 @@ void Method::Clear() { (void) cached_has_bits; options_.Clear(); - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - request_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - response_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); + request_type_url_.ClearToEmpty(); + response_type_url_.ClearToEmpty(); ::memset(&request_streaming_, 0, static_cast( reinterpret_cast(&syntax_) - reinterpret_cast(&request_streaming_)) + sizeof(syntax_)); @@ -1008,12 +1008,12 @@ Mixin::Mixin(const Mixin& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } root_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_root().empty()) { - root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_root(), + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_root(), GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.Mixin) @@ -1058,8 +1058,8 @@ void Mixin::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - root_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); + root_.ClearToEmpty(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index f37ea8c2f7..b47f1df0f3 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -732,7 +731,7 @@ class PROTOBUF_EXPORT Mixin PROTOBUF_FINAL : // string name = 1; inline void Api::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& Api::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.name) @@ -751,31 +750,30 @@ inline const std::string& Api::_internal_name() const { } inline void Api::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Api::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.name) } inline void Api::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name) } inline void Api::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name) } inline std::string* Api::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Api::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Api.name) @@ -869,7 +867,7 @@ Api::options() const { // string version = 4; inline void Api::clear_version() { - version_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + version_.ClearToEmpty(); } inline const std::string& Api::version() const { // @@protoc_insertion_point(field_get:google.protobuf.Api.version) @@ -888,31 +886,30 @@ inline const std::string& Api::_internal_version() const { } inline void Api::_internal_set_version(const std::string& value) { - version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Api::set_version(std::string&& value) { version_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.version) } inline void Api::set_version(const char* value) { GOOGLE_DCHECK(value != nullptr); - version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version) } inline void Api::set_version(const char* value, size_t size) { - version_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version) } inline std::string* Api::_internal_mutable_version() { - return version_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return version_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Api::release_version() { // @@protoc_insertion_point(field_release:google.protobuf.Api.version) @@ -1071,7 +1068,7 @@ inline void Api::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) { // string name = 1; inline void Method::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& Method::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.name) @@ -1090,31 +1087,30 @@ inline const std::string& Method::_internal_name() const { } inline void Method::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Method::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.name) } inline void Method::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name) } inline void Method::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name) } inline std::string* Method::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Method::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Method.name) @@ -1133,7 +1129,7 @@ inline void Method::set_allocated_name(std::string* name) { // string request_type_url = 2; inline void Method::clear_request_type_url() { - request_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + request_type_url_.ClearToEmpty(); } inline const std::string& Method::request_type_url() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url) @@ -1152,31 +1148,30 @@ inline const std::string& Method::_internal_request_type_url() const { } inline void Method::_internal_set_request_type_url(const std::string& value) { - request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Method::set_request_type_url(std::string&& value) { request_type_url_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.request_type_url) } inline void Method::set_request_type_url(const char* value) { GOOGLE_DCHECK(value != nullptr); - request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url) } inline void Method::set_request_type_url(const char* value, size_t size) { - request_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url) } inline std::string* Method::_internal_mutable_request_type_url() { - return request_type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return request_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Method::release_request_type_url() { // @@protoc_insertion_point(field_release:google.protobuf.Method.request_type_url) @@ -1215,7 +1210,7 @@ inline void Method::set_request_streaming(bool value) { // string response_type_url = 4; inline void Method::clear_response_type_url() { - response_type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + response_type_url_.ClearToEmpty(); } inline const std::string& Method::response_type_url() const { // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url) @@ -1234,31 +1229,30 @@ inline const std::string& Method::_internal_response_type_url() const { } inline void Method::_internal_set_response_type_url(const std::string& value) { - response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Method::set_response_type_url(std::string&& value) { response_type_url_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.response_type_url) } inline void Method::set_response_type_url(const char* value) { GOOGLE_DCHECK(value != nullptr); - response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url) } inline void Method::set_response_type_url(const char* value, size_t size) { - response_type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url) } inline std::string* Method::_internal_mutable_response_type_url() { - return response_type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return response_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Method::release_response_type_url() { // @@protoc_insertion_point(field_release:google.protobuf.Method.response_type_url) @@ -1357,7 +1351,7 @@ inline void Method::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) { // string name = 1; inline void Mixin::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& Mixin::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name) @@ -1376,31 +1370,30 @@ inline const std::string& Mixin::_internal_name() const { } inline void Mixin::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Mixin::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.name) } inline void Mixin::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name) } inline void Mixin::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name) } inline std::string* Mixin::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Mixin::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Mixin.name) @@ -1419,7 +1412,7 @@ inline void Mixin::set_allocated_name(std::string* name) { // string root = 2; inline void Mixin::clear_root() { - root_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + root_.ClearToEmpty(); } inline const std::string& Mixin::root() const { // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root) @@ -1438,31 +1431,30 @@ inline const std::string& Mixin::_internal_root() const { } inline void Mixin::_internal_set_root(const std::string& value) { - root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Mixin::set_root(std::string&& value) { root_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.root) } inline void Mixin::set_root(const char* value) { GOOGLE_DCHECK(value != nullptr); - root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root) } inline void Mixin::set_root(const char* value, size_t size) { - root_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root) } inline std::string* Mixin::_internal_mutable_root() { - return root_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return root_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Mixin::release_root() { // @@protoc_insertion_point(field_release:google.protobuf.Mixin.root) diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 13e11b51aa..414e0234f7 100644 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -47,10 +47,14 @@ static const size_t kMaxCleanupListElements = 64; // 1kB on 64-bit. namespace google { namespace protobuf { + +PROTOBUF_EXPORT /*static*/ void* (*const ArenaOptions::kDefaultBlockAlloc)( + size_t) = &::operator new; + namespace internal { -std::atomic ArenaImpl::lifecycle_id_generator_; +ArenaImpl::CacheAlignedLifecycleIdGenerator ArenaImpl::lifecycle_id_generator_; #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) ArenaImpl::ThreadCache& ArenaImpl::thread_cache() { static internal::ThreadLocalStorage* thread_cache_ = @@ -59,78 +63,205 @@ ArenaImpl::ThreadCache& ArenaImpl::thread_cache() { } #elif defined(PROTOBUF_USE_DLLS) ArenaImpl::ThreadCache& ArenaImpl::thread_cache() { - static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {-1, NULL}; + static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = { + 0, static_cast(-1), nullptr}; return thread_cache_; } #else -PROTOBUF_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, - NULL}; +PROTOBUF_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = { + 0, static_cast(-1), nullptr}; +#endif + +void ArenaFree(void* object, size_t size) { +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + ::operator delete(object, size); +#else + (void)size; + ::operator delete(object); #endif +} + +ArenaImpl::ArenaImpl(const ArenaOptions& options) { + ArenaMetricsCollector* collector = nullptr; + bool record_allocs = false; + if (options.make_metrics_collector != nullptr) { + collector = (*options.make_metrics_collector)(); + record_allocs = (collector && collector->RecordAllocs()); + } + + // Get memory where we can store non-default options if needed. + // Use supplied initial_block if it is large enough. + size_t min_block_size = kOptionsSize + kBlockHeaderSize + kSerialArenaSize; + char* mem = options.initial_block; + size_t mem_size = options.initial_block_size; + GOOGLE_DCHECK_EQ(reinterpret_cast(mem) & 7, 0); + if (mem == nullptr || mem_size < min_block_size) { + // Supplied initial block is not big enough. + mem_size = std::max(min_block_size, options.start_block_size); + mem = reinterpret_cast((*options.block_alloc)(mem_size)); + } -void ArenaImpl::Init() { - lifecycle_id_ = - lifecycle_id_generator_.fetch_add(1, std::memory_order_relaxed); + // Create the special block. + const bool special = true; + const bool user_owned = (mem == options.initial_block); + auto block = + new (mem) SerialArena::Block(mem_size, nullptr, special, user_owned); + + // Options occupy the beginning of the initial block. + options_ = new (block->Pointer(block->pos())) Options; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(options_, kOptionsSize); +#endif // ADDRESS_SANITIZER + options_->start_block_size = options.start_block_size; + options_->max_block_size = options.max_block_size; + options_->block_alloc = options.block_alloc; + options_->block_dealloc = options.block_dealloc; + options_->metrics_collector = collector; + block->set_pos(block->pos() + kOptionsSize); + + Init(record_allocs); + SetInitialBlock(block); +} + +void ArenaImpl::Init(bool record_allocs) { + ThreadCache& tc = thread_cache(); + auto id = tc.next_lifecycle_id; + constexpr uint64 kInc = ThreadCache::kPerThreadIds * 2; + if (PROTOBUF_PREDICT_FALSE((id & (kInc - 1)) == 0)) { + if (sizeof(lifecycle_id_generator_.id) == 4) { + // 2^32 is dangerous low to guarantee uniqueness. If we start dolling out + // unique id's in ranges of kInc it's unacceptably low. In this case + // we increment by 1. The additional range of kPerThreadIds that are used + // per thread effectively pushes the overflow time from weeks to years + // of continuous running. + id = lifecycle_id_generator_.id.fetch_add(1, std::memory_order_relaxed) * + kInc; + } else { + id = + lifecycle_id_generator_.id.fetch_add(kInc, std::memory_order_relaxed); + } + } + tc.next_lifecycle_id = id + 2; + // We store "record_allocs" in the low bit of lifecycle_id_. + lifecycle_id_ = id | (record_allocs ? 1 : 0); hint_.store(nullptr, std::memory_order_relaxed); threads_.store(nullptr, std::memory_order_relaxed); + space_allocated_.store(0, std::memory_order_relaxed); +} - if (initial_block_) { - // Thread which calls Init() owns the first block. This allows the - // single-threaded case to allocate on the first block without having to - // perform atomic operations. - new (initial_block_) Block(options_.initial_block_size, NULL); - SerialArena* serial = - SerialArena::New(initial_block_, &thread_cache(), this); - serial->set_next(NULL); - threads_.store(serial, std::memory_order_relaxed); - space_allocated_.store(options_.initial_block_size, - std::memory_order_relaxed); - CacheSerialArena(serial); - } else { - space_allocated_.store(0, std::memory_order_relaxed); - } +void ArenaImpl::SetInitialBlock(SerialArena::Block* block) { + // Calling thread owns the first block. This allows the single-threaded case + // to allocate on the first block without having to perform atomic operations. + SerialArena* serial = SerialArena::New(block, &thread_cache(), this); + serial->set_next(NULL); + threads_.store(serial, std::memory_order_relaxed); + space_allocated_.store(block->size(), std::memory_order_relaxed); + CacheSerialArena(serial); } ArenaImpl::~ArenaImpl() { // Have to do this in a first pass, because some of the destructors might // refer to memory in other blocks. CleanupList(); - FreeBlocks(); + + ArenaMetricsCollector* collector = nullptr; + auto deallocator = &ArenaFree; + if (options_) { + collector = options_->metrics_collector; + deallocator = options_->block_dealloc; + } + + PerBlock([deallocator](SerialArena::Block* b) { +#ifdef ADDRESS_SANITIZER + // This memory was provided by the underlying allocator as unpoisoned, so + // return it in an unpoisoned state. + ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size()); +#endif // ADDRESS_SANITIZER + if (!b->user_owned()) { + (*deallocator)(b, b->size()); + } + }); + + if (collector) { + collector->OnDestroy(SpaceAllocated()); + } } uint64 ArenaImpl::Reset() { + if (options_ && options_->metrics_collector) { + options_->metrics_collector->OnReset(SpaceAllocated()); + } + // Have to do this in a first pass, because some of the destructors might // refer to memory in other blocks. CleanupList(); - uint64 space_allocated = FreeBlocks(); - Init(); + // Discard all blocks except the special block (if present). + uint64 space_allocated = 0; + SerialArena::Block* special_block = nullptr; + auto deallocator = (options_ ? options_->block_dealloc : &ArenaFree); + PerBlock( + [&space_allocated, &special_block, deallocator](SerialArena::Block* b) { + space_allocated += b->size(); +#ifdef ADDRESS_SANITIZER + // This memory was provided by the underlying allocator as unpoisoned, + // so return it in an unpoisoned state. + ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size()); +#endif // ADDRESS_SANITIZER + if (!b->special()) { + (*deallocator)(b, b->size()); + } else { + // Prepare special block for reuse. + // Note: if options_ is present, it occupies the beginning of the + // block and therefore pos is advanced past it. + GOOGLE_DCHECK(special_block == nullptr); + special_block = b; + } + }); + + Init(record_allocs()); + if (special_block != nullptr) { + // next() should still be nullptr since we are using a stack discipline, but + // clear it anyway to reduce fragility. + GOOGLE_DCHECK_EQ(special_block->next(), nullptr); + special_block->clear_next(); + special_block->set_pos(kBlockHeaderSize + (options_ ? kOptionsSize : 0)); + SetInitialBlock(special_block); + } return space_allocated; } -ArenaImpl::Block* ArenaImpl::NewBlock(Block* last_block, size_t min_bytes) { +std::pair ArenaImpl::NewBuffer(size_t last_size, + size_t min_bytes) { size_t size; - if (last_block) { + if (last_size != -1) { // Double the current block size, up to a limit. - size = std::min(2 * last_block->size(), options_.max_block_size); + auto max_size = options_ ? options_->max_block_size : kDefaultMaxBlockSize; + size = std::min(2 * last_size, max_size); } else { - size = options_.start_block_size; + size = options_ ? options_->start_block_size : kDefaultStartBlockSize; } // Verify that min_bytes + kBlockHeaderSize won't overflow. GOOGLE_CHECK_LE(min_bytes, std::numeric_limits::max() - kBlockHeaderSize); size = std::max(size, kBlockHeaderSize + min_bytes); - void* mem = options_.block_alloc(size); - Block* b = new (mem) Block(size, last_block); + void* mem = options_ ? (*options_->block_alloc)(size) : ::operator new(size); space_allocated_.fetch_add(size, std::memory_order_relaxed); - return b; + return {mem, size}; } -ArenaImpl::Block::Block(size_t size, Block* next) - : next_(next), pos_(kBlockHeaderSize), size_(size) {} +SerialArena::Block* SerialArena::NewBlock(SerialArena::Block* last_block, + size_t min_bytes, ArenaImpl* arena) { + void* mem; + size_t size; + std::tie(mem, size) = + arena->NewBuffer(last_block ? last_block->size() : -1, min_bytes); + Block* b = new (mem) Block(size, last_block, false, false); + return b; +} PROTOBUF_NOINLINE -void ArenaImpl::SerialArena::AddCleanupFallback(void* elem, - void (*cleanup)(void*)) { +void SerialArena::AddCleanupFallback(void* elem, void (*cleanup)(void*)) { size_t size = cleanup_ ? cleanup_->size * 2 : kMinCleanupListElements; size = std::min(size, kMaxCleanupListElements); size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size)); @@ -182,11 +313,11 @@ void ArenaImpl::AddCleanupFallback(void* elem, void (*cleanup)(void*)) { } PROTOBUF_NOINLINE -void* ArenaImpl::SerialArena::AllocateAlignedFallback(size_t n) { +void* SerialArena::AllocateAlignedFallback(size_t n) { // Sync back to current's pos. head_->set_pos(head_->size() - (limit_ - ptr_)); - head_ = arena_->NewBlock(head_, n); + head_ = NewBlock(head_, n, arena_); ptr_ = head_->Pointer(head_->pos()); limit_ = head_->Pointer(head_->size()); @@ -207,10 +338,14 @@ uint64 ArenaImpl::SpaceUsed() const { for (; serial; serial = serial->next()) { space_used += serial->SpaceUsed(); } + // Remove the overhead of Options structure, if any. + if (options_) { + space_used -= kOptionsSize; + } return space_used; } -uint64 ArenaImpl::SerialArena::SpaceUsed() const { +uint64 SerialArena::SpaceUsed() const { // Get current block's size from ptr_ (since we can't trust head_->pos(). uint64 space_used = ptr_ - head_->Pointer(kBlockHeaderSize); // Get subsequent block size from b->pos(). @@ -218,57 +353,10 @@ uint64 ArenaImpl::SerialArena::SpaceUsed() const { space_used += (b->pos() - kBlockHeaderSize); } // Remove the overhead of the SerialArena itself. - space_used -= kSerialArenaSize; + space_used -= ArenaImpl::kSerialArenaSize; return space_used; } -uint64 ArenaImpl::FreeBlocks() { - uint64 space_allocated = 0; - // By omitting an Acquire barrier we ensure that any user code that doesn't - // properly synchronize Reset() or the destructor will throw a TSAN warning. - SerialArena* serial = threads_.load(std::memory_order_relaxed); - - while (serial) { - // This is inside a block we are freeing, so we need to read it now. - SerialArena* next = serial->next(); - space_allocated += ArenaImpl::SerialArena::Free(serial, initial_block_, - options_.block_dealloc); - // serial is dead now. - serial = next; - } - - return space_allocated; -} - -uint64 ArenaImpl::SerialArena::Free(ArenaImpl::SerialArena* serial, - Block* initial_block, - void (*block_dealloc)(void*, size_t)) { - uint64 space_allocated = 0; - - // We have to be careful in this function, since we will be freeing the Block - // that contains this SerialArena. Be careful about accessing |serial|. - - for (Block* b = serial->head_; b;) { - // This is inside the block we are freeing, so we need to read it now. - Block* next_block = b->next(); - space_allocated += (b->size()); - -#ifdef ADDRESS_SANITIZER - // This memory was provided by the underlying allocator as unpoisoned, so - // return it in an unpoisoned state. - ASAN_UNPOISON_MEMORY_REGION(b->Pointer(0), b->size()); -#endif // ADDRESS_SANITIZER - - if (b != initial_block) { - block_dealloc(b, b->size()); - } - - b = next_block; - } - - return space_allocated; -} - void ArenaImpl::CleanupList() { // By omitting an Acquire barrier we ensure that any user code that doesn't // properly synchronize Reset() or the destructor will throw a TSAN warning. @@ -279,13 +367,13 @@ void ArenaImpl::CleanupList() { } } -void ArenaImpl::SerialArena::CleanupList() { +void SerialArena::CleanupList() { if (cleanup_ != NULL) { CleanupListFallback(); } } -void ArenaImpl::SerialArena::CleanupListFallback() { +void SerialArena::CleanupListFallback() { // The first chunk might be only partially full, so calculate its size // from cleanup_ptr_. Subsequent chunks are always full, so use list->size. size_t n = cleanup_ptr_ - &cleanup_->nodes[0]; @@ -305,13 +393,11 @@ void ArenaImpl::SerialArena::CleanupListFallback() { } } -ArenaImpl::SerialArena* ArenaImpl::SerialArena::New(Block* b, void* owner, - ArenaImpl* arena) { - GOOGLE_DCHECK_EQ(b->pos(), kBlockHeaderSize); // Should be a fresh block - GOOGLE_DCHECK_LE(kBlockHeaderSize + kSerialArenaSize, b->size()); - SerialArena* serial = - reinterpret_cast(b->Pointer(kBlockHeaderSize)); - b->set_pos(kBlockHeaderSize + kSerialArenaSize); +SerialArena* SerialArena::New(Block* b, void* owner, ArenaImpl* arena) { + auto pos = b->pos(); + GOOGLE_DCHECK_LE(pos + ArenaImpl::kSerialArenaSize, b->size()); + SerialArena* serial = reinterpret_cast(b->Pointer(pos)); + b->set_pos(pos + ArenaImpl::kSerialArenaSize); serial->arena_ = arena; serial->owner_ = owner; serial->head_ = b; @@ -324,7 +410,7 @@ ArenaImpl::SerialArena* ArenaImpl::SerialArena::New(Block* b, void* owner, } PROTOBUF_NOINLINE -ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) { +SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) { // Look for this SerialArena in our linked list. SerialArena* serial = threads_.load(std::memory_order_acquire); for (; serial; serial = serial->next()) { @@ -336,7 +422,7 @@ ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) { if (!serial) { // This thread doesn't have any SerialArena, which also means it doesn't // have any blocks yet. So we'll allocate its first block now. - Block* b = NewBlock(NULL, kSerialArenaSize); + SerialArena::Block* b = SerialArena::NewBlock(NULL, kSerialArenaSize, this); serial = SerialArena::New(b, me, this); SerialArena* head = threads_.load(std::memory_order_relaxed); @@ -350,6 +436,8 @@ ArenaImpl::SerialArena* ArenaImpl::GetSerialArenaFallback(void* me) { return serial; } +ArenaMetricsCollector::~ArenaMetricsCollector() {} + } // namespace internal PROTOBUF_FUNC_ALIGN(32) @@ -357,25 +445,5 @@ void* Arena::AllocateAlignedNoHook(size_t n) { return impl_.AllocateAligned(n); } -void Arena::CallDestructorHooks() { - uint64 space_allocated = impl_.SpaceAllocated(); - // Call the reset hook - if (on_arena_reset_ != NULL) { - on_arena_reset_(this, hooks_cookie_, space_allocated); - } - - // Call the destruction hook - if (on_arena_destruction_ != NULL) { - on_arena_destruction_(this, hooks_cookie_, space_allocated); - } -} - -void Arena::OnArenaAllocation(const std::type_info* allocated_type, - size_t n) const { - if (on_arena_allocation_ != NULL) { - on_arena_allocation_(allocated_type, n, hooks_cookie_); - } -} - } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 038553c83f..f28bebfd34 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -102,15 +102,6 @@ template void arena_delete_object(void* object) { delete reinterpret_cast(object); } -inline void arena_free(void* object, size_t size) { -#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) - ::operator delete(object, size); -#else - (void)size; - ::operator delete(object); -#endif -} - } // namespace internal // ArenaOptions provides optional additional parameters to arena construction @@ -151,44 +142,30 @@ struct ArenaOptions { max_block_size(kDefaultMaxBlockSize), initial_block(NULL), initial_block_size(0), - block_alloc(&::operator new), - block_dealloc(&internal::arena_free), - on_arena_init(NULL), - on_arena_reset(NULL), - on_arena_destruction(NULL), - on_arena_allocation(NULL) {} + block_alloc(kDefaultBlockAlloc), + block_dealloc(&internal::ArenaFree), + make_metrics_collector(nullptr) {} + + PROTOBUF_EXPORT static void* (*const kDefaultBlockAlloc)(size_t); private: - // Hooks for adding external functionality such as user-specific metrics - // collection, specific debugging abilities, etc. - // Init hook (if set) will always be called at Arena init time. Init hook may - // return a pointer to a cookie to be stored in the arena. Reset and - // destruction hooks will then be called with the same cookie pointer. This - // allows us to save an external object per arena instance and use it on the - // other hooks (Note: If init hook returns NULL, the other hooks will NOT be - // called on this arena instance). - // on_arena_reset and on_arena_destruction also receive the space used in the - // arena just before the reset. - void* (*on_arena_init)(Arena* arena); - void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used); - void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used); - - // type_info is promised to be static - its lifetime extends to - // match program's lifetime (It is given by typeid operator). - // Note: typeid(void) will be passed as allocated_type every time we - // intentionally want to avoid monitoring an allocation. (i.e. internal - // allocations for managing the arena) - void (*on_arena_allocation)(const std::type_info* allocated_type, - uint64 alloc_size, void* cookie); + // If make_metrics_collector is not nullptr, it will be called at Arena init + // time. It may return a pointer to a collector instance that will be notified + // of interesting events related to the arena. + internal::ArenaMetricsCollector* (*make_metrics_collector)(); // Constants define default starting block size and max block size for // arena allocator behavior -- see descriptions above. - static const size_t kDefaultStartBlockSize = 256; - static const size_t kDefaultMaxBlockSize = 8192; + static const size_t kDefaultStartBlockSize = + internal::ArenaImpl::kDefaultStartBlockSize; + static const size_t kDefaultMaxBlockSize = + internal::ArenaImpl::kDefaultMaxBlockSize; friend void arena_metrics::EnableArenaMetrics(ArenaOptions*); + friend class Arena; friend class ArenaOptionsTestFriend; + friend class internal::ArenaImpl; }; // Support for non-RTTI environments. (The metrics hooks API uses type @@ -246,11 +223,20 @@ struct ArenaOptions { // should not rely on this protocol. class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { public: - // Arena constructor taking custom options. See ArenaOptions below for + // Default constructor with sensible default options, tuned for average + // use-cases. + inline Arena() : impl_() {} + + // Construct an arena with default options, except for the supplied + // initial block. It is more efficient to use this constructor + // instead of passing ArenaOptions if the only configuration needed + // by the caller is supplying an initial block. + inline Arena(char* initial_block, size_t initial_block_size) + : impl_(initial_block, initial_block_size) {} + + // Arena constructor taking custom options. See ArenaOptions above for // descriptions of the options available. - explicit Arena(const ArenaOptions& options) : impl_(options) { - Init(options); - } + explicit Arena(const ArenaOptions& options) : impl_(options) {} // Block overhead. Use this as a guide for how much to over-allocate the // initial block if you want an allocation of size N to fit inside it. @@ -261,27 +247,10 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { static const size_t kBlockOverhead = internal::ArenaImpl::kBlockHeaderSize + internal::ArenaImpl::kSerialArenaSize; - // Default constructor with sensible default options, tuned for average - // use-cases. - Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); } - - ~Arena() { - if (hooks_cookie_) { - CallDestructorHooks(); - } - } + inline ~Arena() {} - void Init(const ArenaOptions& options) { - on_arena_allocation_ = options.on_arena_allocation; - on_arena_reset_ = options.on_arena_reset; - on_arena_destruction_ = options.on_arena_destruction; - // Call the initialization hook - if (options.on_arena_init != NULL) { - hooks_cookie_ = options.on_arena_init(this); - } else { - hooks_cookie_ = NULL; - } - } + // TODO(protobuf-team): Fix callers to use constructor and delete this method. + void Init(const ArenaOptions&) {} // API to create proto2 message objects on the arena. If the arena passed in // is NULL, then a heap allocated object is returned. Type T must be a message @@ -362,13 +331,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // 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. - PROTOBUF_NOINLINE uint64 Reset() { - // Call the reset hook - if (on_arena_reset_ != NULL) { - on_arena_reset_(this, hooks_cookie_, impl_.SpaceAllocated()); - } - return impl_.Reset(); - } + uint64 Reset() { return impl_.Reset(); } // Adds |object| to a list of heap-allocated objects to be freed with |delete| // when the arena is destroyed or reset. @@ -515,28 +478,31 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { } } - void CallDestructorHooks(); - void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const; inline void AllocHook(const std::type_info* allocated_type, size_t n) const { - if (PROTOBUF_PREDICT_FALSE(hooks_cookie_ != NULL)) { - OnArenaAllocation(allocated_type, n); - } + impl_.RecordAlloc(allocated_type, n); } - // Allocate and also optionally call on_arena_allocation callback with the - // allocated type info when the hooks are in place in ArenaOptions and - // the cookie is not null. + // Allocate and also optionally call collector with the allocated type info + // when allocation recording is enabled. template PROTOBUF_ALWAYS_INLINE void* AllocateInternal(bool skip_explicit_ownership) { - static_assert(alignof(T) <= 8, "T is overaligned, see b/151247138"); const size_t n = internal::AlignUpTo8(sizeof(T)); - AllocHook(RTTI_TYPE_ID(T), n); // Monitor allocation if needed. + impl_.RecordAlloc(RTTI_TYPE_ID(T), n); if (skip_explicit_ownership) { - return AllocateAlignedNoHook(n); + return AllocateAlignedTo(sizeof(T)); } else { - return impl_.AllocateAlignedAndAddCleanup( - n, &internal::arena_destruct_object); + if (alignof(T) <= 8) { + return impl_.AllocateAlignedAndAddCleanup( + n, &internal::arena_destruct_object); + } else { + auto ptr = + reinterpret_cast(impl_.AllocateAlignedAndAddCleanup( + sizeof(T) + alignof(T) - 8, + &internal::arena_destruct_object)); + return reinterpret_cast((ptr + alignof(T) - 8) & + (~alignof(T) + 1)); + } } } @@ -591,10 +557,12 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { PROTOBUF_ALWAYS_INLINE T* CreateInternalRawArray(size_t num_elements) { GOOGLE_CHECK_LE(num_elements, std::numeric_limits::max() / sizeof(T)) << "Requested size is too large to fit into size_t."; + // We count on compiler to realize that if sizeof(T) is a multiple of + // 8 AlignUpTo can be elided. const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements); // Monitor allocation if needed. - AllocHook(RTTI_TYPE_ID(T), n); - return static_cast(AllocateAlignedNoHook(n)); + impl_.RecordAlloc(RTTI_TYPE_ID(T), n); + return static_cast(AllocateAlignedTo(n)); } template @@ -687,7 +655,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // For friends of arena. void* AllocateAligned(size_t n) { - AllocHook(NULL, n); return AllocateAlignedNoHook(internal::AlignUpTo8(n)); } template @@ -698,7 +665,7 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { // TODO(b/151247138): if the pointer would have been aligned already, // this is wasting space. We should pass the alignment down. uintptr_t ptr = reinterpret_cast(AllocateAligned(n + Align - 8)); - ptr = (ptr + Align - 1) & -Align; + ptr = (ptr + Align - 1) & (~Align + 1); return reinterpret_cast(ptr); } @@ -706,15 +673,6 @@ class PROTOBUF_EXPORT PROTOBUF_ALIGNAS(8) Arena final { internal::ArenaImpl impl_; - void (*on_arena_allocation_)(const std::type_info* allocated_type, - uint64 alloc_size, void* cookie); - void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used); - void (*on_arena_destruction_)(Arena* arena, void* cookie, uint64 space_used); - - // The arena may save a cookie it receives from the external on_init hook - // and then use it when calling the on_reset and on_destruction hooks. - void* hooks_cookie_; - template friend class internal::GenericTypeHandler; friend struct internal::ArenaStringPtr; // For AllocateAligned. diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h index 2f8d343fd3..1377268621 100644 --- a/src/google/protobuf/arena_impl.h +++ b/src/google/protobuf/arena_impl.h @@ -48,6 +48,9 @@ namespace google { namespace protobuf { + +struct ArenaOptions; + namespace internal { inline size_t AlignUpTo8(size_t n) { @@ -55,7 +58,195 @@ inline size_t AlignUpTo8(size_t n) { return (n + 7) & static_cast(-8); } -using LifecycleId = int64_t; +using LifecycleIdAtomic = uint64_t; + +void PROTOBUF_EXPORT ArenaFree(void* object, size_t size); + +// MetricsCollector collects stats for a particular arena. +class PROTOBUF_EXPORT ArenaMetricsCollector { + public: + virtual ~ArenaMetricsCollector(); + + // Invoked when the arena is about to be destroyed. This method will + // typically finalize any metric collection and delete the collector. + // space_allocated is the space used by the arena. + virtual void OnDestroy(uint64 space_allocated) = 0; + + // OnReset() is called when the associated arena is reset. + // space_allocated is the space used by the arena just before the reset. + virtual void OnReset(uint64 space_allocated) = 0; + + // Does OnAlloc() need to be called? If false, metric collection overhead + // will be reduced since we will not do extra work per allocation. + virtual bool RecordAllocs() = 0; + + // OnAlloc is called when an allocation happens. + // type_info is promised to be static - its lifetime extends to + // match program's lifetime (It is given by typeid operator). + // Note: typeid(void) will be passed as allocated_type every time we + // intentionally want to avoid monitoring an allocation. (i.e. internal + // allocations for managing the arena) + virtual void OnAlloc(const std::type_info* allocated_type, + uint64 alloc_size) = 0; +}; + +class ArenaImpl; + +// A thread-unsafe Arena that can only be used within its owning thread. +class PROTOBUF_EXPORT SerialArena { + public: + // Blocks are variable length malloc-ed objects. The following structure + // describes the common header for all blocks. + class PROTOBUF_EXPORT Block { + public: + Block(size_t size, Block* next, bool special, bool user_owned) + : next_and_bits_(reinterpret_cast(next) | (special ? 1 : 0) | + (user_owned ? 2 : 0)), + pos_(kBlockHeaderSize), + size_(size) { + GOOGLE_DCHECK_EQ(reinterpret_cast(next) & 3, 0u); + } + + char* Pointer(size_t n) { + GOOGLE_DCHECK(n <= size_); + return reinterpret_cast(this) + n; + } + + // One of the blocks may be special. This is either a user-supplied + // initial block, or a block we created at startup to hold Options info. + // A special block is not deleted by Reset. + bool special() const { return (next_and_bits_ & 1) != 0; } + + // Whether or not this current block is owned by the user. + // Only special blocks can be user_owned. + bool user_owned() const { return (next_and_bits_ & 2) != 0; } + + Block* next() const { + const uintptr_t bottom_bits = 3; + return reinterpret_cast(next_and_bits_ & ~bottom_bits); + } + + void clear_next() { + next_and_bits_ &= 3; // Set next to nullptr, preserve bottom bits. + } + + size_t pos() const { return pos_; } + size_t size() const { return size_; } + void set_pos(size_t pos) { pos_ = pos; } + + private: + // Holds pointer to next block for this thread + special/user_owned bits. + uintptr_t next_and_bits_; + + size_t pos_; + size_t size_; + // data follows + }; + + // The allocate/free methods here are a little strange, since SerialArena is + // allocated inside a Block which it also manages. This is to avoid doing + // an extra allocation for the SerialArena itself. + + // Creates a new SerialArena inside Block* and returns it. + static SerialArena* New(Block* b, void* owner, ArenaImpl* arena); + + void CleanupList(); + uint64 SpaceUsed() const; + + bool HasSpace(size_t n) { return n <= static_cast(limit_ - ptr_); } + + void* AllocateAligned(size_t n) { + GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + GOOGLE_DCHECK_GE(limit_, ptr_); + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) { + return AllocateAlignedFallback(n); + } + void* ret = ptr_; + ptr_ += n; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, n); +#endif // ADDRESS_SANITIZER + return ret; + } + + // Allocate space if the current region provides enough space. + bool MaybeAllocateAligned(size_t n, void** out) { + GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. + GOOGLE_DCHECK_GE(limit_, ptr_); + if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false; + void* ret = ptr_; + ptr_ += n; +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(ret, n); +#endif // ADDRESS_SANITIZER + *out = ret; + return true; + } + + void AddCleanup(void* elem, void (*cleanup)(void*)) { + if (PROTOBUF_PREDICT_FALSE(cleanup_ptr_ == cleanup_limit_)) { + AddCleanupFallback(elem, cleanup); + return; + } + cleanup_ptr_->elem = elem; + cleanup_ptr_->cleanup = cleanup; + cleanup_ptr_++; + } + + void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*)) { + void* ret = AllocateAligned(n); + AddCleanup(ret, cleanup); + return ret; + } + + Block* head() const { return head_; } + void* owner() const { return owner_; } + SerialArena* next() const { return next_; } + void set_next(SerialArena* next) { next_ = next; } + static Block* NewBlock(Block* last_block, size_t min_bytes, ArenaImpl* arena); + + private: + // Node contains the ptr of the object to be cleaned up and the associated + // cleanup function ptr. + struct CleanupNode { + void* elem; // Pointer to the object to be cleaned up. + void (*cleanup)(void*); // Function pointer to the destructor or deleter. + }; + + // Cleanup uses a chunked linked list, to reduce pointer chasing. + struct CleanupChunk { + static size_t SizeOf(size_t i) { + return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1)); + } + size_t size; // Total elements in the list. + CleanupChunk* next; // Next node in the list. + CleanupNode nodes[1]; // True length is |size|. + }; + + ArenaImpl* arena_; // Containing arena. + void* owner_; // &ThreadCache of this thread; + Block* head_; // Head of linked list of blocks. + CleanupChunk* cleanup_; // Head of cleanup list. + SerialArena* next_; // Next SerialArena in this linked list. + + // Next pointer to allocate from. Always 8-byte aligned. Points inside + // head_ (and head_->pos will always be non-canonical). We keep these + // here to reduce indirection. + char* ptr_; + char* limit_; + + // Next CleanupList members to append to. These point inside cleanup_. + CleanupNode* cleanup_ptr_; + CleanupNode* cleanup_limit_; + + void* AllocateAlignedFallback(size_t n); + void AddCleanupFallback(void* elem, void (*cleanup)(void*)); + void CleanupListFallback(); + + public: + static constexpr size_t kBlockHeaderSize = + (sizeof(Block) + 7) & static_cast(-8); +}; // This class provides the core Arena memory allocation library. Different // implementations only need to implement the public interface below. @@ -65,37 +256,23 @@ using LifecycleId = int64_t; // use #ifdef the select the best implementation based on hardware / OS. class PROTOBUF_EXPORT ArenaImpl { public: - struct Options { - size_t start_block_size; - size_t max_block_size; - char* initial_block; - size_t initial_block_size; - void* (*block_alloc)(size_t); - void (*block_dealloc)(void*, size_t); + static const size_t kDefaultStartBlockSize = 256; + static const size_t kDefaultMaxBlockSize = 8192; - template - explicit Options(const O& options) - : start_block_size(options.start_block_size), - max_block_size(options.max_block_size), - initial_block(options.initial_block), - initial_block_size(options.initial_block_size), - block_alloc(options.block_alloc), - block_dealloc(options.block_dealloc) {} - }; + ArenaImpl() { Init(false); } - template - explicit ArenaImpl(const O& options) : options_(options) { - if (options_.initial_block != NULL && options_.initial_block_size > 0) { - GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block)) - << ": Initial block size too small for header."; - initial_block_ = reinterpret_cast(options_.initial_block); - } else { - initial_block_ = NULL; - } + ArenaImpl(char* mem, size_t size) { + GOOGLE_DCHECK_EQ(reinterpret_cast(mem) & 7, 0u); + Init(false); - Init(); + // Ignore initial block if it is too small. + if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) { + SetInitialBlock(new (mem) SerialArena::Block(size, nullptr, true, true)); + } } + explicit ArenaImpl(const ArenaOptions& options); + // Destructor deletes all owned heap allocated objects, and destructs objects // that have non-trivial destructors, except for proto2 message objects whose // destructors can be skipped. Also, frees all blocks except the initial block @@ -134,178 +311,64 @@ class PROTOBUF_EXPORT ArenaImpl { // Add object pointer and cleanup function pointer to the list. void AddCleanup(void* elem, void (*cleanup)(void*)); - private: - friend class ArenaBenchmark; - - void* AllocateAlignedFallback(size_t n); - void* AllocateAlignedAndAddCleanupFallback(size_t n, void (*cleanup)(void*)); - void AddCleanupFallback(void* elem, void (*cleanup)(void*)); - - // Node contains the ptr of the object to be cleaned up and the associated - // cleanup function ptr. - struct CleanupNode { - void* elem; // Pointer to the object to be cleaned up. - void (*cleanup)(void*); // Function pointer to the destructor or deleter. - }; - - // Cleanup uses a chunked linked list, to reduce pointer chasing. - struct CleanupChunk { - static size_t SizeOf(size_t i) { - return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1)); + inline void RecordAlloc(const std::type_info* allocated_type, + size_t n) const { + if (PROTOBUF_PREDICT_FALSE(record_allocs())) { + options_->metrics_collector->OnAlloc(allocated_type, n); } - size_t size; // Total elements in the list. - CleanupChunk* next; // Next node in the list. - CleanupNode nodes[1]; // True length is |size|. - }; - - class Block; - - // A thread-unsafe Arena that can only be used within its owning thread. - class PROTOBUF_EXPORT SerialArena { - public: - // The allocate/free methods here are a little strange, since SerialArena is - // allocated inside a Block which it also manages. This is to avoid doing - // an extra allocation for the SerialArena itself. + } - // Creates a new SerialArena inside Block* and returns it. - static SerialArena* New(Block* b, void* owner, ArenaImpl* arena); + std::pair NewBuffer(size_t last_size, size_t min_bytes); - // Destroys this SerialArena, freeing all blocks with the given dealloc - // function, except any block equal to |initial_block|. - static uint64 Free(SerialArena* serial, Block* initial_block, - void (*block_dealloc)(void*, size_t)); + private: + // Pointer to a linked list of SerialArena. + std::atomic threads_; + std::atomic hint_; // Fast thread-local block access + std::atomic space_allocated_; // Total size of all allocated blocks. - void CleanupList(); - uint64 SpaceUsed() const; + // Unique for each arena. Changes on Reset(). + // Least-significant-bit is 1 iff allocations should be recorded. + uint64 lifecycle_id_; - bool HasSpace(size_t n) { return n <= static_cast(limit_ - ptr_); } + struct Options { + size_t start_block_size; + size_t max_block_size; + void* (*block_alloc)(size_t); + void (*block_dealloc)(void*, size_t); + ArenaMetricsCollector* metrics_collector; + }; - void* AllocateAligned(size_t n) { - GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. - GOOGLE_DCHECK_GE(limit_, ptr_); - if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) { - return AllocateAlignedFallback(n); - } - void* ret = ptr_; - ptr_ += n; -#ifdef ADDRESS_SANITIZER - ASAN_UNPOISON_MEMORY_REGION(ret, n); -#endif // ADDRESS_SANITIZER - return ret; - } + Options* options_ = nullptr; - // Allocate space if the current region provides enough space. - bool MaybeAllocateAligned(size_t n, void** out) { - GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n); // Must be already aligned. - GOOGLE_DCHECK_GE(limit_, ptr_); - if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false; - void* ret = ptr_; - ptr_ += n; -#ifdef ADDRESS_SANITIZER - ASAN_UNPOISON_MEMORY_REGION(ret, n); -#endif // ADDRESS_SANITIZER - *out = ret; - return true; - } + void* AllocateAlignedFallback(size_t n); + void* AllocateAlignedAndAddCleanupFallback(size_t n, void (*cleanup)(void*)); + void AddCleanupFallback(void* elem, void (*cleanup)(void*)); - void AddCleanup(void* elem, void (*cleanup)(void*)) { - if (PROTOBUF_PREDICT_FALSE(cleanup_ptr_ == cleanup_limit_)) { - AddCleanupFallback(elem, cleanup); - return; + void Init(bool record_allocs); + void SetInitialBlock( + SerialArena::Block* block); // Can be called right after Init() + + // Return true iff allocations should be recorded in a metrics collector. + inline bool record_allocs() const { return lifecycle_id_ & 1; } + + // Invoke fn(b) for every Block* b. + template + void PerBlock(Functor fn) { + // By omitting an Acquire barrier we ensure that any user code that doesn't + // properly synchronize Reset() or the destructor will throw a TSAN warning. + SerialArena* serial = threads_.load(std::memory_order_relaxed); + while (serial) { + // fn() may delete blocks and arenas, so fetch next pointers before fn(); + SerialArena* cur = serial; + serial = serial->next(); + for (auto* block = cur->head(); block != nullptr;) { + auto* b = block; + block = b->next(); + fn(b); } - cleanup_ptr_->elem = elem; - cleanup_ptr_->cleanup = cleanup; - cleanup_ptr_++; } + } - void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*)) { - void* ret = AllocateAligned(n); - AddCleanup(ret, cleanup); - return ret; - } - - void* owner() const { return owner_; } - SerialArena* next() const { return next_; } - void set_next(SerialArena* next) { next_ = next; } - - private: - void* AllocateAlignedFallback(size_t n); - void AddCleanupFallback(void* elem, void (*cleanup)(void*)); - void CleanupListFallback(); - - ArenaImpl* arena_; // Containing arena. - void* owner_; // &ThreadCache of this thread; - Block* head_; // Head of linked list of blocks. - CleanupChunk* cleanup_; // Head of cleanup list. - SerialArena* next_; // Next SerialArena in this linked list. - - // Next pointer to allocate from. Always 8-byte aligned. Points inside - // head_ (and head_->pos will always be non-canonical). We keep these - // here to reduce indirection. - char* ptr_; - char* limit_; - - // Next CleanupList members to append to. These point inside cleanup_. - CleanupNode* cleanup_ptr_; - CleanupNode* cleanup_limit_; - }; - - // Blocks are variable length malloc-ed objects. The following structure - // describes the common header for all blocks. - class PROTOBUF_EXPORT Block { - public: - Block(size_t size, Block* next); - - char* Pointer(size_t n) { - GOOGLE_DCHECK(n <= size_); - return reinterpret_cast(this) + n; - } - - Block* next() const { return next_; } - size_t pos() const { return pos_; } - size_t size() const { return size_; } - void set_pos(size_t pos) { pos_ = pos; } - - private: - Block* next_; // Next block for this thread. - size_t pos_; - size_t size_; - // data follows - }; - - struct ThreadCache { -#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) - // If we are using the ThreadLocalStorage class to store the ThreadCache, - // then the ThreadCache's default constructor has to be responsible for - // initializing it. - ThreadCache() : last_lifecycle_id_seen(-1), last_serial_arena(NULL) {} -#endif - - // The ThreadCache is considered valid as long as this matches the - // lifecycle_id of the arena being used. - LifecycleId last_lifecycle_id_seen; - SerialArena* last_serial_arena; - }; - static std::atomic lifecycle_id_generator_; -#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) - // Android ndk does not support __thread keyword so we use a custom thread - // local storage class we implemented. - // iOS also does not support the __thread keyword. - static ThreadCache& thread_cache(); -#elif defined(PROTOBUF_USE_DLLS) - // Thread local variables cannot be exposed through DLL interface but we can - // wrap them in static functions. - static ThreadCache& thread_cache(); -#else - static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_; - static ThreadCache& thread_cache() { return thread_cache_; } -#endif - - void Init(); - - // Free all blocks and return the total space used which is the sums of sizes - // of the all the allocated blocks. - uint64 FreeBlocks(); // Delete or Destruct all objects owned by the arena. void CleanupList(); @@ -319,16 +382,6 @@ class PROTOBUF_EXPORT ArenaImpl { hint_.store(serial, std::memory_order_release); } - std::atomic - threads_; // Pointer to a linked list of SerialArena. - std::atomic hint_; // Fast thread-local block access - std::atomic space_allocated_; // Total size of all allocated blocks. - - Block* initial_block_; // If non-NULL, points to the block that came from - // user data. - - Block* NewBlock(Block* last_block, size_t min_bytes); - PROTOBUF_ALWAYS_INLINE bool GetSerialArenaFast(SerialArena** arena) { if (GetSerialArenaFromThreadCache(arena)) return true; @@ -356,9 +409,58 @@ class PROTOBUF_EXPORT ArenaImpl { return false; } SerialArena* GetSerialArenaFallback(void* me); - LifecycleId lifecycle_id_; // Unique for each arena. Changes on Reset(). - Options options_; +#ifdef _MSC_VER +#pragma warning(disable : 4324) +#endif + struct alignas(64) ThreadCache { +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) + // If we are using the ThreadLocalStorage class to store the ThreadCache, + // then the ThreadCache's default constructor has to be responsible for + // initializing it. + ThreadCache() + : next_lifecycle_id(0), + last_lifecycle_id_seen(-1), + last_serial_arena(NULL) {} +#endif + + // Number of per-thread lifecycle IDs to reserve. Must be power of two. + // To reduce contention on a global atomic, each thread reserves a batch of + // IDs. The following number is calculated based on a stress test with + // ~6500 threads all frequently allocating a new arena. + static constexpr size_t kPerThreadIds = 256; + // Next lifecycle ID available to this thread. We need to reserve a new + // batch, if `next_lifecycle_id & (kPerThreadIds - 1) == 0`. + uint64 next_lifecycle_id; + // The ThreadCache is considered valid as long as this matches the + // lifecycle_id of the arena being used. + uint64 last_lifecycle_id_seen; + SerialArena* last_serial_arena; + }; + + // Lifecycle_id can be highly contended variable in a situation of lots of + // arena creation. Make sure that other global variables are not sharing the + // cacheline. +#ifdef _MSC_VER +#pragma warning(disable : 4324) +#endif + struct alignas(64) CacheAlignedLifecycleIdGenerator { + std::atomic id; + }; + static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_; +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) + // Android ndk does not support __thread keyword so we use a custom thread + // local storage class we implemented. + // iOS also does not support the __thread keyword. + static ThreadCache& thread_cache(); +#elif defined(PROTOBUF_USE_DLLS) + // Thread local variables cannot be exposed through DLL interface but we can + // wrap them in static functions. + static ThreadCache& thread_cache(); +#else + static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_; + static ThreadCache& thread_cache() { return thread_cache_; } +#endif GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl); // All protos have pointers back to the arena hence Arena must have @@ -369,10 +471,11 @@ class PROTOBUF_EXPORT ArenaImpl { public: // kBlockHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 // to protect the invariant that pos is always at a multiple of 8. - static const size_t kBlockHeaderSize = - (sizeof(Block) + 7) & static_cast(-8); - static const size_t kSerialArenaSize = + static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize; + static constexpr size_t kSerialArenaSize = (sizeof(SerialArena) + 7) & static_cast(-8); + static constexpr size_t kOptionsSize = + (sizeof(Options) + 7) & static_cast(-8); static_assert(kBlockHeaderSize % 8 == 0, "kBlockHeaderSize must be a multiple of 8."); static_assert(kSerialArenaSize % 8 == 0, diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 8919027a89..829c6a0703 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -272,28 +273,36 @@ TEST(ArenaTest, CreateWithMoveArguments) { } TEST(ArenaTest, InitialBlockTooSmall) { - // Construct a small (64 byte) initial block of memory to be used by the - // arena allocator; then, allocate an object which will not fit in the - // initial block. - std::vector arena_block(96); - ArenaOptions options; - options.initial_block = &arena_block[0]; - options.initial_block_size = arena_block.size(); - Arena arena(options); + // Construct a small blocks of memory to be used by the arena allocator; then, + // allocate an object which will not fit in the initial block. + for (int size = 0; size <= Arena::kBlockOverhead + 32; size++) { + std::vector arena_block(size); + ArenaOptions options; + options.initial_block = arena_block.data(); + options.initial_block_size = arena_block.size(); + + // Try sometimes with non-default block sizes so that we exercise paths + // with and without ArenaImpl::Options. + if ((size % 2) != 0) { + options.start_block_size += 8; + } - char* p = Arena::CreateArray(&arena, 96); - uintptr_t allocation = reinterpret_cast(p); + Arena arena(options); + + char* p = Arena::CreateArray(&arena, 96); + uintptr_t allocation = reinterpret_cast(p); - // Ensure that the arena allocator did not return memory pointing into the - // initial block of memory. - uintptr_t arena_start = reinterpret_cast(&arena_block[0]); - uintptr_t arena_end = arena_start + arena_block.size(); - EXPECT_FALSE(allocation >= arena_start && allocation < arena_end); + // Ensure that the arena allocator did not return memory pointing into the + // initial block of memory. + uintptr_t arena_start = reinterpret_cast(arena_block.data()); + uintptr_t arena_end = arena_start + arena_block.size(); + EXPECT_FALSE(allocation >= arena_start && allocation < arena_end); - // Write to the memory we allocated; this should (but is not guaranteed to) - // trigger a check for heap corruption if the object was allocated from the - // initially-provided block. - memset(p, '\0', 96); + // Write to the memory we allocated; this should (but is not guaranteed to) + // trigger a check for heap corruption if the object was allocated from the + // initially-provided block. + memset(p, '\0', 96); + } } TEST(ArenaTest, Parsing) { @@ -988,10 +997,7 @@ TEST(ArenaTest, ExtensionsOnArena) { TEST(ArenaTest, RepeatedFieldOnArena) { // Preallocate an initial arena block to avoid mallocs during hooked region. std::vector arena_block(1024 * 1024); - ArenaOptions options; - options.initial_block = &arena_block[0]; - options.initial_block_size = arena_block.size(); - Arena arena(options); + Arena arena(arena_block.data(), arena_block.size()); { internal::NoHeapChecker no_heap; @@ -1189,10 +1195,7 @@ TEST(ArenaTest, RepeatedFieldWithNonPODType) { uint64 Align8(uint64 n) { return (n + 7) & -8; } TEST(ArenaTest, SpaceAllocated_and_Used) { - ArenaOptions options; - options.start_block_size = 256; - options.max_block_size = 8192; - Arena arena_1(options); + Arena arena_1; EXPECT_EQ(0, arena_1.SpaceAllocated()); EXPECT_EQ(0, arena_1.SpaceUsed()); EXPECT_EQ(0, arena_1.Reset()); @@ -1204,6 +1207,9 @@ TEST(ArenaTest, SpaceAllocated_and_Used) { // Test with initial block. std::vector arena_block(1024); + ArenaOptions options; + options.start_block_size = 256; + options.max_block_size = 8192; options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena_2(options); @@ -1214,19 +1220,25 @@ TEST(ArenaTest, SpaceAllocated_and_Used) { EXPECT_EQ(1024, arena_2.SpaceAllocated()); EXPECT_EQ(Align8(55), arena_2.SpaceUsed()); EXPECT_EQ(1024, arena_2.Reset()); +} - // Reset options to test doubling policy explicitly. - options.initial_block = NULL; - options.initial_block_size = 0; - Arena arena_3(options); - EXPECT_EQ(0, arena_3.SpaceUsed()); - Arena::CreateArray(&arena_3, 160); - EXPECT_EQ(256, arena_3.SpaceAllocated()); - EXPECT_EQ(Align8(160), arena_3.SpaceUsed()); - Arena::CreateArray(&arena_3, 70); - EXPECT_EQ(256 + 512, arena_3.SpaceAllocated()); - EXPECT_EQ(Align8(160) + Align8(70), arena_3.SpaceUsed()); - EXPECT_EQ(256 + 512, arena_3.Reset()); +TEST(ArenaTest, BlockSizeDoubling) { + Arena arena; + EXPECT_EQ(0, arena.SpaceUsed()); + EXPECT_EQ(0, arena.SpaceAllocated()); + + // Allocate something to get initial block size. + Arena::CreateArray(&arena, 1); + auto first_block_size = arena.SpaceAllocated(); + + // Keep allocating until space used increases. + while (arena.SpaceAllocated() == first_block_size) { + Arena::CreateArray(&arena, 1); + } + ASSERT_GT(arena.SpaceAllocated(), first_block_size); + auto second_block_size = (arena.SpaceAllocated() - first_block_size); + + EXPECT_EQ(second_block_size, 2*first_block_size); } TEST(ArenaTest, Alignment) { @@ -1304,81 +1316,93 @@ TEST(ArenaTest, AddCleanup) { } } -// A helper utility class to only contain static hook functions, some -// counters to be used to verify the counters have been called and a cookie -// value to be verified. -class ArenaHooksTestUtil { +namespace { +uint32 hooks_num_init = 0; +uint32 hooks_num_allocations = 0; +uint32 hooks_num_reset = 0; +uint32 hooks_num_destruct = 0; + +void ClearHookCounts() { + hooks_num_init = 0; + hooks_num_allocations = 0; + hooks_num_reset = 0; + hooks_num_destruct = 0; +} +} // namespace + +// A helper utility class that handles arena callbacks. +class ArenaOptionsTestFriend : public internal::ArenaMetricsCollector { public: - static void* on_init(Arena* arena) { - ++num_init; - int* cookie = new int(kCookieValue); - return static_cast(cookie); + static internal::ArenaMetricsCollector* NewWithAllocs() { + return new ArenaOptionsTestFriend(true); } - static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size, - void* cookie) { - ++num_allocations; - int cookie_value = *static_cast(cookie); - EXPECT_EQ(kCookieValue, cookie_value); + static internal::ArenaMetricsCollector* NewWithoutAllocs() { + return new ArenaOptionsTestFriend(false); } - static void on_reset(Arena* arena, void* cookie, uint64 space_used) { - ++num_reset; - int cookie_value = *static_cast(cookie); - EXPECT_EQ(kCookieValue, cookie_value); + static void Enable(ArenaOptions* options) { + ClearHookCounts(); + options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithAllocs; } - static void on_destruction(Arena* arena, void* cookie, uint64 space_used) { - ++num_destruct; - int cookie_value = *static_cast(cookie); - EXPECT_EQ(kCookieValue, cookie_value); - delete static_cast(cookie); + static void EnableWithoutAllocs(ArenaOptions* options) { + ClearHookCounts(); + options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithoutAllocs; } - static const int kCookieValue = 999; - static uint32 num_init; - static uint32 num_allocations; - static uint32 num_reset; - static uint32 num_destruct; -}; -uint32 ArenaHooksTestUtil::num_init = 0; -uint32 ArenaHooksTestUtil::num_allocations = 0; -uint32 ArenaHooksTestUtil::num_reset = 0; -uint32 ArenaHooksTestUtil::num_destruct = 0; -const int ArenaHooksTestUtil::kCookieValue; - -class ArenaOptionsTestFriend { - public: - static void Set(ArenaOptions* options) { - options->on_arena_init = ArenaHooksTestUtil::on_init; - options->on_arena_allocation = ArenaHooksTestUtil::on_allocation; - options->on_arena_reset = ArenaHooksTestUtil::on_reset; - options->on_arena_destruction = ArenaHooksTestUtil::on_destruction; + explicit ArenaOptionsTestFriend(bool record_allocs) + : record_allocs_(record_allocs) { + ++hooks_num_init; } + void OnDestroy(uint64 space_allocated) override { + ++hooks_num_destruct; + delete this; + } + void OnReset(uint64 space_allocated) override { ++hooks_num_reset; } + bool RecordAllocs() override { return record_allocs_; } + void OnAlloc(const std::type_info* allocated_type, + uint64 alloc_size) override { + ++hooks_num_allocations; + } + + private: + bool record_allocs_; }; -// Test the hooks are correctly called and that the cookie is passed. +// Test the hooks are correctly called. TEST(ArenaTest, ArenaHooksSanity) { ArenaOptions options; - ArenaOptionsTestFriend::Set(&options); + ArenaOptionsTestFriend::Enable(&options); // Scope for defining the arena { Arena arena(options); - EXPECT_EQ(1, ArenaHooksTestUtil::num_init); - EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations); + EXPECT_EQ(1, hooks_num_init); + EXPECT_EQ(0, hooks_num_allocations); Arena::Create(&arena); if (std::is_trivially_destructible::value) { - EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations); + EXPECT_EQ(1, hooks_num_allocations); } else { - EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations); + EXPECT_EQ(2, hooks_num_allocations); } arena.Reset(); arena.Reset(); - EXPECT_EQ(2, ArenaHooksTestUtil::num_reset); + EXPECT_EQ(2, hooks_num_reset); } - EXPECT_EQ(3, ArenaHooksTestUtil::num_reset); - EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct); + EXPECT_EQ(2, hooks_num_reset); + EXPECT_EQ(1, hooks_num_destruct); +} + +// Test that allocation hooks are not called when we don't need them. +TEST(ArenaTest, ArenaHooksWhenAllocationsNotNeeded) { + ArenaOptions options; + ArenaOptionsTestFriend::EnableWithoutAllocs(&options); + + Arena arena(options); + EXPECT_EQ(0, hooks_num_allocations); + Arena::Create(&arena); + EXPECT_EQ(0, hooks_num_allocations); } diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc new file mode 100644 index 0000000000..b5f48c53a1 --- /dev/null +++ b/src/google/protobuf/arenastring.cc @@ -0,0 +1,254 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// clang-format off +#include +// clang-format on + +namespace google { +namespace protobuf { +namespace internal { + +const std::string& LazyString::Init() const { + static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED}; + mu.Lock(); + const std::string* res = inited_.load(std::memory_order_acquire); + if (res == nullptr) { + auto init_value = init_value_; + res = ::new (static_cast(string_buf_)) + std::string(init_value.ptr, init_value.size); + inited_.store(res, std::memory_order_release); + } + mu.Unlock(); + return *res; +} + + +void ArenaStringPtr::Set(const std::string* default_value, + ConstStringParam value, ::google::protobuf::Arena* arena) { + if (IsDefault(default_value)) { + tagged_ptr_.Set(Arena::Create(arena, value)); + } else { + UnsafeMutablePointer()->assign(value.data(), value.length()); + } +} + +void ArenaStringPtr::Set(const std::string* default_value, std::string&& value, + ::google::protobuf::Arena* arena) { + if (IsDefault(default_value)) { + if (arena == nullptr) { + tagged_ptr_.Set(new std::string(std::move(value))); + } else { + tagged_ptr_.Set(Arena::Create(arena, std::move(value))); + } + } else if (IsDonatedString()) { + std::string* current = tagged_ptr_.Get(); + auto* s = new (current) std::string(std::move(value)); + arena->OwnDestructor(s); + tagged_ptr_.Set(s); + } else /* !IsDonatedString() */ { + *UnsafeMutablePointer() = std::move(value); + } +} + +void ArenaStringPtr::Set(EmptyDefault, ConstStringParam value, + ::google::protobuf::Arena* arena) { + Set(&GetEmptyStringAlreadyInited(), value, arena); +} + +void ArenaStringPtr::Set(EmptyDefault, std::string&& value, + ::google::protobuf::Arena* arena) { + Set(&GetEmptyStringAlreadyInited(), std::move(value), arena); +} + +void ArenaStringPtr::Set(NonEmptyDefault, ConstStringParam value, + ::google::protobuf::Arena* arena) { + Set(nullptr, value, arena); +} + +void ArenaStringPtr::Set(NonEmptyDefault, std::string&& value, + ::google::protobuf::Arena* arena) { + Set(nullptr, std::move(value), arena); +} + +std::string* ArenaStringPtr::Mutable(EmptyDefault, ::google::protobuf::Arena* arena) { + if (!IsDonatedString() && !IsDefault(&GetEmptyStringAlreadyInited())) { + return UnsafeMutablePointer(); + } else { + return MutableSlow(arena); + } +} + +std::string* ArenaStringPtr::Mutable(const LazyString& default_value, + ::google::protobuf::Arena* arena) { + if (!IsDonatedString() && !IsDefault(nullptr)) { + return UnsafeMutablePointer(); + } else { + return MutableSlow(arena, default_value); + } +} + +std::string* ArenaStringPtr::MutableNoCopy(const std::string* default_value, + ::google::protobuf::Arena* arena) { + if (!IsDonatedString() && !IsDefault(default_value)) { + return UnsafeMutablePointer(); + } else { + GOOGLE_DCHECK(IsDefault(default_value)); + // Allocate empty. The contents are not relevant. + std::string* new_string = Arena::Create(arena); + tagged_ptr_.Set(new_string); + return new_string; + } +} + +template +std::string* ArenaStringPtr::MutableSlow(::google::protobuf::Arena* arena, + const Lazy&... lazy_default) { + const std::string* const default_value = + sizeof...(Lazy) == 0 ? &GetEmptyStringAlreadyInited() : nullptr; + GOOGLE_DCHECK(IsDefault(default_value)); + std::string* new_string = + Arena::Create(arena, lazy_default.get()...); + tagged_ptr_.Set(new_string); + return new_string; +} + +std::string* ArenaStringPtr::Release(const std::string* default_value, + ::google::protobuf::Arena* arena) { + if (IsDefault(default_value)) { + return nullptr; + } else { + return ReleaseNonDefault(default_value, arena); + } +} + +std::string* ArenaStringPtr::ReleaseNonDefault(const std::string* default_value, + ::google::protobuf::Arena* arena) { + GOOGLE_DCHECK(!IsDefault(default_value)); + + if (!IsDonatedString()) { + std::string* released; + if (arena != nullptr) { + released = new std::string; + released->swap(*UnsafeMutablePointer()); + } else { + released = UnsafeMutablePointer(); + } + tagged_ptr_.Set(const_cast(default_value)); + return released; + } else /* IsDonatedString() */ { + GOOGLE_DCHECK(arena != nullptr); + std::string* released = new std::string(Get()); + tagged_ptr_.Set(const_cast(default_value)); + return released; + } +} + +void ArenaStringPtr::SetAllocated(const std::string* default_value, + std::string* value, ::google::protobuf::Arena* arena) { + // Release what we have first. + if (arena == nullptr && !IsDefault(default_value)) { + delete UnsafeMutablePointer(); + } + if (value == nullptr) { + tagged_ptr_.Set(const_cast(default_value)); + } else { +#ifdef NDEBUG + tagged_ptr_.Set(value); + if (arena != nullptr) { + arena->Own(value); + } +#else + // On debug builds, copy the string so the address differs. delete will + // fail if value was a stack-allocated temporary/etc., which would have + // failed when arena ran its cleanup list. + std::string* new_value = Arena::Create(arena, *value); + delete value; + tagged_ptr_.Set(new_value); +#endif + } +} + +void ArenaStringPtr::Destroy(const std::string* default_value, + ::google::protobuf::Arena* arena) { + if (arena == nullptr) { + GOOGLE_DCHECK(!IsDonatedString()); + if (!IsDefault(default_value)) { + delete UnsafeMutablePointer(); + } + } +} + +void ArenaStringPtr::Destroy(EmptyDefault, ::google::protobuf::Arena* arena) { + Destroy(&GetEmptyStringAlreadyInited(), arena); +} + +void ArenaStringPtr::Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena) { + Destroy(nullptr, arena); +} + +void ArenaStringPtr::ClearToEmpty() { + if (IsDefault(&GetEmptyStringAlreadyInited())) { + // Already set to default -- do nothing. + } else { + // Unconditionally mask away the tag. + // + // UpdateDonatedString uses assign when capacity is larger than the new + // value, which is trivially true in the donated string case. + // const_cast(PtrValue())->clear(); + tagged_ptr_.Get()->clear(); + } +} + +void ArenaStringPtr::ClearToDefault(const LazyString& default_value, + ::google::protobuf::Arena* arena) { + (void)arena; + if (IsDefault(nullptr)) { + // Already set to default -- do nothing. + } else if (!IsDonatedString()) { + UnsafeMutablePointer()->assign(default_value.get()); + } +} + + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h index b87be8e39b..60307b2763 100644 --- a/src/google/protobuf/arenastring.h +++ b/src/google/protobuf/arenastring.h @@ -37,7 +37,6 @@ #include #include -#include #include #include @@ -48,261 +47,329 @@ #endif -// This is the implementation of arena string fields written for the open-source -// release. The ArenaStringPtr struct below is an internal implementation class -// and *should not be used* by user code. It is used to collect string -// operations together into one place and abstract away the underlying -// string-field pointer representation, so that (for example) an alternate -// implementation that knew more about ::std::string's internals could integrate -// more closely with the arena allocator. - namespace google { namespace protobuf { namespace internal { +// Lazy string instance to support string fields with non-empty default. +// These are initialized on the first call to .get(). +class PROTOBUF_EXPORT LazyString { + public: + // We explicitly make LazyString an aggregate so that MSVC can do constant + // initialization on it without marking it `constexpr`. + // We do not want to use `constexpr` because it makes it harder to have extern + // storage for it and causes library bloat. + struct InitValue { + const char* ptr; + size_t size; + }; + // We keep a union of the initialization value and the std::string to save on + // space. We don't need the string array after Init() is done. + union { + mutable InitValue init_value_; + alignas(std::string) mutable char string_buf_[sizeof(std::string)]; + }; + mutable std::atomic inited_; + + const std::string& get() const { + // This check generates less code than a call-once invocation. + auto* res = inited_.load(std::memory_order_acquire); + if (PROTOBUF_PREDICT_FALSE(res == nullptr)) return Init(); + return *res; + } + + private: + // Initialize the string in `string_buf_`, update `inited_` and return it. + // We return it here to avoid having to read it again in the inlined code. + const std::string& Init() const; +}; + template class TaggedPtr { public: - void Set(T* p) { ptr_ = reinterpret_cast(p); } - T* Get() const { return reinterpret_cast(ptr_); } + TaggedPtr() = default; + explicit constexpr TaggedPtr(const std::string* ptr) + : ptr_(const_cast(ptr)) {} + + void SetTagged(T* p) { + Set(p); + ptr_ = reinterpret_cast(as_int() | 1); + } + void Set(T* p) { ptr_ = p; } + T* Get() const { return reinterpret_cast(as_int() & -2); } + bool IsTagged() const { return as_int() & 1; } - bool IsNull() { return ptr_ == 0; } + // Returned value is only safe to dereference if IsTagged() == false. + // It is safe to compare. + T* UnsafeGet() const { return static_cast(ptr_); } + + bool IsNull() { return ptr_ == nullptr; } private: - uintptr_t ptr_; + uintptr_t as_int() const { return reinterpret_cast(ptr_); } + void* ptr_; }; -struct PROTOBUF_EXPORT ArenaStringPtr { - inline void Set(const ::std::string* default_value, - const ::std::string& value, Arena* arena) { - if (ptr_ == default_value) { - CreateInstance(arena, &value); - } else { - *ptr_ = value; - } - } +static_assert(std::is_trivial>::value, + "TaggedPtr must be trivial"); - inline void SetLite(const ::std::string* default_value, - const ::std::string& value, Arena* arena) { - Set(default_value, value, arena); - } +// This class encapsulates a pointer to a std::string with or without a donated +// buffer, tagged by bottom bit. It is a high-level wrapper that almost directly +// corresponds to the interface required by string fields in generated +// code. It replaces the old std::string* pointer in such cases. +// +// The object has different but similar code paths for when the default value is +// the empty string and when it is a non-empty string. +// The empty string is handled different throughout the library and there is a +// single global instance of it we can share. +// +// For fields with an empty string default value, there are three distinct +// states: +// +// - Pointer set to 'String' tag (LSB is 0), equal to +// &GetEmptyStringAlreadyInited(): field is set to its default value. Points +// to a true std::string*, but we do not own that std::string* (it's a +// globally shared instance). +// +// - Pointer set to 'String' tag (LSB is 0), but not equal to the global empty +// string: field points to a true std::string* instance that we own. This +// instance is either on the heap or on the arena (i.e. registered on +// free()/destructor-call list) as appropriate. +// +// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string +// instance with a buffer on the arena (arena != NULL, always, in this case). +// +// For fields with a non-empty string default value, there are three distinct +// states: +// +// - Pointer set to 'String' tag (LSB is 0), equal to `nullptr`: +// Field is in "default" mode and does not point to any actual instance. +// Methods that might need to create an instance of the object will pass a +// `const LazyString&` for it. +// +// - Pointer set to 'String' tag (LSB is 0), but not equal to `nullptr`: +// field points to a true std::string* instance that we own. This instance is +// either on the heap or on the arena (i.e. registered on +// free()/destructor-call list) as appropriate. +// +// - Pointer set to 'DonatedString' tag (LSB is 1): points to a std::string +// instance with a buffer on the arena (arena != NULL, always, in this case). +// +// Generated code and reflection code both ensure that ptr_ is never null for +// fields with an empty default. +// Because ArenaStringPtr is used in oneof unions, its constructor is a NOP and +// so the field is always manually initialized via method calls. +// +// Side-note: why pass information about the default on every API call? Because +// we don't want to hold it in a member variable, or else this would go into +// every proto message instance. This would be a huge waste of space, since the +// default instance pointer is typically a global (static class field). We want +// the generated code to be as efficient as possible, and if we take +// the default value information as a parameter that's in practice taken from a +// static class field, and compare ptr_ to the default value, we end up with a +// single "cmp %reg, GLOBAL" in the resulting machine code. (Note that this also +// requires the String tag to be 0 so we can avoid the mask before comparing.) +struct PROTOBUF_EXPORT ArenaStringPtr { + ArenaStringPtr() = default; + explicit constexpr ArenaStringPtr(const std::string* default_value) + : tagged_ptr_(default_value) {} + + // Some methods below are overloaded on a `default_value` and on tags. + // The tagged overloads help reduce code size in the callers in generated + // code, while the `default_value` overloads are useful from reflection. + // By-value empty struct arguments are elided in the ABI. + struct EmptyDefault {}; + struct NonEmptyDefault {}; + + void Set(const std::string* default_value, ConstStringParam value, + ::google::protobuf::Arena* arena); + void Set(const std::string* default_value, std::string&& value, + ::google::protobuf::Arena* arena); + void Set(EmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena); + void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena); + void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena); + void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena); // Basic accessors. - inline const ::std::string& Get() const { return *ptr_; } - - inline ::std::string* Mutable(const ::std::string* default_value, - Arena* arena) { - if (ptr_ == default_value) { - CreateInstance(arena, default_value); - } - return ptr_; + const std::string& Get() const PROTOBUF_ALWAYS_INLINE { + // Unconditionally mask away the tag. + return *tagged_ptr_.Get(); } - - // Release returns a ::std::string* instance that is heap-allocated and is not - // Own()'d by any arena. If the field was not set, it returns NULL. The caller - // retains ownership. Clears this field back to NULL state. Used to implement - // release_() methods on generated classes. - inline ::std::string* Release(const ::std::string* default_value, - Arena* arena) { - if (ptr_ == default_value) { - return NULL; - } - return ReleaseNonDefault(default_value, arena); + const std::string* GetPointer() const PROTOBUF_ALWAYS_INLINE { + // Unconditionally mask away the tag. + return tagged_ptr_.Get(); } - // Similar to Release, but ptr_ cannot be the default_value. - inline ::std::string* ReleaseNonDefault(const ::std::string* default_value, - Arena* arena) { - GOOGLE_DCHECK(!IsDefault(default_value)); - ::std::string* released = NULL; - if (arena != NULL) { - // ptr_ is owned by the arena. - released = new ::std::string; - released->swap(*ptr_); - } else { - released = ptr_; - } - ptr_ = const_cast< ::std::string*>(default_value); - return released; - } - - // UnsafeArenaRelease returns a ::std::string*, but it may be arena-owned - // (i.e. have its destructor already registered) if arena != NULL. If the - // field was not set, this returns NULL. This method clears this field back to - // NULL state. Used to implement unsafe_arena_release_() methods on - // generated classes. - inline ::std::string* UnsafeArenaRelease(const ::std::string* default_value, - Arena* /* arena */) { - if (ptr_ == default_value) { - return NULL; - } - ::std::string* released = ptr_; - ptr_ = const_cast< ::std::string*>(default_value); - return released; - } - - // Takes a string that is heap-allocated, and takes ownership. The string's - // destructor is registered with the arena. Used to implement + // For fields with an empty default value. + std::string* Mutable(EmptyDefault, ::google::protobuf::Arena* arena); + // For fields with a non-empty default value. + std::string* Mutable(const LazyString& default_value, ::google::protobuf::Arena* arena); + + // Release returns a std::string* instance that is heap-allocated and is not + // Own()'d by any arena. If the field is not set, this returns NULL. The + // caller retains ownership. Clears this field back to NULL state. Used to + // implement release_() methods on generated classes. + std::string* Release(const std::string* default_value, + ::google::protobuf::Arena* arena); + std::string* ReleaseNonDefault(const std::string* default_value, + ::google::protobuf::Arena* arena); + + // Takes a std::string that is heap-allocated, and takes ownership. The + // std::string's destructor is registered with the arena. Used to implement // set_allocated_ in generated classes. - inline void SetAllocated(const ::std::string* default_value, - ::std::string* value, Arena* arena) { - if (arena == NULL && ptr_ != default_value) { - Destroy(default_value, arena); - } - if (value != NULL) { - ptr_ = value; - if (arena != NULL) { - arena->Own(value); - } - } else { - ptr_ = const_cast< ::std::string*>(default_value); - } - } - - // Takes a string that has lifetime equal to the arena's lifetime. The arena - // must be non-null. It is safe only to pass this method a value returned by - // UnsafeArenaRelease() on another field of a message in the same arena. Used - // to implement unsafe_arena_set_allocated_ in generated classes. - inline void UnsafeArenaSetAllocated(const ::std::string* default_value, - ::std::string* value, - Arena* /* arena */) { - if (value != NULL) { - ptr_ = value; - } else { - ptr_ = const_cast< ::std::string*>(default_value); - } - } + void SetAllocated(const std::string* default_value, std::string* value, + ::google::protobuf::Arena* arena); // 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. - PROTOBUF_ALWAYS_INLINE void Swap(ArenaStringPtr* other) { - std::swap(ptr_, other->ptr_); - } - PROTOBUF_ALWAYS_INLINE void Swap(ArenaStringPtr* other, - const ::std::string* default_value, - Arena* arena) { -#ifndef NDEBUG - // For debug builds, we swap the contents of the string, rather than the - // string instances themselves. This invalidates previously taken const - // references that are (per our documentation) invalidated by calling Swap() - // on the message. - // - // If both strings are the default_value, swapping is uninteresting. - // Otherwise, we use ArenaStringPtr::Mutable() to access the string, to - // ensure that we do not try to mutate default_value itself. - if (IsDefault(default_value) && other->IsDefault(default_value)) { - return; - } - - ::std::string* this_ptr = Mutable(default_value, arena); - ::std::string* other_ptr = other->Mutable(default_value, arena); - - this_ptr->swap(*other_ptr); -#else - std::swap(ptr_, other->ptr_); - (void)default_value; - (void)arena; -#endif - } + inline void Swap(ArenaStringPtr* other, const std::string* default_value, + Arena* arena) PROTOBUF_ALWAYS_INLINE; // Frees storage (if not on an arena). - inline void Destroy(const ::std::string* default_value, Arena* arena) { - if (arena == NULL && ptr_ != default_value) { - delete ptr_; - } - } + void Destroy(const std::string* default_value, ::google::protobuf::Arena* arena); + void Destroy(EmptyDefault, ::google::protobuf::Arena* arena); + void Destroy(NonEmptyDefault, ::google::protobuf::Arena* arena); - // Clears content, but keeps allocated string if arena != NULL, to avoid the - // overhead of heap operations. After this returns, the content (as seen by - // the user) will always be the empty string. Assumes that |default_value| - // is an empty string. - inline void ClearToEmpty(const ::std::string* default_value, - Arena* /* arena */) { - if (ptr_ == default_value) { - // Already set to default (which is empty) -- do nothing. - } else { - ptr_->clear(); - } - } + // Clears content, but keeps allocated std::string, to avoid the overhead of + // heap operations. After this returns, the content (as seen by the user) will + // always be the empty std::string. Assumes that |default_value| is an empty + // std::string. + void ClearToEmpty(); - // Clears content, assuming that the current value is not the empty string - // default. - inline void ClearNonDefaultToEmpty() { ptr_->clear(); } - - // Clears content, but keeps allocated string if arena != NULL, to avoid the - // overhead of heap operations. After this returns, the content (as seen by - // the user) will always be equal to |default_value|. - inline void ClearToDefault(const ::std::string* default_value, - Arena* /* arena */) { - if (ptr_ == default_value) { - // Already set to default -- do nothing. - } else { - // Have another allocated string -- rather than throwing this away and - // resetting ptr_ to the canonical default string instance, we just reuse - // this instance. - *ptr_ = *default_value; - } - } + // Clears content, assuming that the current value is not the empty + // string default. + void ClearNonDefaultToEmpty(); + + // Clears content, but keeps allocated std::string if arena != NULL, to avoid + // the overhead of heap operations. After this returns, the content (as seen + // by the user) will always be equal to |default_value|. + void ClearToDefault(const LazyString& default_value, ::google::protobuf::Arena* arena); // Called from generated code / reflection runtime only. Resets value to point - // to a default string pointer, with the semantics that this ArenaStringPtr - // does not own the pointed-to memory. Disregards initial value of ptr_ (so - // this is the *ONLY* safe method to call after construction or when - // reinitializing after becoming the active field in a oneof union). - inline void UnsafeSetDefault(const ::std::string* default_value) { - // Casting away 'const' is safe here: accessors ensure that ptr_ is only - // returned as a const if it is equal to default_value. - ptr_ = const_cast< ::std::string*>(default_value); - } + // to a default string pointer, with the semantics that this + // ArenaStringPtr does not own the pointed-to memory. Disregards initial value + // of ptr_ (so this is the *ONLY* safe method to call after construction or + // when reinitializing after becoming the active field in a oneof union). + inline void UnsafeSetDefault(const std::string* default_value); + + // Returns a mutable pointer, but doesn't initialize the string to the + // default value. + std::string* MutableNoArenaNoDefault(const std::string* default_value); + + // Get a mutable pointer with unspecified contents. + // Similar to `MutableNoArenaNoDefault`, but also handles the arena case. + // If the value was donated, the contents are discarded. + std::string* MutableNoCopy(const std::string* default_value, + ::google::protobuf::Arena* arena); // Destroy the string. Assumes `arena == nullptr`. - inline void DestroyNoArena(const ::std::string* default_value) { - if (ptr_ != default_value) { - delete ptr_; - } - } - - // Internal accessor used only at parse time to provide direct access to the - // raw pointer from the shared parse routine (in the non-arenas case). The - // parse routine does the string allocation in order to save code size in the - // generated parsing code. - inline ::std::string** UnsafeRawStringPointer() { return &ptr_; } - - inline bool IsDefault(const ::std::string* default_value) const { - return ptr_ == default_value; - } + void DestroyNoArena(const std::string* default_value); - // Internal accessors!!!! - void UnsafeSetTaggedPointer(TaggedPtr< ::std::string> value) { - ptr_ = value.Get(); + // Internal setter used only at parse time to directly set a donated string + // value. + void UnsafeSetTaggedPointer(TaggedPtr value) { + tagged_ptr_ = value; } // Generated code only! An optimization, in certain cases the generated - // code is certain we can obtain a string with no default checks and + // code is certain we can obtain a std::string with no default checks and // tag tests. - ::std::string* UnsafeMutablePointer() { return ptr_; } + std::string* UnsafeMutablePointer() PROTOBUF_RETURNS_NONNULL; + + inline bool IsDefault(const std::string* default_value) const { + // Relies on the fact that kPtrTagString == 0, so if IsString(), ptr_ is the + // actual std::string pointer (and if !IsString(), ptr_ will never be equal + // to any aligned |default_value| pointer). The key is that we want to avoid + // masking in the fastpath const-pointer Get() case for non-arena code. + return tagged_ptr_.UnsafeGet() == default_value; + } private: - ::std::string* ptr_; + TaggedPtr tagged_ptr_; + + bool IsDonatedString() const { return false; } + + // Slow paths. - PROTOBUF_NOINLINE - void CreateInstance(Arena* arena, const ::std::string* initial_value) { - GOOGLE_DCHECK(initial_value != NULL); - // uses "new ::std::string" when arena is nullptr - ptr_ = Arena::Create< ::std::string>(arena, *initial_value); + // MutableSlow requires that !IsString() || IsDefault + // Variadic to support 0 args for EmptyDefault and 1 arg for LazyString. + template + std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default); + +}; + +inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) { + tagged_ptr_.Set(const_cast(value)); +} + +inline void ArenaStringPtr::Swap(ArenaStringPtr* other, + const std::string* default_value, + Arena* arena) { +#ifndef NDEBUG + // For debug builds, we swap the contents of the string, rather than the + // std::string instances themselves. This invalidates previously taken const + // references that are (per our documentation) invalidated by calling Swap() + // on the message. + // + // If both strings are the default_value, swapping is uninteresting. + // Otherwise, we use ArenaStringPtr::Mutable() to access the std::string, to + // ensure that we do not try to mutate default_value itself. + if (IsDefault(default_value) && other->IsDefault(default_value)) { + return; } - PROTOBUF_NOINLINE - void CreateInstanceNoArena(const ::std::string* initial_value) { - GOOGLE_DCHECK(initial_value != NULL); - ptr_ = new ::std::string(*initial_value); + + if (default_value == nullptr) { + // If we have non-empty default, then `default_value` is null and we can't + // call Mutable the same way. Just do the regular swap. + std::swap(tagged_ptr_, other->tagged_ptr_); + } else { + std::string* this_ptr = Mutable(EmptyDefault{}, arena); + std::string* other_ptr = other->Mutable(EmptyDefault{}, arena); + + this_ptr->swap(*other_ptr); } -}; +#else + std::swap(tagged_ptr_, other->tagged_ptr_); +#endif +} + +inline void ArenaStringPtr::ClearNonDefaultToEmpty() { + // Unconditionally mask away the tag. + tagged_ptr_.Get()->clear(); +} + +inline std::string* ArenaStringPtr::MutableNoArenaNoDefault( + const std::string* default_value) { + // VERY IMPORTANT for performance and code size: this will reduce to a member + // variable load, a pointer check (against |default_value|, in practice a + // static global) and a branch to the slowpath (which calls operator new and + // the ctor). DO NOT add any tagged-pointer operations here. + if (IsDefault(default_value)) { + std::string* new_string = new std::string(); + tagged_ptr_.Set(new_string); + return new_string; + } else { + return UnsafeMutablePointer(); + } +} + +inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) { + if (!IsDefault(default_value)) { + delete UnsafeMutablePointer(); + } +} + +inline std::string* ArenaStringPtr::UnsafeMutablePointer() { + GOOGLE_DCHECK(!tagged_ptr_.IsTagged()); + GOOGLE_DCHECK(tagged_ptr_.UnsafeGet() != nullptr); + return tagged_ptr_.UnsafeGet(); +} + } // namespace internal } // namespace protobuf } // namespace google - #include #endif // GOOGLE_PROTOBUF_ARENASTRING_H__ diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc index c5da4476b4..321b45140f 100644 --- a/src/google/protobuf/arenastring_unittest.cc +++ b/src/google/protobuf/arenastring_unittest.cc @@ -28,8 +28,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Based on mvels@'s frankenstring. - #include #include @@ -42,10 +40,14 @@ #include #include #include +#include #include #include +// Must be included last. +#include + namespace google { namespace protobuf { @@ -53,82 +55,119 @@ using internal::ArenaStringPtr; static std::string WrapString(const char* value) { return value; } +using EmptyDefault = ArenaStringPtr::EmptyDefault; + +const internal::LazyString nonempty_default{{{"default", 7}}, {nullptr}}; + // Test ArenaStringPtr with arena == NULL. TEST(ArenaStringPtrTest, ArenaStringPtrOnHeap) { ArenaStringPtr field; - std::string default_value = "default"; - field.UnsafeSetDefault(&default_value); - EXPECT_EQ(std::string("default"), field.Get()); - field.Set(&default_value, WrapString("Test short"), NULL); + const std::string* empty_default = &internal::GetEmptyString(); + field.UnsafeSetDefault(empty_default); + EXPECT_EQ(std::string(""), field.Get()); + field.Set(empty_default, WrapString("Test short"), NULL); EXPECT_EQ(std::string("Test short"), field.Get()); - field.Set(&default_value, WrapString("Test long long long long value"), NULL); + field.Set(empty_default, WrapString("Test long long long long value"), NULL); EXPECT_EQ(std::string("Test long long long long value"), field.Get()); - field.Set(&default_value, std::string(""), NULL); - field.Destroy(&default_value, NULL); + field.Set(empty_default, std::string(""), NULL); + field.Destroy(empty_default, NULL); ArenaStringPtr field2; - field2.UnsafeSetDefault(&default_value); - std::string* mut = field2.Mutable(&default_value, NULL); - EXPECT_EQ(mut, field2.Mutable(&default_value, NULL)); + field2.UnsafeSetDefault(empty_default); + std::string* mut = field2.Mutable(EmptyDefault{}, NULL); + EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, NULL)); EXPECT_EQ(mut, &field2.Get()); - EXPECT_NE(&default_value, mut); - EXPECT_EQ(std::string("default"), *mut); + EXPECT_NE(empty_default, mut); + EXPECT_EQ(std::string(""), *mut); *mut = "Test long long long long value"; // ensure string allocates storage EXPECT_EQ(std::string("Test long long long long value"), field2.Get()); - field2.Destroy(&default_value, NULL); + field2.Destroy(empty_default, NULL); + + ArenaStringPtr field3; + field3.UnsafeSetDefault(nullptr); + mut = field3.Mutable(nonempty_default, NULL); + EXPECT_EQ(mut, field3.Mutable(nonempty_default, NULL)); + EXPECT_EQ(mut, &field3.Get()); + EXPECT_NE(nullptr, mut); + EXPECT_EQ(std::string("default"), *mut); + *mut = "Test long long long long value"; // ensure string allocates storage + EXPECT_EQ(std::string("Test long long long long value"), field3.Get()); + field3.Destroy(nullptr, NULL); } TEST(ArenaStringPtrTest, ArenaStringPtrOnArena) { Arena arena; ArenaStringPtr field; - std::string default_value = "default"; - field.UnsafeSetDefault(&default_value); - EXPECT_EQ(std::string("default"), field.Get()); - field.Set(&default_value, WrapString("Test short"), &arena); + const std::string* empty_default = &internal::GetEmptyString(); + field.UnsafeSetDefault(empty_default); + EXPECT_EQ(std::string(""), field.Get()); + field.Set(empty_default, WrapString("Test short"), &arena); EXPECT_EQ(std::string("Test short"), field.Get()); - field.Set(&default_value, WrapString("Test long long long long value"), + field.Set(empty_default, WrapString("Test long long long long value"), &arena); EXPECT_EQ(std::string("Test long long long long value"), field.Get()); - field.Set(&default_value, std::string(""), &arena); - field.Destroy(&default_value, &arena); + field.Set(empty_default, std::string(""), &arena); + field.Destroy(empty_default, &arena); ArenaStringPtr field2; - field2.UnsafeSetDefault(&default_value); - std::string* mut = field2.Mutable(&default_value, &arena); - EXPECT_EQ(mut, field2.Mutable(&default_value, &arena)); + field2.UnsafeSetDefault(empty_default); + std::string* mut = field2.Mutable(EmptyDefault{}, &arena); + EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, &arena)); EXPECT_EQ(mut, &field2.Get()); - EXPECT_NE(&default_value, mut); - EXPECT_EQ(std::string("default"), *mut); + EXPECT_NE(empty_default, mut); + EXPECT_EQ(std::string(""), *mut); *mut = "Test long long long long value"; // ensure string allocates storage EXPECT_EQ(std::string("Test long long long long value"), field2.Get()); - field2.Destroy(&default_value, &arena); + field2.Destroy(empty_default, &arena); + + ArenaStringPtr field3; + field3.UnsafeSetDefault(nullptr); + mut = field3.Mutable(nonempty_default, &arena); + EXPECT_EQ(mut, field3.Mutable(nonempty_default, &arena)); + EXPECT_EQ(mut, &field3.Get()); + EXPECT_NE(nullptr, mut); + EXPECT_EQ(std::string("default"), *mut); + *mut = "Test long long long long value"; // ensure string allocates storage + EXPECT_EQ(std::string("Test long long long long value"), field3.Get()); + field3.Destroy(nullptr, &arena); } TEST(ArenaStringPtrTest, ArenaStringPtrOnArenaNoSSO) { Arena arena; ArenaStringPtr field; - std::string default_value = "default"; - field.UnsafeSetDefault(&default_value); - EXPECT_EQ(std::string("default"), field.Get()); + const std::string* empty_default = &internal::GetEmptyString(); + field.UnsafeSetDefault(empty_default); + EXPECT_EQ(std::string(""), field.Get()); // Avoid triggering the SSO optimization by setting the string to something // larger than the internal buffer. - field.Set(&default_value, WrapString("Test long long long long value"), + field.Set(empty_default, WrapString("Test long long long long value"), &arena); EXPECT_EQ(std::string("Test long long long long value"), field.Get()); - field.Set(&default_value, std::string(""), &arena); - field.Destroy(&default_value, &arena); + field.Set(empty_default, std::string(""), &arena); + field.Destroy(empty_default, &arena); ArenaStringPtr field2; - field2.UnsafeSetDefault(&default_value); - std::string* mut = field2.Mutable(&default_value, &arena); - EXPECT_EQ(mut, field2.Mutable(&default_value, &arena)); + field2.UnsafeSetDefault(empty_default); + std::string* mut = field2.Mutable(EmptyDefault{}, &arena); + EXPECT_EQ(mut, field2.Mutable(EmptyDefault{}, &arena)); EXPECT_EQ(mut, &field2.Get()); - EXPECT_NE(&default_value, mut); - EXPECT_EQ(std::string("default"), *mut); + EXPECT_NE(empty_default, mut); + EXPECT_EQ(std::string(""), *mut); *mut = "Test long long long long value"; // ensure string allocates storage EXPECT_EQ(std::string("Test long long long long value"), field2.Get()); - field2.Destroy(&default_value, &arena); + field2.Destroy(empty_default, &arena); + + ArenaStringPtr field3; + field3.UnsafeSetDefault(nullptr); + mut = field3.Mutable(nonempty_default, &arena); + EXPECT_EQ(mut, field3.Mutable(nonempty_default, &arena)); + EXPECT_EQ(mut, &field3.Get()); + EXPECT_NE(nullptr, mut); + EXPECT_EQ(std::string("default"), *mut); + *mut = "Test long long long long value"; // ensure string allocates storage + EXPECT_EQ(std::string("Test long long long long value"), field3.Get()); + field3.Destroy(nullptr, &arena); } diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 45010e48b7..f192ae6740 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1233,6 +1233,7 @@ bool CommandLineInterface::AllowProto3Optional( return false; } + bool CommandLineInterface::VerifyInputFilesInDescriptors( DescriptorDatabase* database) { for (const auto& input_file : input_files_) { @@ -1251,6 +1252,7 @@ bool CommandLineInterface::VerifyInputFilesInDescriptors( << std::endl; return false; } + } return true; } @@ -1301,6 +1303,7 @@ bool CommandLineInterface::ParseInputFiles( break; } + // Enforce --direct_dependencies if (direct_dependencies_explicitly_set_) { bool indirect_imports = false; @@ -1347,6 +1350,7 @@ void CommandLineInterface::Clear() { disallow_services_ = false; direct_dependencies_explicitly_set_ = false; allow_proto3_optional_ = false; + deterministic_output_ = false; } bool CommandLineInterface::MakeProtoProtoPathRelative( @@ -1582,6 +1586,11 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( << std::endl; return PARSE_ARGUMENT_FAIL; } + if (mode_ != MODE_ENCODE && deterministic_output_) { + std::cerr << "Can only use --deterministic_output with --encode." + << std::endl; + return PARSE_ARGUMENT_FAIL; + } if (!dependency_out_name_.empty() && input_files_.size() > 1) { std::cerr << "Can only process one input file when using --dependency_out=FILE." @@ -1650,7 +1659,8 @@ bool CommandLineInterface::ParseArgument(const char* arg, std::string* name, *name == "--include_imports" || *name == "--include_source_info" || *name == "--version" || *name == "--decode_raw" || *name == "--print_free_field_numbers" || - *name == "--experimental_allow_proto3_optional") { + *name == "--experimental_allow_proto3_optional" || + *name == "--deterministic_output") { // HACK: These are the only flags that don't take a value. // They probably should not be hard-coded like this but for now it's // not worth doing better. @@ -1857,6 +1867,7 @@ CommandLineInterface::InterpretArgument(const std::string& name, } else if (name == "--disallow_services") { disallow_services_ = true; + } else if (name == "--experimental_allow_proto3_optional") { allow_proto3_optional_ = true; @@ -1890,6 +1901,9 @@ CommandLineInterface::InterpretArgument(const std::string& name, codec_type_ = value; + } else if (name == "--deterministic_output") { + deterministic_output_ = true; + } else if (name == "--error_format") { if (value == "gcc") { error_format_ = ERROR_FORMAT_GCC; @@ -2032,6 +2046,12 @@ void CommandLineInterface::PrintHelpText() { "must\n" " be defined in PROTO_FILES or their " "imports.\n" + " --deterministic_output When using --encode, ensure map fields " + "are\n" + " deterministically ordered. Note that" + "this order is not\n" + " canonical, and changes across builds" + "or releases of protoc.\n" " --decode=MESSAGE_TYPE Read a binary message of the given " "type from\n" " standard input and write it in text " @@ -2444,7 +2464,9 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { if (mode_ == MODE_ENCODE) { // Output is binary. - if (!message->SerializePartialToZeroCopyStream(&out)) { + io::CodedOutputStream coded_out(&out); + coded_out.SetSerializationDeterministic(deterministic_output_); + if (!message->SerializePartialToCodedStream(&coded_out)) { std::cerr << "output: I/O error." << std::endl; return false; } diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index b89d4e47fc..12ba653758 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -451,6 +451,9 @@ class PROTOC_EXPORT CommandLineInterface { // Was the --experimental_allow_proto3_optional flag used? bool allow_proto3_optional_ = false; + // When using --encode, this will be passed to SetSerializationDeterministic. + bool deterministic_output_ = false; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface); }; diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 5d91042845..1987e08268 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -40,12 +40,14 @@ #include #endif #include +#include #include #include #include #include #include +#include #include #include #include @@ -59,10 +61,10 @@ #include #include #include +#include #include #include -#include namespace google { namespace protobuf { @@ -122,7 +124,7 @@ class CommandLineInterfaceTest : public testing::Test { void SwitchToTempDirectory() { File::ChangeWorkingDirectory(temp_directory_); } -#else // !PROTOBUF_OPENSOURCE +#else // !PROTOBUF_OPENSOURCE // TODO(teboring): Figure out how to change and get working directory in // google3. #endif // !PROTOBUF_OPENSOURCE @@ -680,6 +682,9 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs_UnusedImport_DescriptorSetIn) { FileDescriptorProto::descriptor()->file(); descriptor_file->CopyTo(file_descriptor_set.add_file()); + FileDescriptorProto& any_proto = *file_descriptor_set.add_file(); + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + const FileDescriptor* custom_file = protobuf_unittest::AggregateMessage::descriptor()->file(); FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file(); @@ -1387,6 +1392,7 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) { ExpectGenerated("test_generator", "", "foo.proto", "Foo"); } + TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" @@ -2567,7 +2573,10 @@ class EncodeDecodeTest : public testing::TestWithParam { bool Run(const std::string& command, bool specify_proto_files = true) { std::vector args; args.push_back("protoc"); - SplitStringUsing(command, " ", &args); + for (StringPiece split_piece : + Split(command, " ", true)) { + args.push_back(std::string(split_piece)); + } if (specify_proto_files) { switch (GetParam()) { case PROTO_PATH: @@ -2726,6 +2735,32 @@ TEST_P(EncodeDecodeTest, ProtoParseError) { "net/proto2/internal/no_such_file.proto: No such file or directory\n"); } +TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) { + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/" + "testdata/text_format_unittest_data_oneof_implemented.txt")); + std::string args; + if (GetParam() != DESCRIPTOR_SET_IN) { + args.append( + TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto")); + } + EXPECT_TRUE(Run( + args + " --encode=protobuf_unittest.TestAllTypes --deterministic_output")); + ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); + ExpectStderrMatchesText(""); +} + +TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) { + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); + EXPECT_FALSE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --decode=protobuf_unittest.TestAllTypes --deterministic_output")); + ExpectStderrMatchesText( + "Can only use --deterministic_output with --encode.\n"); +} + INSTANTIATE_TEST_SUITE_P(FileDescriptorSetSource, EncodeDecodeTest, testing::Values(PROTO_PATH, DESCRIPTOR_SET_IN)); } // anonymous namespace diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index aef9aaf304..2d11f907bc 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -164,10 +164,6 @@ class FieldGenerator { return false; } - // Generate code that allocates the fields's default instance. - virtual void GenerateDefaultInstanceAllocator( - io::Printer* /*printer*/) const {} - // Generate lines to serialize this field directly to the array "target", // which are placed within the message's SerializeWithCachedSizesToArray() // method. This must also advance "target" past the written bytes. @@ -178,11 +174,6 @@ class FieldGenerator { // are placed in the message's ByteSize() method. virtual void GenerateByteSize(io::Printer* printer) const = 0; - // Any tags about field layout decisions (such as inlining) to embed in the - // offset. - virtual uint32 CalculateFieldTag() const { return 0; } - virtual bool IsInlined() const { return false; } - void SetHasBitIndex(int32 has_bit_index); protected: diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index c27b464f95..875beec9f6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -941,7 +941,6 @@ void FileGenerator::GenerateInitForSCC(const SCC* scc, if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) { continue; } - message_generators_[i]->GenerateFieldDefaultInstances(printer); format( "{\n" " void* ptr = &$1$;\n" @@ -1198,7 +1197,6 @@ void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { decls[Namespace(d, options_)].AddEnum(d); } - { NamespaceOpener ns(format); for (const auto& pair : decls) { @@ -1281,7 +1279,6 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { IncludeFile("net/proto2/public/arenastring.h", printer); IncludeFile("net/proto2/public/generated_message_table_driven.h", printer); IncludeFile("net/proto2/public/generated_message_util.h", printer); - IncludeFile("net/proto2/public/inlined_string_field.h", printer); IncludeFile("net/proto2/public/metadata_lite.h", printer); if (HasDescriptorMethods(file_, options_)) { diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index b446e8fb23..8b70117796 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -787,25 +787,6 @@ std::string SafeFunctionName(const Descriptor* descriptor, return function_name; } -bool IsStringInlined(const FieldDescriptor* descriptor, - const Options& options) { - if (options.opensource_runtime) return false; - - // TODO(ckennelly): Handle inlining for any.proto. - if (IsAnyMessage(descriptor->containing_type(), options)) return false; - if (descriptor->containing_type()->options().map_entry()) return false; - - // We rely on has bits to distinguish field presence for release_$name$. When - // there is no hasbit, we cannot use the address of the string instance when - // the field has been inlined. - if (!HasHasbit(descriptor)) return false; - - if (options.access_info_map) { - if (descriptor->is_required()) return true; - } - return false; -} - static bool HasLazyFields(const Descriptor* descriptor, const Options& options) { for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) { @@ -1470,8 +1451,7 @@ class ParseLoopGenerator { GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME && // For now only use arena string for strings with empty defaults. field->default_value_string().empty() && - !IsStringInlined(field, options_) && !field->real_containing_oneof() && - ctype == FieldOptions::STRING) { + !field->real_containing_oneof() && ctype == FieldOptions::STRING) { GenerateArenaString(field); } else { std::string name; diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 4ee19b8b15..a036bbc0b7 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -318,8 +318,6 @@ inline bool IsWeak(const FieldDescriptor* field, const Options& options) { return false; } -bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options); - // For a string field, returns the effective ctype. If the actual ctype is // not supported, returns the default of STRING. FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, @@ -410,14 +408,6 @@ inline bool IsProto2MessageSet(const Descriptor* descriptor, descriptor->full_name() == "google.protobuf.bridge.MessageSet"; } -inline bool IsProto2MessageSetFile(const FileDescriptor* file, - const Options& options) { - return !options.opensource_runtime && - options.enforce_mode != EnforceOptimizeMode::kLiteRuntime && - !options.lite_implicit_weak_fields && - file->name() == "net/proto2/bridge/proto/message_set.proto"; -} - inline bool IsMapEntryMessage(const Descriptor* descriptor) { return descriptor->options().map_entry(); } diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 75c009f7ad..aaa00b084b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -1699,9 +1699,6 @@ uint32 CalcFieldNum(const FieldGenerator& generator, int type = field->type(); if (type == FieldDescriptor::TYPE_STRING || type == FieldDescriptor::TYPE_BYTES) { - if (generator.IsInlined()) { - type = internal::FieldMetadata::kInlinedType; - } // string field if (IsCord(field, options)) { type = internal::FieldMetadata::kCordType; @@ -1902,13 +1899,6 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { return num_field_metadata; } -void MessageGenerator::GenerateFieldDefaultInstances(io::Printer* printer) { - // Construct the default instances for all fields that need one. - for (auto field : FieldRange(descriptor_)) { - field_generators_.get(field).GenerateDefaultInstanceAllocator(printer); - } -} - void MessageGenerator::GenerateClassMethods(io::Printer* printer) { Formatter format(printer, variables_); if (IsMapEntryMessage(descriptor_)) { @@ -2111,14 +2101,9 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { } processing_type = static_cast(field->type()); - const FieldGenerator& generator = field_generators_.get(field); if (field->type() == FieldDescriptor::TYPE_STRING) { switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - if (generator.IsInlined()) { - processing_type = internal::TYPE_STRING_INLINED; - break; - } break; case FieldOptions::CORD: processing_type = internal::TYPE_STRING_CORD; @@ -2130,10 +2115,6 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { } else if (field->type() == FieldDescriptor::TYPE_BYTES) { switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - if (generator.IsInlined()) { - processing_type = internal::TYPE_BYTES_INLINED; - break; - } break; case FieldOptions::CORD: processing_type = internal::TYPE_BYTES_CORD; @@ -2317,11 +2298,6 @@ std::pair MessageGenerator::GenerateOffsets( format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_)", FieldName(field)); } - uint32 tag = field_generators_.get(field).CalculateFieldTag(); - if (tag != 0) { - format(" | $1$", tag); - } - if (!IsFieldUsed(field, options_)) { format(" | 0x80000000u, // unused\n"); } else { diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index 0bc32b46c0..933386fbd5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -82,9 +82,6 @@ class MessageGenerator { // Source file stuff. - // Generates code that creates default instances for fields. - void GenerateFieldDefaultInstances(io::Printer* printer); - // Generate all non-inline methods for this class. void GenerateClassMethods(io::Printer* printer); diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 9acc447983..beed6e5107 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -55,12 +55,31 @@ void SetStringVariables(const FieldDescriptor* descriptor, StrCat(descriptor->default_value_string().length()); std::string default_variable_string = MakeDefaultName(descriptor); (*variables)["default_variable_name"] = default_variable_string; - (*variables)["default_variable"] = + + if (!descriptor->default_value_string().empty()) { + (*variables)["lazy_variable"] = + QualifiedClassName(descriptor->containing_type(), options) + + "::" + default_variable_string; + } + + (*variables)["default_string"] = + descriptor->default_value_string().empty() + ? "::" + (*variables)["proto_ns"] + + "::internal::GetEmptyStringAlreadyInited()" + : (*variables)["lazy_variable"] + ".get()"; + (*variables)["init_value"] = descriptor->default_value_string().empty() ? "&::" + (*variables)["proto_ns"] + "::internal::GetEmptyStringAlreadyInited()" - : "&" + QualifiedClassName(descriptor->containing_type(), options) + - "::" + default_variable_string + ".get()"; + : "nullptr"; + (*variables)["default_value_tag"] = + "::" + (*variables)["proto_ns"] + "::internal::ArenaStringPtr::" + + (descriptor->default_value_string().empty() ? "Empty" : "NonEmpty") + + "Default{}"; + (*variables)["default_variable_or_tag"] = + (*variables)[descriptor->default_value_string().empty() + ? "default_value_tag" + : "lazy_variable"]; (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n"; @@ -75,9 +94,6 @@ void SetStringVariables(const FieldDescriptor* descriptor, } else { (*variables)["string_piece"] = "::StringPiece"; } - - (*variables)["lite"] = - HasDescriptorMethods(descriptor->file(), options) ? "" : "Lite"; } } // namespace @@ -86,9 +102,7 @@ void SetStringVariables(const FieldDescriptor* descriptor, StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(descriptor, options), - lite_(!HasDescriptorMethods(descriptor->file(), options)), - inlined_(IsStringInlined(descriptor, options)) { + : FieldGenerator(descriptor, options) { SetStringVariables(descriptor, &variables_, options); } @@ -96,23 +110,15 @@ StringFieldGenerator::~StringFieldGenerator() {} void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { Formatter format(printer, variables_); - if (inlined_) { - format("::$proto_ns$::internal::InlinedStringField $name$_;\n"); - } else { - format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n"); - } + format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n"); } void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const { Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { - // We make the default instance public, so it can be initialized by - // non-friend code. format( - "public:\n" - "static ::$proto_ns$::internal::ExplicitlyConstructed" - " $default_variable_name$;\n" - "private:\n"); + "static const ::$proto_ns$::internal::LazyString" + " $default_variable_name$;\n"); } } @@ -187,7 +193,13 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions( format( "inline const std::string& $classname$::$name$() const {\n" "$annotate_accessor$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n"); + if (!descriptor_->default_value_string().empty()) { + format( + " if ($name$_.IsDefault(nullptr)) return " + "$default_variable_name$.get();\n"); + } + format( " return _internal_$name$();\n" "}\n" "inline void $classname$::set_$name$(const std::string& value) {\n" @@ -206,21 +218,20 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions( "inline void $classname$::_internal_set_$name$(const std::string& " "value) {\n" " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, value, GetArena());\n" + " $name$_.Set($default_value_tag$, value, GetArena());\n" "}\n" "inline void $classname$::set_$name$(std::string&& value) {\n" "$annotate_accessor$" " $set_hasbit$\n" - " $name$_.Set$lite$(\n" - " $default_variable$, ::std::move(value), GetArena());\n" + " $name$_.Set(\n" + " $default_value_tag$, ::std::move(value), GetArena());\n" " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" "}\n" "inline void $classname$::set_$name$(const char* value) {\n" "$annotate_accessor$" " $null_check$" " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, $string_piece$(value),\n" - " GetArena());\n" + " $name$_.Set($default_value_tag$, $string_piece$(value), GetArena());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n"); if (!options_.opensource_runtime) { @@ -228,7 +239,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions( "inline void $classname$::set_$name$(::StringPiece value) {\n" "$annotate_accessor$" " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, value,GetArena());\n" + " $name$_.Set($default_value_tag$, value,GetArena());\n" " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" "}\n"); } @@ -238,13 +249,13 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions( " size_t size) {\n" "$annotate_accessor$" " $set_hasbit$\n" - " $name$_.Set$lite$($default_variable$, $string_piece$(\n" + " $name$_.Set($default_value_tag$, $string_piece$(\n" " reinterpret_cast(value), size), GetArena());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" "inline std::string* $classname$::_internal_mutable_$name$() {\n" " $set_hasbit$\n" - " return $name$_.Mutable($default_variable$, GetArena());\n" + " return $name$_.Mutable($default_variable_or_tag$, GetArena());\n" "}\n" "inline std::string* $classname$::$release_name$() {\n" "$annotate_accessor$" @@ -256,10 +267,9 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions( " return nullptr;\n" " }\n" " $clear_hasbit$\n" - " return $name$_.ReleaseNonDefault(" - "$default_variable$, GetArena());\n"); + " return $name$_.ReleaseNonDefault($init_value$, GetArena());\n"); } else { - format(" return $name$_.Release($default_variable$, GetArena());\n"); + format(" return $name$_.Release($init_value$, GetArena());\n"); } format( @@ -271,7 +281,7 @@ void StringFieldGenerator::GenerateInlineAccessorDefinitions( " } else {\n" " $clear_hasbit$\n" " }\n" - " $name$_.SetAllocated($default_variable$, $name$,\n" + " $name$_.SetAllocated($init_value$, $name$,\n" " GetArena());\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); @@ -281,23 +291,19 @@ void StringFieldGenerator::GenerateNonInlineAccessorDefinitions( io::Printer* printer) const { Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { - // Initialized in GenerateDefaultInstanceAllocator. format( - "::$proto_ns$::internal::ExplicitlyConstructed " - "$classname$::$default_variable_name$;\n"); + "const ::$proto_ns$::internal::LazyString " + "$classname$::$default_variable_name$" + "{{{$default$, $default_length$}}, {nullptr}};\n"); } } void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const { Formatter format(printer, variables_); - // Two-dimension specialization here: supporting arenas or not, and default - // value is the empty string or not. Complexity here ensures the minimal - // number of branches / amount of extraneous code at runtime (given that the - // below methods are inlined one-liners)! if (descriptor_->default_value_string().empty()) { - format("$name$_.ClearToEmpty($default_variable$, GetArena());\n"); + format("$name$_.ClearToEmpty();\n"); } else { - format("$name$_.ClearToDefault($default_variable$, GetArena());\n"); + format("$name$_.ClearToDefault($lazy_variable$, GetArena());\n"); } } @@ -311,31 +317,19 @@ void StringFieldGenerator::GenerateMessageClearingCode( // If we have a hasbit, then the Clear() method of the protocol buffer // will have checked that this field is set. If so, we can avoid redundant - // checks against default_variable. + // checks against the default variable. const bool must_be_present = HasHasbit(descriptor_); - if (inlined_ && must_be_present) { - // Calling mutable_$name$() gives us a string reference and sets the has bit - // for $name$ (in proto2). We may get here when the string field is inlined - // but the string's contents have not been changed by the user, so we cannot - // make an assertion about the contents of the string and could never make - // an assertion about the string instance. - // - // For non-inlined strings, we distinguish from non-default by comparing - // instances, rather than contents. - format("$DCHK$(!$name$_.IsDefault($default_variable$));\n"); - } - if (descriptor_->default_value_string().empty()) { if (must_be_present) { format("$name$_.ClearNonDefaultToEmpty();\n"); } else { - format("$name$_.ClearToEmpty($default_variable$, GetArena());\n"); + format("$name$_.ClearToEmpty();\n"); } } else { // Clear to a non-empty default is more involved, as we try to use the // Arena if one is present and may need to reallocate the string. - format("$name$_.ClearToDefault($default_variable$, GetArena());\n"); + format("$name$_.ClearToDefault($lazy_variable$, GetArena());\n "); } } @@ -347,23 +341,12 @@ void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const { void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { Formatter format(printer, variables_); - if (inlined_) { - format("$name$_.Swap(&other->$name$_);\n"); - } else { - format("$name$_.Swap(&other->$name$_, $default_variable$, GetArena());\n"); - } + format("$name$_.Swap(&other->$name$_, $init_value$, GetArena());\n"); } void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { Formatter format(printer, variables_); - // TODO(ckennelly): Construct non-empty strings as part of the initializer - // list. - if (inlined_ && descriptor_->default_value_string().empty()) { - // Automatic initialization will construct the string. - return; - } - - format("$name$_.UnsafeSetDefault($default_variable$);\n"); + format("$name$_.UnsafeSetDefault($init_value$);\n"); } void StringFieldGenerator::GenerateCopyConstructorCode( @@ -381,7 +364,7 @@ void StringFieldGenerator::GenerateCopyConstructorCode( // TODO(gpike): improve this format( - "$name$_.Set$lite$($default_variable$, from._internal_$name$(),\n" + "$name$_.Set($default_value_tag$, from._internal_$name$(), \n" " GetArena());\n"); format.Outdent(); @@ -390,40 +373,7 @@ void StringFieldGenerator::GenerateCopyConstructorCode( void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { Formatter format(printer, variables_); - if (inlined_) { - // The destructor is automatically invoked. - return; - } - - format("$name$_.DestroyNoArena($default_variable$);\n"); -} - -bool StringFieldGenerator::GenerateArenaDestructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (!inlined_) { - return false; - } - - format("_this->$name$_.DestroyNoArena($default_variable$);\n"); - return true; -} - -void StringFieldGenerator::GenerateDefaultInstanceAllocator( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (!descriptor_->default_value_string().empty()) { - format( - "$ns$::$classname$::$default_variable_name$.DefaultConstruct();\n" - "*$ns$::$classname$::$default_variable_name$.get_mutable() = " - "std::string($default$, $default_length$);\n" - "::$proto_ns$::internal::OnShutdownDestroyString(\n" - " $ns$::$classname$::$default_variable_name$.get_mutable());\n"); - } -} - -bool StringFieldGenerator::MergeFromCodedStreamNeedsArena() const { - return !lite_ && !inlined_ && !options_.opensource_runtime; + format("$name$_.DestroyNoArena($init_value$);\n"); } void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray( @@ -449,17 +399,11 @@ void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const { " this->_internal_$name$());\n"); } -uint32 StringFieldGenerator::CalculateFieldTag() const { - return inlined_ ? 1 : 0; -} - // =================================================================== StringOneofFieldGenerator::StringOneofFieldGenerator( const FieldDescriptor* descriptor, const Options& options) : StringFieldGenerator(descriptor, options) { - inlined_ = false; - SetCommonOneofFieldVariables(descriptor, &variables_); variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true); variables_["oneof_index"] = @@ -491,16 +435,16 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( " if (_internal_has_$name$()) {\n" " return $field_member$.Get();\n" " }\n" - " return *$default_variable$;\n" + " return $default_string$;\n" "}\n" "inline void $classname$::_internal_set_$name$(const std::string& " "value) {\n" " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" " }\n" - " $field_member$.Set$lite$($default_variable$, value, GetArena());\n" + " $field_member$.Set($default_value_tag$, value, GetArena());\n" "}\n" "inline void $classname$::set_$name$(std::string&& value) {\n" "$annotate_accessor$" @@ -508,10 +452,10 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" " }\n" - " $field_member$.Set$lite$(\n" - " $default_variable$, ::std::move(value), GetArena());\n" + " $field_member$.Set(\n" + " $default_value_tag$, ::std::move(value), GetArena());\n" " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n" "}\n" "inline void $classname$::set_$name$(const char* value) {\n" @@ -520,9 +464,9 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" " }\n" - " $field_member$.Set$lite$($default_variable$,\n" + " $field_member$.Set($default_value_tag$,\n" " $string_piece$(value), GetArena());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n"); @@ -533,10 +477,9 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" " }\n" - " $field_member$.Set$lite$($default_variable$, value,\n" - " GetArena());\n" + " $field_member$.Set($default_value_tag$, value, GetArena());\n" " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" "}\n"); } @@ -548,10 +491,10 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" " }\n" - " $field_member$.Set$lite$(\n" - " $default_variable$, $string_piece$(\n" + " $field_member$.Set(\n" + " $default_value_tag$, $string_piece$(\n" " reinterpret_cast(value), size),\n" " GetArena());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" @@ -560,16 +503,17 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( " if (!_internal_has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + " $field_member$.UnsafeSetDefault($init_value$);\n" " }\n" - " return $field_member$.Mutable($default_variable$, GetArena());\n" + " return $field_member$.Mutable(\n" + " $default_variable_or_tag$, GetArena());\n" "}\n" "inline std::string* $classname$::$release_name$() {\n" "$annotate_accessor$" " // @@protoc_insertion_point(field_release:$full_name$)\n" " if (_internal_has_$name$()) {\n" " clear_has_$oneof_name$();\n" - " return $field_member$.Release($default_variable$, GetArena());\n" + " return $field_member$.ReleaseNonDefault($init_value$, GetArena());\n" " } else {\n" " return nullptr;\n" " }\n" @@ -594,7 +538,7 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( void StringOneofFieldGenerator::GenerateClearingCode( io::Printer* printer) const { Formatter format(printer, variables_); - format("$field_member$.Destroy($default_variable$, GetArena());\n"); + format("$field_member$.Destroy($default_value_tag$, GetArena());\n"); } void StringOneofFieldGenerator::GenerateMessageClearingCode( @@ -609,10 +553,7 @@ void StringOneofFieldGenerator::GenerateSwappingCode( void StringOneofFieldGenerator::GenerateConstructorCode( io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "$ns$::_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n" - " $default_variable$);\n"); + // Nothing required here. } // =================================================================== diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 0192b3dd6d..91424d221c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -63,18 +63,8 @@ class StringFieldGenerator : public FieldGenerator { void GenerateConstructorCode(io::Printer* printer) const; void GenerateCopyConstructorCode(io::Printer* printer) const; void GenerateDestructorCode(io::Printer* printer) const; - bool GenerateArenaDestructorCode(io::Printer* printer) const; - void GenerateDefaultInstanceAllocator(io::Printer* printer) const; void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - uint32 CalculateFieldTag() const; - bool IsInlined() const { return inlined_; } - - bool MergeFromCodedStreamNeedsArena() const; - - protected: - const bool lite_; - bool inlined_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 8622ff0507..51032c2742 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -77,9 +77,10 @@ void EnumGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); printer->Print( - "public enum $classname$\n" + "$deprecation$public enum $classname$\n" " implements com.google.protobuf.ProtocolMessageEnum {\n", - "classname", descriptor_->name()); + "classname", descriptor_->name(), "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""); printer->Annotate("classname", descriptor_); printer->Indent(); diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 7eb9c75485..d96ac7d772 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -81,7 +81,7 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations. (*variables)["for_number"] = "valueOf"; - if (SupportFieldPresence(descriptor)) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -145,7 +145,7 @@ ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator( ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { - return SupportFieldPresence(descriptor_) ? 1 : 0; + return HasHasbit(descriptor_) ? 1 : 0; } int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { 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 23aea9b20b..b0b3b78cc6 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc @@ -83,7 +83,7 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["required"] = descriptor->is_required() ? "true" : "false"; - if (SupportFieldPresence(descriptor)) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); @@ -137,7 +137,7 @@ ImmutableEnumFieldLiteGenerator::ImmutableEnumFieldLiteGenerator( ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {} int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { - return SupportFieldPresence(descriptor_) ? 1 : 0; + return HasHasbit(descriptor_) ? 1 : 0; } void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers( diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc index 226fa4fb51..aa64c97127 100644 --- a/src/google/protobuf/compiler/java/java_enum_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_lite.cc @@ -78,9 +78,10 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); printer->Print( - "public enum $classname$\n" + "$deprecation$public enum $classname$\n" " implements com.google.protobuf.Internal.EnumLite {\n", - "classname", descriptor_->name()); + "classname", descriptor_->name(), "deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""); printer->Annotate("classname", descriptor_); printer->Indent(); diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 2fc7aadff6..fb00110c41 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -76,7 +76,6 @@ struct FieldDescriptorCompare { typedef std::set FieldDescriptorSet; - // Recursively searches the given message to collect extensions. // Returns true if all the extensions can be recognized. The extensions will be // appended in to the extensions parameter. @@ -86,9 +85,7 @@ bool CollectExtensions(const Message& message, FieldDescriptorSet* extensions) { const Reflection* reflection = message.GetReflection(); // There are unknown fields that could be extensions, thus this call fails. - UnknownFieldSet unknown_fields; - unknown_fields.MergeFrom(reflection->GetUnknownFields(message)); - if (unknown_fields.field_count() > 0) return false; + if (reflection->GetUnknownFields(message).field_count() > 0) return false; std::vector fields; reflection->ListFields(message, &fields); @@ -390,6 +387,7 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print("}\n"); } + void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( io::Printer* printer) { printer->Print( diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index bb3e4a5765..9f1f719237 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -78,6 +78,7 @@ class FileGenerator { void Generate(io::Printer* printer); + // If we aren't putting everything into one file, this will write all the // files other than the outer file (i.e. one for each message, enum, and // service type). diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 0192e4bc67..6623595b11 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -1355,7 +1355,6 @@ void ImmutableMessageGenerator::GenerateInitializers(io::Printer* printer) { } } - void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { printer->Print( "private static String getTypeUrl(\n" diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc index d998f166a3..bc13dd8733 100644 --- a/src/google/protobuf/compiler/java/java_name_resolver.cc +++ b/src/google/protobuf/compiler/java/java_name_resolver.cc @@ -160,7 +160,14 @@ std::string ClassNameResolver::GetFileImmutableClassName( std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file, bool immutable) { - if (immutable) { + return GetFileClassName(file, immutable, false); +} + +std::string ClassNameResolver::GetFileClassName(const FileDescriptor* file, + bool immutable, bool kotlin) { + if (kotlin) { + return GetFileImmutableClassName(file) + "Kt"; + } else if (immutable) { return GetFileImmutableClassName(file); } else { return "Mutable" + GetFileImmutableClassName(file); @@ -200,9 +207,14 @@ std::string ClassNameResolver::GetDescriptorClassName( std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, bool immutable) { + return GetClassName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, + bool immutable, bool kotlin) { std::string result = FileJavaPackage(descriptor, immutable); if (!result.empty()) result += '.'; - result += GetFileClassName(descriptor, immutable); + result += GetFileClassName(descriptor, immutable, kotlin); return result; } @@ -211,50 +223,79 @@ std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, std::string ClassNameResolver::GetClassFullName( const std::string& name_without_package, const FileDescriptor* file, bool immutable, bool is_own_file) { + return GetClassFullName(name_without_package, file, immutable, is_own_file, + false); +} + +std::string ClassNameResolver::GetClassFullName( + const std::string& name_without_package, const FileDescriptor* file, + bool immutable, bool is_own_file, bool kotlin) { std::string result; if (is_own_file) { result = FileJavaPackage(file, immutable); } else { - result = GetClassName(file, immutable); + result = GetClassName(file, immutable, kotlin); } if (!result.empty()) { result += '.'; } result += name_without_package; + if (kotlin) result += "Kt"; return result; } std::string ClassNameResolver::GetClassName(const Descriptor* descriptor, bool immutable) { - return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), - descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); + return GetClassName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetClassName(const Descriptor* descriptor, + bool immutable, bool kotlin) { + return GetClassFullName( + ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), + immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin); } std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, bool immutable) { - return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), - descriptor->file(), immutable, - MultipleJavaFiles(descriptor->file(), immutable)); + return GetClassName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, + bool immutable, bool kotlin) { + return GetClassFullName( + ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), + immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin); } std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, bool immutable) { + return GetClassName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, + bool immutable, bool kotlin) { return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), immutable, - IsOwnFile(descriptor, immutable)); + IsOwnFile(descriptor, immutable), kotlin); } // Get the Java Class style full name of a message. std::string ClassNameResolver::GetJavaClassFullName( const std::string& name_without_package, const FileDescriptor* file, bool immutable) { + return GetJavaClassFullName(name_without_package, file, immutable, false); +} + +std::string ClassNameResolver::GetJavaClassFullName( + const std::string& name_without_package, const FileDescriptor* file, + bool immutable, bool kotlin) { std::string result; if (MultipleJavaFiles(file, immutable)) { result = FileJavaPackage(file, immutable); if (!result.empty()) result += '.'; } else { - result = GetClassName(file, immutable); + result = GetClassName(file, immutable, kotlin); if (!result.empty()) result += '$'; } result += StringReplace(name_without_package, ".", "$", true); @@ -263,7 +304,12 @@ std::string ClassNameResolver::GetJavaClassFullName( std::string ClassNameResolver::GetExtensionIdentifierName( const FieldDescriptor* descriptor, bool immutable) { - return GetClassName(descriptor->containing_type(), immutable) + "." + + return GetExtensionIdentifierName(descriptor, immutable, false); +} + +std::string ClassNameResolver::GetExtensionIdentifierName( + const FieldDescriptor* descriptor, bool immutable, bool kotlin) { + return GetClassName(descriptor->containing_type(), immutable, kotlin) + "." + descriptor->name(); } diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h index b92570c600..8461df9009 100644 --- a/src/google/protobuf/compiler/java/java_name_resolver.h +++ b/src/google/protobuf/compiler/java/java_name_resolver.h @@ -60,6 +60,8 @@ class ClassNameResolver { // Gets the unqualified outer class name for the file. std::string GetFileClassName(const FileDescriptor* file, bool immutable); + std::string GetFileClassName(const FileDescriptor* file, bool immutable, + bool kotlin); // Gets the unqualified immutable outer class name of a file. std::string GetFileImmutableClassName(const FileDescriptor* file); // Gets the unqualified default immutable outer class name of a file @@ -80,9 +82,17 @@ class ClassNameResolver { // Gets the fully-qualified class name corresponding to the given descriptor. std::string GetClassName(const Descriptor* descriptor, bool immutable); + std::string GetClassName(const Descriptor* descriptor, bool immutable, + bool kotlin); std::string GetClassName(const EnumDescriptor* descriptor, bool immutable); + std::string GetClassName(const EnumDescriptor* descriptor, bool immutable, + bool kotlin); std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable); + std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable, + bool kotlin); std::string GetClassName(const FileDescriptor* descriptor, bool immutable); + std::string GetClassName(const FileDescriptor* descriptor, bool immutable, + bool kotlin); template std::string GetImmutableClassName(const DescriptorType* descriptor) { @@ -96,6 +106,8 @@ class ClassNameResolver { // Gets the fully qualified name of an extension identifier. std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor, bool immutable); + std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor, + bool immutable, bool kotlin); // Gets the fully qualified name for generated classes in Java convention. // Nested classes will be separated using '$' instead of '.' @@ -109,9 +121,15 @@ class ClassNameResolver { std::string GetClassFullName(const std::string& name_without_package, const FileDescriptor* file, bool immutable, bool is_own_file); + std::string GetClassFullName(const std::string& name_without_package, + const FileDescriptor* file, bool immutable, + bool is_own_file, bool kotlin); // Get the Java Class style full name of a message. std::string GetJavaClassFullName(const std::string& name_without_package, const FileDescriptor* file, bool immutable); + std::string GetJavaClassFullName(const std::string& name_without_package, + const FileDescriptor* file, bool immutable, + bool kotlin); // Caches the result to provide better performance. std::map file_immutable_outer_class_names_; diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index f0b3d0959e..f06e8fb203 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -133,7 +133,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } (*variables)["on_changed"] = "onChanged();"; - if (SupportFieldPresence(descriptor)) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -195,7 +195,7 @@ ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator( ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { - return SupportFieldPresence(descriptor_) ? 1 : 0; + return HasHasbit(descriptor_) ? 1 : 0; } int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { 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 53366b295a..59dba76cc0 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc @@ -140,7 +140,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["fixed_size"] = StrCat(fixed_size); } - if (SupportFieldPresence(descriptor)) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); @@ -188,7 +188,7 @@ ImmutablePrimitiveFieldLiteGenerator::ImmutablePrimitiveFieldLiteGenerator( ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {} int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const { - return SupportFieldPresence(descriptor_) ? 1 : 0; + return HasHasbit(descriptor_) ? 1 : 0; } void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers( diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 37e81b1100..548f898e46 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -90,7 +90,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["on_changed"] = "onChanged();"; - if (SupportFieldPresence(descriptor)) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -147,7 +147,7 @@ ImmutableStringFieldGenerator::ImmutableStringFieldGenerator( ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { - return SupportFieldPresence(descriptor_) ? 1 : 0; + return HasHasbit(descriptor_) ? 1 : 0; } int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { 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 432a789551..06a3c25bd9 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc @@ -85,7 +85,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["required"] = descriptor->is_required() ? "true" : "false"; - if (SupportFieldPresence(descriptor)) { + if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); @@ -127,7 +127,7 @@ ImmutableStringFieldLiteGenerator::ImmutableStringFieldLiteGenerator( ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {} int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { - return SupportFieldPresence(descriptor_) ? 1 : 0; + return HasHasbit(descriptor_) ? 1 : 0; } // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes, diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index a702ca9495..895b47dee6 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -65,6 +65,7 @@ int ProtobufMain(int argc, char* argv[]) { "Generate Java source file."); + // Proto2 Python python::Generator py_generator; cli.RegisterGenerator("--python_out", "--python_opt", &py_generator, diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index b463622d4a..3abb5c0b13 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -119,7 +119,7 @@ void MockCodeGenerator::ExpectGenerated( std::vector insertion_list; if (!insertions.empty()) { - SplitStringUsing(insertions, ",", &insertion_list); + insertion_list = Split(insertions, ",", true); } EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2); @@ -250,12 +250,10 @@ bool MockCodeGenerator::Generate(const FileDescriptor* file, bool insert_endlines = HasPrefixString(parameter, "insert_endlines="); if (insert_endlines || HasPrefixString(parameter, "insert=")) { - std::vector insert_into; - - SplitStringUsing( + std::vector insert_into = Split( StripPrefixString( parameter, insert_endlines ? "insert_endlines=" : "insert="), - ",", &insert_into); + ",", true); for (size_t i = 0; i < insert_into.size(); i++) { { diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 4a3a228e89..cbb24a50a5 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -2276,6 +2277,11 @@ TEST_F(ParseDescriptorDebugTest, TestCustomOptions) { FileDescriptorProto import_proto; import->CopyTo(&import_proto); ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); + + FileDescriptorProto any_import; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_import); + ASSERT_TRUE(pool_.BuildFile(any_import) != nullptr); + const FileDescriptor* actual = pool_.BuildFile(parsed); ASSERT_TRUE(actual != NULL); parsed.Clear(); diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 83d631af69..2422ce5f77 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -260,7 +260,7 @@ Version::Version(const Version& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); suffix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_suffix()) { - suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_suffix(), + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_suffix(), GetArena()); } ::memcpy(&major_, &from.major_, @@ -593,7 +593,7 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); parameter_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_parameter()) { - parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_parameter(), + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_parameter(), GetArena()); } if (from._internal_has_compiler_version()) { @@ -945,17 +945,17 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } insertion_point_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_insertion_point()) { - insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_insertion_point(), + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_insertion_point(), GetArena()); } content_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_content()) { - content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_content(), + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_content(), GetArena()); } if (from._internal_has_generated_code_info()) { @@ -1300,7 +1300,7 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); error_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_error()) { - error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_error(), + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_error(), GetArena()); } supported_features_ = from.supported_features_; diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index 09e3bbb171..ee1308c6a0 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -1076,7 +1075,7 @@ inline bool Version::has_suffix() const { return _internal_has_suffix(); } inline void Version::clear_suffix() { - suffix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + suffix_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& Version::suffix() const { @@ -1096,31 +1095,30 @@ inline const std::string& Version::_internal_suffix() const { } inline void Version::_internal_set_suffix(const std::string& value) { _has_bits_[0] |= 0x00000001u; - suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Version::set_suffix(std::string&& value) { _has_bits_[0] |= 0x00000001u; suffix_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix) } inline void Version::set_suffix(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix) } inline void Version::set_suffix(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - suffix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix) } inline std::string* Version::_internal_mutable_suffix() { _has_bits_[0] |= 0x00000001u; - return suffix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return suffix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Version::release_suffix() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix) @@ -1228,7 +1226,7 @@ inline bool CodeGeneratorRequest::has_parameter() const { return _internal_has_parameter(); } inline void CodeGeneratorRequest::clear_parameter() { - parameter_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + parameter_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& CodeGeneratorRequest::parameter() const { @@ -1248,31 +1246,30 @@ inline const std::string& CodeGeneratorRequest::_internal_parameter() const { } inline void CodeGeneratorRequest::_internal_set_parameter(const std::string& value) { _has_bits_[0] |= 0x00000001u; - parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void CodeGeneratorRequest::set_parameter(std::string&& value) { _has_bits_[0] |= 0x00000001u; parameter_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - parameter_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline std::string* CodeGeneratorRequest::_internal_mutable_parameter() { _has_bits_[0] |= 0x00000001u; - return parameter_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return parameter_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* CodeGeneratorRequest::release_parameter() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter) @@ -1425,7 +1422,7 @@ inline bool CodeGeneratorResponse_File::has_name() const { return _internal_has_name(); } inline void CodeGeneratorResponse_File::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& CodeGeneratorResponse_File::name() const { @@ -1445,31 +1442,30 @@ inline const std::string& CodeGeneratorResponse_File::_internal_name() const { } inline void CodeGeneratorResponse_File::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void CodeGeneratorResponse_File::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline std::string* CodeGeneratorResponse_File::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* CodeGeneratorResponse_File::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name) @@ -1499,7 +1495,7 @@ inline bool CodeGeneratorResponse_File::has_insertion_point() const { return _internal_has_insertion_point(); } inline void CodeGeneratorResponse_File::clear_insertion_point() { - insertion_point_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + insertion_point_.ClearToEmpty(); _has_bits_[0] &= ~0x00000002u; } inline const std::string& CodeGeneratorResponse_File::insertion_point() const { @@ -1519,31 +1515,30 @@ inline const std::string& CodeGeneratorResponse_File::_internal_insertion_point( } inline void CodeGeneratorResponse_File::_internal_set_insertion_point(const std::string& value) { _has_bits_[0] |= 0x00000002u; - insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void CodeGeneratorResponse_File::set_insertion_point(std::string&& value) { _has_bits_[0] |= 0x00000002u; insertion_point_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000002u; - insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { _has_bits_[0] |= 0x00000002u; - insertion_point_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline std::string* CodeGeneratorResponse_File::_internal_mutable_insertion_point() { _has_bits_[0] |= 0x00000002u; - return insertion_point_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return insertion_point_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* CodeGeneratorResponse_File::release_insertion_point() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) @@ -1573,7 +1568,7 @@ inline bool CodeGeneratorResponse_File::has_content() const { return _internal_has_content(); } inline void CodeGeneratorResponse_File::clear_content() { - content_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + content_.ClearToEmpty(); _has_bits_[0] &= ~0x00000004u; } inline const std::string& CodeGeneratorResponse_File::content() const { @@ -1593,31 +1588,30 @@ inline const std::string& CodeGeneratorResponse_File::_internal_content() const } inline void CodeGeneratorResponse_File::_internal_set_content(const std::string& value) { _has_bits_[0] |= 0x00000004u; - content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void CodeGeneratorResponse_File::set_content(std::string&& value) { _has_bits_[0] |= 0x00000004u; content_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000004u; - content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { _has_bits_[0] |= 0x00000004u; - content_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline std::string* CodeGeneratorResponse_File::_internal_mutable_content() { _has_bits_[0] |= 0x00000004u; - return content_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return content_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* CodeGeneratorResponse_File::release_content() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content) @@ -1730,7 +1724,7 @@ inline bool CodeGeneratorResponse::has_error() const { return _internal_has_error(); } inline void CodeGeneratorResponse::clear_error() { - error_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + error_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& CodeGeneratorResponse::error() const { @@ -1750,31 +1744,30 @@ inline const std::string& CodeGeneratorResponse::_internal_error() const { } inline void CodeGeneratorResponse::_internal_set_error(const std::string& value) { _has_bits_[0] |= 0x00000001u; - error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void CodeGeneratorResponse::set_error(std::string&& value) { _has_bits_[0] |= 0x00000001u; error_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - error_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) } inline std::string* CodeGeneratorResponse::_internal_mutable_error() { _has_bits_[0] |= 0x00000001u; - return error_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return error_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* CodeGeneratorResponse::release_error() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error) diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index c3d96555bd..8998e1bd78 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -254,14 +255,14 @@ std::string ToCamelCase(const std::string& input, bool lower_first) { std::string result; result.reserve(input.size()); - for (int i = 0; i < input.size(); i++) { - if (input[i] == '_') { + for (char character : input) { + if (character == '_') { capitalize_next = true; } else if (capitalize_next) { - result.push_back(ToUpper(input[i])); + result.push_back(ToUpper(character)); capitalize_next = false; } else { - result.push_back(input[i]); + result.push_back(character); } } @@ -278,14 +279,14 @@ std::string ToJsonName(const std::string& input) { std::string result; result.reserve(input.size()); - for (int i = 0; i < input.size(); i++) { - if (input[i] == '_') { + for (char character : input) { + if (character == '_') { capitalize_next = true; } else if (capitalize_next) { - result.push_back(ToUpper(input[i])); + result.push_back(ToUpper(character)); capitalize_next = false; } else { - result.push_back(input[i]); + result.push_back(character); } } @@ -297,14 +298,14 @@ std::string EnumValueToPascalCase(const std::string& input) { std::string result; result.reserve(input.size()); - for (int i = 0; i < input.size(); i++) { - if (input[i] == '_') { + for (char character : input) { + if (character == '_') { next_upper = true; } else { if (next_upper) { - result.push_back(ToUpper(input[i])); + result.push_back(ToUpper(character)); } else { - result.push_back(ToLower(input[i])); + result.push_back(ToLower(character)); } next_upper = false; } @@ -318,9 +319,9 @@ class PrefixRemover { public: PrefixRemover(StringPiece prefix) { // Strip underscores and lower-case the prefix. - for (int i = 0; i < prefix.size(); i++) { - if (prefix[i] != '_') { - prefix_ += ascii_tolower(prefix[i]); + for (char character : prefix) { + if (character != '_') { + prefix_ += ascii_tolower(character); } } } @@ -471,16 +472,15 @@ std::set* NewAllowedProto3Extendee() { const char* kOptionNames[] = { "FileOptions", "MessageOptions", "FieldOptions", "EnumOptions", "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"}; - for (int i = 0; i < GOOGLE_ARRAYSIZE(kOptionNames); ++i) { + for (const char* option_name : kOptionNames) { // descriptor.proto has a different package name in opensource. We allow // both so the opensource protocol compiler can also compile internal // proto3 files with custom options. See: b/27567912 allowed_proto3_extendees->insert(std::string("google.protobuf.") + - kOptionNames[i]); + option_name); // Split the word to trick the opensource processing scripts so they // will keep the original package name. - allowed_proto3_extendees->insert(std::string("proto") + "2." + - kOptionNames[i]); + allowed_proto3_extendees->insert(std::string("proto") + "2." + option_name); } return allowed_proto3_extendees; } @@ -1571,8 +1571,7 @@ void DescriptorPool::FindAllExtensions( std::vector numbers; if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(), &numbers)) { - for (int i = 0; i < numbers.size(); ++i) { - int number = numbers[i]; + for (int number : numbers) { if (tables_->FindExtension(extendee, number) == nullptr) { TryFindExtensionInFallbackDatabase(extendee, number); } @@ -2279,34 +2278,34 @@ bool RetrieveOptionsAssumingRightPool( const Reflection* reflection = options.GetReflection(); std::vector fields; reflection->ListFields(options, &fields); - for (int i = 0; i < fields.size(); i++) { + for (const FieldDescriptor* field : fields) { int count = 1; bool repeated = false; - if (fields[i]->is_repeated()) { - count = reflection->FieldSize(options, fields[i]); + if (field->is_repeated()) { + count = reflection->FieldSize(options, field); repeated = true; } for (int j = 0; j < count; j++) { std::string fieldval; - if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { std::string tmp; TextFormat::Printer printer; printer.SetInitialIndentLevel(depth + 1); - printer.PrintFieldValueToString(options, fields[i], repeated ? j : -1, + printer.PrintFieldValueToString(options, field, repeated ? j : -1, &tmp); fieldval.append("{\n"); fieldval.append(tmp); fieldval.append(depth * 2, ' '); fieldval.append("}"); } else { - TextFormat::PrintFieldValueToString(options, fields[i], - repeated ? j : -1, &fieldval); + TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1, + &fieldval); } std::string name; - if (fields[i]->is_extension()) { - name = "(." + fields[i]->full_name() + ")"; + if (field->is_extension()) { + name = "(." + field->full_name() + ")"; } else { - name = fields[i]->name(); + name = field->name(); } option_entries->push_back(name + " = " + fieldval); } @@ -2363,9 +2362,8 @@ bool FormatLineOptions(int depth, const Message& options, std::string prefix(depth * 2, ' '); std::vector all_options; if (RetrieveOptions(depth, options, pool, &all_options)) { - for (int i = 0; i < all_options.size(); i++) { - strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, - all_options[i]); + for (const std::string& option : all_options) { + strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, option); } } return !all_options.empty(); @@ -2395,8 +2393,9 @@ class SourceLocationCommentPrinter { void AddPreComment(std::string* output) { if (have_source_loc_) { // Detached leading comments. - for (int i = 0; i < source_loc_.leading_detached_comments.size(); ++i) { - *output += FormatComment(source_loc_.leading_detached_comments[i]); + for (const std::string& leading_detached_comment : + source_loc_.leading_detached_comments) { + *output += FormatComment(leading_detached_comment); *output += "\n"; } // Attached leading comments. @@ -2418,8 +2417,7 @@ class SourceLocationCommentPrinter { StripWhitespace(&stripped_comment); std::vector lines = Split(stripped_comment, "\n"); std::string output; - for (int i = 0; i < lines.size(); ++i) { - const std::string& line = lines[i]; + for (const std::string& line : lines) { strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line); } return output; @@ -3440,7 +3438,6 @@ class DescriptorBuilder { void SetUInt64(int number, uint64 value, FieldDescriptor::Type type, UnknownFieldSet* unknown_fields); - // A helper function that adds an error at the specified location of the // option we're currently interpreting, and returns false. bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location, @@ -3866,13 +3863,13 @@ Symbol DescriptorBuilder::LookupSymbol( static bool ValidateQualifiedName(StringPiece name) { bool last_was_period = false; - for (int i = 0; i < name.size(); i++) { + for (char character : name) { // I don't trust isalnum() due to locales. :( - if (('a' <= name[i] && name[i] <= 'z') || - ('A' <= name[i] && name[i] <= 'Z') || - ('0' <= name[i] && name[i] <= '9') || (name[i] == '_')) { + if (('a' <= character && character <= 'z') || + ('A' <= character && character <= 'Z') || + ('0' <= character && character <= '9') || (character == '_')) { last_was_period = false; - } else if (name[i] == '.') { + } else if (character == '.') { if (last_was_period) return false; last_was_period = true; } else { @@ -4052,7 +4049,8 @@ bool DescriptorBuilder::AddSymbol(const std::string& full_name, // Symbol seems to have been defined in a different file. AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "\"" + full_name + "\" is already defined in file \"" + - other_file->name() + "\"."); + (other_file == nullptr ? "null" : other_file->name()) + + "\"."); } return false; } @@ -4095,11 +4093,11 @@ void DescriptorBuilder::ValidateSymbolName(const std::string& name, AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "Missing name."); } else { - for (int i = 0; i < name.size(); i++) { + for (char character : name) { // I don't trust isalnum() due to locales. :( - if ((name[i] < 'a' || 'z' < name[i]) && - (name[i] < 'A' || 'Z' < name[i]) && - (name[i] < '0' || '9' < name[i]) && (name[i] != '_')) { + if ((character < 'a' || 'z' < character) && + (character < 'A' || 'Z' < character) && + (character < '0' || '9' < character) && (character != '_')) { AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, "\"" + name + "\" is not a valid identifier."); } @@ -5944,12 +5942,12 @@ void DescriptorBuilder::ValidateProto3(FileDescriptor* file, static std::string ToLowercaseWithoutUnderscores(const std::string& name) { std::string result; - for (int i = 0; i < name.size(); ++i) { - if (name[i] != '_') { - if (name[i] >= 'A' && name[i] <= 'Z') { - result.push_back(name[i] - 'A' + 'a'); + for (char character : name) { + if (character != '_') { + if (character >= 'A' && character <= 'Z') { + result.push_back(character - 'A' + 'a'); } else { - result.push_back(name[i]); + result.push_back(character); } } } @@ -6382,7 +6380,6 @@ DescriptorBuilder::OptionInterpreter::OptionInterpreter( DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {} - bool DescriptorBuilder::OptionInterpreter::InterpretOptions( OptionsToInterpret* options_to_interpret) { // Note that these may be in different pools, so we can't use the same @@ -6463,7 +6460,6 @@ bool DescriptorBuilder::OptionInterpreter::InterpretOptions( } } - return !failed; } @@ -7066,6 +7062,18 @@ class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder public: DescriptorBuilder* builder_; + const Descriptor* FindAnyType(const Message& message, + const std::string& prefix, + const std::string& name) const override { + if (prefix != internal::kTypeGoogleApisComPrefix && + prefix != internal::kTypeGoogleProdComPrefix) { + return nullptr; + } + assert_mutex_held(builder_->pool_); + Symbol result = builder_->FindSymbol(name); + return result.type == Symbol::MESSAGE ? result.descriptor : nullptr; + } + const FieldDescriptor* FindExtension(Message* message, const std::string& name) const override { assert_mutex_held(builder_->pool_); diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 422adf8201..f12a8583ac 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1604,17 +1604,17 @@ FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_package()) { - package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_package(), + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_package(), GetArena()); } syntax_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_syntax()) { - syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_syntax(), + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_syntax(), GetArena()); } if (from._internal_has_options()) { @@ -2806,7 +2806,7 @@ DescriptorProto::DescriptorProto(const DescriptorProto& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_options()) { @@ -3585,27 +3585,27 @@ FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } extendee_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_extendee()) { - extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_extendee(), + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_extendee(), GetArena()); } type_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_type_name()) { - type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_type_name(), + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_name(), GetArena()); } default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_default_value()) { - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_default_value(), + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_default_value(), GetArena()); } json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_json_name()) { - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_json_name(), + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_json_name(), GetArena()); } if (from._internal_has_options()) { @@ -4187,7 +4187,7 @@ OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_options()) { @@ -4724,7 +4724,7 @@ EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_options()) { @@ -5102,7 +5102,7 @@ EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProt _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_options()) { @@ -5416,7 +5416,7 @@ ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& fro _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_options()) { @@ -5736,17 +5736,17 @@ MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } input_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_input_type()) { - input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_input_type(), + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_input_type(), GetArena()); } output_type_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_output_type()) { - output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_output_type(), + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_output_type(), GetArena()); } if (from._internal_has_options()) { @@ -6209,52 +6209,52 @@ FileOptions::FileOptions(const FileOptions& from) _extensions_.MergeFrom(from._extensions_); java_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_java_package()) { - java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_java_package(), + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_java_package(), GetArena()); } java_outer_classname_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_java_outer_classname()) { - java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_java_outer_classname(), + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_java_outer_classname(), GetArena()); } go_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_go_package()) { - go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_go_package(), + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_go_package(), GetArena()); } objc_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_objc_class_prefix()) { - objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_objc_class_prefix(), + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_objc_class_prefix(), GetArena()); } csharp_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_csharp_namespace()) { - csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_csharp_namespace(), + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_csharp_namespace(), GetArena()); } swift_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_swift_prefix()) { - swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_swift_prefix(), + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_swift_prefix(), GetArena()); } php_class_prefix_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_php_class_prefix()) { - php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_php_class_prefix(), + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_class_prefix(), GetArena()); } php_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_php_namespace()) { - php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_php_namespace(), + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_namespace(), GetArena()); } php_metadata_namespace_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_php_metadata_namespace()) { - php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_php_metadata_namespace(), + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_php_metadata_namespace(), GetArena()); } ruby_package_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_ruby_package()) { - ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_ruby_package(), + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_ruby_package(), GetArena()); } ::memcpy(&java_multiple_files_, &from.java_multiple_files_, @@ -9261,7 +9261,7 @@ UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOp _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_part_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_name_part()) { - name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name_part(), + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name_part(), GetArena()); } is_extension_ = from.is_extension_; @@ -9548,17 +9548,17 @@ UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); identifier_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_identifier_value()) { - identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_identifier_value(), + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_identifier_value(), GetArena()); } string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_string_value()) { - string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_string_value(), + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_string_value(), GetArena()); } aggregate_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_aggregate_value()) { - aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_aggregate_value(), + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_aggregate_value(), GetArena()); } ::memcpy(&positive_int_value_, &from.positive_int_value_, @@ -9983,12 +9983,12 @@ SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); leading_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_leading_comments()) { - leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_leading_comments(), + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_leading_comments(), GetArena()); } trailing_comments_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_trailing_comments()) { - trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_trailing_comments(), + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_trailing_comments(), GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location) @@ -10573,7 +10573,7 @@ GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(const GeneratedCodeIn _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); source_file_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (from._internal_has_source_file()) { - source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_source_file(), + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_source_file(), GetArena()); } ::memcpy(&begin_, &from.begin_, diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index feaae115cb..20c412aefe 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -6623,7 +6622,7 @@ inline bool FileDescriptorProto::has_name() const { return _internal_has_name(); } inline void FileDescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& FileDescriptorProto::name() const { @@ -6643,31 +6642,30 @@ inline const std::string& FileDescriptorProto::_internal_name() const { } inline void FileDescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileDescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.name) } inline void FileDescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) } inline void FileDescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name) } inline std::string* FileDescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name) @@ -6697,7 +6695,7 @@ inline bool FileDescriptorProto::has_package() const { return _internal_has_package(); } inline void FileDescriptorProto::clear_package() { - package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + package_.ClearToEmpty(); _has_bits_[0] &= ~0x00000002u; } inline const std::string& FileDescriptorProto::package() const { @@ -6717,31 +6715,30 @@ inline const std::string& FileDescriptorProto::_internal_package() const { } inline void FileDescriptorProto::_internal_set_package(const std::string& value) { _has_bits_[0] |= 0x00000002u; - package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileDescriptorProto::set_package(std::string&& value) { _has_bits_[0] |= 0x00000002u; package_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.package) } inline void FileDescriptorProto::set_package(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000002u; - package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package) } inline void FileDescriptorProto::set_package(const char* value, size_t size) { _has_bits_[0] |= 0x00000002u; - package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package) } inline std::string* FileDescriptorProto::_internal_mutable_package() { _has_bits_[0] |= 0x00000002u; - return package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileDescriptorProto::release_package() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package) @@ -7261,7 +7258,7 @@ inline bool FileDescriptorProto::has_syntax() const { return _internal_has_syntax(); } inline void FileDescriptorProto::clear_syntax() { - syntax_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + syntax_.ClearToEmpty(); _has_bits_[0] &= ~0x00000004u; } inline const std::string& FileDescriptorProto::syntax() const { @@ -7281,31 +7278,30 @@ inline const std::string& FileDescriptorProto::_internal_syntax() const { } inline void FileDescriptorProto::_internal_set_syntax(const std::string& value) { _has_bits_[0] |= 0x00000004u; - syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileDescriptorProto::set_syntax(std::string&& value) { _has_bits_[0] |= 0x00000004u; syntax_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.syntax) } inline void FileDescriptorProto::set_syntax(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000004u; - syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax) } inline void FileDescriptorProto::set_syntax(const char* value, size_t size) { _has_bits_[0] |= 0x00000004u; - syntax_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax) } inline std::string* FileDescriptorProto::_internal_mutable_syntax() { _has_bits_[0] |= 0x00000004u; - return syntax_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return syntax_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileDescriptorProto::release_syntax() { // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax) @@ -7542,7 +7538,7 @@ inline bool DescriptorProto::has_name() const { return _internal_has_name(); } inline void DescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& DescriptorProto::name() const { @@ -7562,31 +7558,30 @@ inline const std::string& DescriptorProto::_internal_name() const { } inline void DescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void DescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.DescriptorProto.name) } inline void DescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name) } inline void DescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name) } inline std::string* DescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* DescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name) @@ -8093,7 +8088,7 @@ inline bool FieldDescriptorProto::has_name() const { return _internal_has_name(); } inline void FieldDescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& FieldDescriptorProto::name() const { @@ -8113,31 +8108,30 @@ inline const std::string& FieldDescriptorProto::_internal_name() const { } inline void FieldDescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FieldDescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.name) } inline void FieldDescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name) } inline void FieldDescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name) } inline std::string* FieldDescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FieldDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name) @@ -8253,7 +8247,7 @@ inline bool FieldDescriptorProto::has_type_name() const { return _internal_has_type_name(); } inline void FieldDescriptorProto::clear_type_name() { - type_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + type_name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000004u; } inline const std::string& FieldDescriptorProto::type_name() const { @@ -8273,31 +8267,30 @@ inline const std::string& FieldDescriptorProto::_internal_type_name() const { } inline void FieldDescriptorProto::_internal_set_type_name(const std::string& value) { _has_bits_[0] |= 0x00000004u; - type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FieldDescriptorProto::set_type_name(std::string&& value) { _has_bits_[0] |= 0x00000004u; type_name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.type_name) } inline void FieldDescriptorProto::set_type_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000004u; - type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name) } inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000004u; - type_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name) } inline std::string* FieldDescriptorProto::_internal_mutable_type_name() { _has_bits_[0] |= 0x00000004u; - return type_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return type_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FieldDescriptorProto::release_type_name() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name) @@ -8327,7 +8320,7 @@ inline bool FieldDescriptorProto::has_extendee() const { return _internal_has_extendee(); } inline void FieldDescriptorProto::clear_extendee() { - extendee_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + extendee_.ClearToEmpty(); _has_bits_[0] &= ~0x00000002u; } inline const std::string& FieldDescriptorProto::extendee() const { @@ -8347,31 +8340,30 @@ inline const std::string& FieldDescriptorProto::_internal_extendee() const { } inline void FieldDescriptorProto::_internal_set_extendee(const std::string& value) { _has_bits_[0] |= 0x00000002u; - extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FieldDescriptorProto::set_extendee(std::string&& value) { _has_bits_[0] |= 0x00000002u; extendee_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.extendee) } inline void FieldDescriptorProto::set_extendee(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000002u; - extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee) } inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) { _has_bits_[0] |= 0x00000002u; - extendee_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee) } inline std::string* FieldDescriptorProto::_internal_mutable_extendee() { _has_bits_[0] |= 0x00000002u; - return extendee_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return extendee_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FieldDescriptorProto::release_extendee() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee) @@ -8401,7 +8393,7 @@ inline bool FieldDescriptorProto::has_default_value() const { return _internal_has_default_value(); } inline void FieldDescriptorProto::clear_default_value() { - default_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + default_value_.ClearToEmpty(); _has_bits_[0] &= ~0x00000008u; } inline const std::string& FieldDescriptorProto::default_value() const { @@ -8421,31 +8413,30 @@ inline const std::string& FieldDescriptorProto::_internal_default_value() const } inline void FieldDescriptorProto::_internal_set_default_value(const std::string& value) { _has_bits_[0] |= 0x00000008u; - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FieldDescriptorProto::set_default_value(std::string&& value) { _has_bits_[0] |= 0x00000008u; default_value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.default_value) } inline void FieldDescriptorProto::set_default_value(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000008u; - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value) } inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) { _has_bits_[0] |= 0x00000008u; - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value) } inline std::string* FieldDescriptorProto::_internal_mutable_default_value() { _has_bits_[0] |= 0x00000008u; - return default_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return default_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FieldDescriptorProto::release_default_value() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value) @@ -8503,7 +8494,7 @@ inline bool FieldDescriptorProto::has_json_name() const { return _internal_has_json_name(); } inline void FieldDescriptorProto::clear_json_name() { - json_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + json_name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000010u; } inline const std::string& FieldDescriptorProto::json_name() const { @@ -8523,31 +8514,30 @@ inline const std::string& FieldDescriptorProto::_internal_json_name() const { } inline void FieldDescriptorProto::_internal_set_json_name(const std::string& value) { _has_bits_[0] |= 0x00000010u; - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FieldDescriptorProto::set_json_name(std::string&& value) { _has_bits_[0] |= 0x00000010u; json_name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.json_name) } inline void FieldDescriptorProto::set_json_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000010u; - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name) } inline void FieldDescriptorProto::set_json_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000010u; - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name) } inline std::string* FieldDescriptorProto::_internal_mutable_json_name() { _has_bits_[0] |= 0x00000010u; - return json_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return json_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FieldDescriptorProto::release_json_name() { // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name) @@ -8692,7 +8682,7 @@ inline bool OneofDescriptorProto::has_name() const { return _internal_has_name(); } inline void OneofDescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& OneofDescriptorProto::name() const { @@ -8712,31 +8702,30 @@ inline const std::string& OneofDescriptorProto::_internal_name() const { } inline void OneofDescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void OneofDescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.OneofDescriptorProto.name) } inline void OneofDescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name) } inline void OneofDescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name) } inline std::string* OneofDescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* OneofDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name) @@ -8913,7 +8902,7 @@ inline bool EnumDescriptorProto::has_name() const { return _internal_has_name(); } inline void EnumDescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& EnumDescriptorProto::name() const { @@ -8933,31 +8922,30 @@ inline const std::string& EnumDescriptorProto::_internal_name() const { } inline void EnumDescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void EnumDescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumDescriptorProto.name) } inline void EnumDescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) } inline void EnumDescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) } inline std::string* EnumDescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* EnumDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name) @@ -9226,7 +9214,7 @@ inline bool EnumValueDescriptorProto::has_name() const { return _internal_has_name(); } inline void EnumValueDescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& EnumValueDescriptorProto::name() const { @@ -9246,31 +9234,30 @@ inline const std::string& EnumValueDescriptorProto::_internal_name() const { } inline void EnumValueDescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void EnumValueDescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValueDescriptorProto.name) } inline void EnumValueDescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name) } inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name) } inline std::string* EnumValueDescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* EnumValueDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name) @@ -9415,7 +9402,7 @@ inline bool ServiceDescriptorProto::has_name() const { return _internal_has_name(); } inline void ServiceDescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& ServiceDescriptorProto::name() const { @@ -9435,31 +9422,30 @@ inline const std::string& ServiceDescriptorProto::_internal_name() const { } inline void ServiceDescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void ServiceDescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.ServiceDescriptorProto.name) } inline void ServiceDescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name) } inline void ServiceDescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name) } inline std::string* ServiceDescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* ServiceDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name) @@ -9615,7 +9601,7 @@ inline bool MethodDescriptorProto::has_name() const { return _internal_has_name(); } inline void MethodDescriptorProto::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& MethodDescriptorProto::name() const { @@ -9635,31 +9621,30 @@ inline const std::string& MethodDescriptorProto::_internal_name() const { } inline void MethodDescriptorProto::_internal_set_name(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void MethodDescriptorProto::set_name(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.name) } inline void MethodDescriptorProto::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name) } inline void MethodDescriptorProto::set_name(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name) } inline std::string* MethodDescriptorProto::_internal_mutable_name() { _has_bits_[0] |= 0x00000001u; - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* MethodDescriptorProto::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name) @@ -9689,7 +9674,7 @@ inline bool MethodDescriptorProto::has_input_type() const { return _internal_has_input_type(); } inline void MethodDescriptorProto::clear_input_type() { - input_type_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + input_type_.ClearToEmpty(); _has_bits_[0] &= ~0x00000002u; } inline const std::string& MethodDescriptorProto::input_type() const { @@ -9709,31 +9694,30 @@ inline const std::string& MethodDescriptorProto::_internal_input_type() const { } inline void MethodDescriptorProto::_internal_set_input_type(const std::string& value) { _has_bits_[0] |= 0x00000002u; - input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void MethodDescriptorProto::set_input_type(std::string&& value) { _has_bits_[0] |= 0x00000002u; input_type_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.input_type) } inline void MethodDescriptorProto::set_input_type(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000002u; - input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type) } inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) { _has_bits_[0] |= 0x00000002u; - input_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type) } inline std::string* MethodDescriptorProto::_internal_mutable_input_type() { _has_bits_[0] |= 0x00000002u; - return input_type_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return input_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* MethodDescriptorProto::release_input_type() { // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type) @@ -9763,7 +9747,7 @@ inline bool MethodDescriptorProto::has_output_type() const { return _internal_has_output_type(); } inline void MethodDescriptorProto::clear_output_type() { - output_type_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + output_type_.ClearToEmpty(); _has_bits_[0] &= ~0x00000004u; } inline const std::string& MethodDescriptorProto::output_type() const { @@ -9783,31 +9767,30 @@ inline const std::string& MethodDescriptorProto::_internal_output_type() const { } inline void MethodDescriptorProto::_internal_set_output_type(const std::string& value) { _has_bits_[0] |= 0x00000004u; - output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void MethodDescriptorProto::set_output_type(std::string&& value) { _has_bits_[0] |= 0x00000004u; output_type_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.output_type) } inline void MethodDescriptorProto::set_output_type(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000004u; - output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type) } inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) { _has_bits_[0] |= 0x00000004u; - output_type_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type) } inline std::string* MethodDescriptorProto::_internal_mutable_output_type() { _has_bits_[0] |= 0x00000004u; - return output_type_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return output_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* MethodDescriptorProto::release_output_type() { // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type) @@ -9980,7 +9963,7 @@ inline bool FileOptions::has_java_package() const { return _internal_has_java_package(); } inline void FileOptions::clear_java_package() { - java_package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + java_package_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& FileOptions::java_package() const { @@ -10000,31 +9983,30 @@ inline const std::string& FileOptions::_internal_java_package() const { } inline void FileOptions::_internal_set_java_package(const std::string& value) { _has_bits_[0] |= 0x00000001u; - java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_java_package(std::string&& value) { _has_bits_[0] |= 0x00000001u; java_package_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_package) } inline void FileOptions::set_java_package(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package) } inline void FileOptions::set_java_package(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - java_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package) } inline std::string* FileOptions::_internal_mutable_java_package() { _has_bits_[0] |= 0x00000001u; - return java_package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return java_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_java_package() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package) @@ -10054,7 +10036,7 @@ inline bool FileOptions::has_java_outer_classname() const { return _internal_has_java_outer_classname(); } inline void FileOptions::clear_java_outer_classname() { - java_outer_classname_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + java_outer_classname_.ClearToEmpty(); _has_bits_[0] &= ~0x00000002u; } inline const std::string& FileOptions::java_outer_classname() const { @@ -10074,31 +10056,30 @@ inline const std::string& FileOptions::_internal_java_outer_classname() const { } inline void FileOptions::_internal_set_java_outer_classname(const std::string& value) { _has_bits_[0] |= 0x00000002u; - java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_java_outer_classname(std::string&& value) { _has_bits_[0] |= 0x00000002u; java_outer_classname_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_outer_classname) } inline void FileOptions::set_java_outer_classname(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000002u; - java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname) } inline void FileOptions::set_java_outer_classname(const char* value, size_t size) { _has_bits_[0] |= 0x00000002u; - java_outer_classname_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname) } inline std::string* FileOptions::_internal_mutable_java_outer_classname() { _has_bits_[0] |= 0x00000002u; - return java_outer_classname_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return java_outer_classname_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_java_outer_classname() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname) @@ -10241,7 +10222,7 @@ inline bool FileOptions::has_go_package() const { return _internal_has_go_package(); } inline void FileOptions::clear_go_package() { - go_package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + go_package_.ClearToEmpty(); _has_bits_[0] &= ~0x00000004u; } inline const std::string& FileOptions::go_package() const { @@ -10261,31 +10242,30 @@ inline const std::string& FileOptions::_internal_go_package() const { } inline void FileOptions::_internal_set_go_package(const std::string& value) { _has_bits_[0] |= 0x00000004u; - go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_go_package(std::string&& value) { _has_bits_[0] |= 0x00000004u; go_package_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.go_package) } inline void FileOptions::set_go_package(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000004u; - go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package) } inline void FileOptions::set_go_package(const char* value, size_t size) { _has_bits_[0] |= 0x00000004u; - go_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package) } inline std::string* FileOptions::_internal_mutable_go_package() { _has_bits_[0] |= 0x00000004u; - return go_package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return go_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_go_package() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package) @@ -10483,7 +10463,7 @@ inline bool FileOptions::has_objc_class_prefix() const { return _internal_has_objc_class_prefix(); } inline void FileOptions::clear_objc_class_prefix() { - objc_class_prefix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + objc_class_prefix_.ClearToEmpty(); _has_bits_[0] &= ~0x00000008u; } inline const std::string& FileOptions::objc_class_prefix() const { @@ -10503,31 +10483,30 @@ inline const std::string& FileOptions::_internal_objc_class_prefix() const { } inline void FileOptions::_internal_set_objc_class_prefix(const std::string& value) { _has_bits_[0] |= 0x00000008u; - objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_objc_class_prefix(std::string&& value) { _has_bits_[0] |= 0x00000008u; objc_class_prefix_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.objc_class_prefix) } inline void FileOptions::set_objc_class_prefix(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000008u; - objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix) } inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) { _has_bits_[0] |= 0x00000008u; - objc_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix) } inline std::string* FileOptions::_internal_mutable_objc_class_prefix() { _has_bits_[0] |= 0x00000008u; - return objc_class_prefix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return objc_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_objc_class_prefix() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix) @@ -10557,7 +10536,7 @@ inline bool FileOptions::has_csharp_namespace() const { return _internal_has_csharp_namespace(); } inline void FileOptions::clear_csharp_namespace() { - csharp_namespace_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + csharp_namespace_.ClearToEmpty(); _has_bits_[0] &= ~0x00000010u; } inline const std::string& FileOptions::csharp_namespace() const { @@ -10577,31 +10556,30 @@ inline const std::string& FileOptions::_internal_csharp_namespace() const { } inline void FileOptions::_internal_set_csharp_namespace(const std::string& value) { _has_bits_[0] |= 0x00000010u; - csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_csharp_namespace(std::string&& value) { _has_bits_[0] |= 0x00000010u; csharp_namespace_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.csharp_namespace) } inline void FileOptions::set_csharp_namespace(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000010u; - csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace) } inline void FileOptions::set_csharp_namespace(const char* value, size_t size) { _has_bits_[0] |= 0x00000010u; - csharp_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace) } inline std::string* FileOptions::_internal_mutable_csharp_namespace() { _has_bits_[0] |= 0x00000010u; - return csharp_namespace_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return csharp_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_csharp_namespace() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace) @@ -10631,7 +10609,7 @@ inline bool FileOptions::has_swift_prefix() const { return _internal_has_swift_prefix(); } inline void FileOptions::clear_swift_prefix() { - swift_prefix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swift_prefix_.ClearToEmpty(); _has_bits_[0] &= ~0x00000020u; } inline const std::string& FileOptions::swift_prefix() const { @@ -10651,31 +10629,30 @@ inline const std::string& FileOptions::_internal_swift_prefix() const { } inline void FileOptions::_internal_set_swift_prefix(const std::string& value) { _has_bits_[0] |= 0x00000020u; - swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_swift_prefix(std::string&& value) { _has_bits_[0] |= 0x00000020u; swift_prefix_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.swift_prefix) } inline void FileOptions::set_swift_prefix(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000020u; - swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.swift_prefix) } inline void FileOptions::set_swift_prefix(const char* value, size_t size) { _has_bits_[0] |= 0x00000020u; - swift_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.swift_prefix) } inline std::string* FileOptions::_internal_mutable_swift_prefix() { _has_bits_[0] |= 0x00000020u; - return swift_prefix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return swift_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_swift_prefix() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.swift_prefix) @@ -10705,7 +10682,7 @@ inline bool FileOptions::has_php_class_prefix() const { return _internal_has_php_class_prefix(); } inline void FileOptions::clear_php_class_prefix() { - php_class_prefix_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + php_class_prefix_.ClearToEmpty(); _has_bits_[0] &= ~0x00000040u; } inline const std::string& FileOptions::php_class_prefix() const { @@ -10725,31 +10702,30 @@ inline const std::string& FileOptions::_internal_php_class_prefix() const { } inline void FileOptions::_internal_set_php_class_prefix(const std::string& value) { _has_bits_[0] |= 0x00000040u; - php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_php_class_prefix(std::string&& value) { _has_bits_[0] |= 0x00000040u; php_class_prefix_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_class_prefix) } inline void FileOptions::set_php_class_prefix(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000040u; - php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_class_prefix) } inline void FileOptions::set_php_class_prefix(const char* value, size_t size) { _has_bits_[0] |= 0x00000040u; - php_class_prefix_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_class_prefix) } inline std::string* FileOptions::_internal_mutable_php_class_prefix() { _has_bits_[0] |= 0x00000040u; - return php_class_prefix_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return php_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_php_class_prefix() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_class_prefix) @@ -10779,7 +10755,7 @@ inline bool FileOptions::has_php_namespace() const { return _internal_has_php_namespace(); } inline void FileOptions::clear_php_namespace() { - php_namespace_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + php_namespace_.ClearToEmpty(); _has_bits_[0] &= ~0x00000080u; } inline const std::string& FileOptions::php_namespace() const { @@ -10799,31 +10775,30 @@ inline const std::string& FileOptions::_internal_php_namespace() const { } inline void FileOptions::_internal_set_php_namespace(const std::string& value) { _has_bits_[0] |= 0x00000080u; - php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_php_namespace(std::string&& value) { _has_bits_[0] |= 0x00000080u; php_namespace_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_namespace) } inline void FileOptions::set_php_namespace(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000080u; - php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_namespace) } inline void FileOptions::set_php_namespace(const char* value, size_t size) { _has_bits_[0] |= 0x00000080u; - php_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_namespace) } inline std::string* FileOptions::_internal_mutable_php_namespace() { _has_bits_[0] |= 0x00000080u; - return php_namespace_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return php_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_php_namespace() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace) @@ -10853,7 +10828,7 @@ inline bool FileOptions::has_php_metadata_namespace() const { return _internal_has_php_metadata_namespace(); } inline void FileOptions::clear_php_metadata_namespace() { - php_metadata_namespace_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + php_metadata_namespace_.ClearToEmpty(); _has_bits_[0] &= ~0x00000100u; } inline const std::string& FileOptions::php_metadata_namespace() const { @@ -10873,31 +10848,30 @@ inline const std::string& FileOptions::_internal_php_metadata_namespace() const } inline void FileOptions::_internal_set_php_metadata_namespace(const std::string& value) { _has_bits_[0] |= 0x00000100u; - php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_php_metadata_namespace(std::string&& value) { _has_bits_[0] |= 0x00000100u; php_metadata_namespace_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_metadata_namespace) } inline void FileOptions::set_php_metadata_namespace(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000100u; - php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_metadata_namespace) } inline void FileOptions::set_php_metadata_namespace(const char* value, size_t size) { _has_bits_[0] |= 0x00000100u; - php_metadata_namespace_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_metadata_namespace) } inline std::string* FileOptions::_internal_mutable_php_metadata_namespace() { _has_bits_[0] |= 0x00000100u; - return php_metadata_namespace_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return php_metadata_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_php_metadata_namespace() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_metadata_namespace) @@ -10927,7 +10901,7 @@ inline bool FileOptions::has_ruby_package() const { return _internal_has_ruby_package(); } inline void FileOptions::clear_ruby_package() { - ruby_package_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ruby_package_.ClearToEmpty(); _has_bits_[0] &= ~0x00000200u; } inline const std::string& FileOptions::ruby_package() const { @@ -10947,31 +10921,30 @@ inline const std::string& FileOptions::_internal_ruby_package() const { } inline void FileOptions::_internal_set_ruby_package(const std::string& value) { _has_bits_[0] |= 0x00000200u; - ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void FileOptions::set_ruby_package(std::string&& value) { _has_bits_[0] |= 0x00000200u; ruby_package_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.ruby_package) } inline void FileOptions::set_ruby_package(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000200u; - ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.ruby_package) } inline void FileOptions::set_ruby_package(const char* value, size_t size) { _has_bits_[0] |= 0x00000200u; - ruby_package_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.ruby_package) } inline std::string* FileOptions::_internal_mutable_ruby_package() { _has_bits_[0] |= 0x00000200u; - return ruby_package_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return ruby_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* FileOptions::release_ruby_package() { // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.ruby_package) @@ -11796,7 +11769,7 @@ inline bool UninterpretedOption_NamePart::has_name_part() const { return _internal_has_name_part(); } inline void UninterpretedOption_NamePart::clear_name_part() { - name_part_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_part_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& UninterpretedOption_NamePart::name_part() const { @@ -11816,31 +11789,30 @@ inline const std::string& UninterpretedOption_NamePart::_internal_name_part() co } inline void UninterpretedOption_NamePart::_internal_set_name_part(const std::string& value) { _has_bits_[0] |= 0x00000001u; - name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void UninterpretedOption_NamePart::set_name_part(std::string&& value) { _has_bits_[0] |= 0x00000001u; name_part_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.NamePart.name_part) } inline void UninterpretedOption_NamePart::set_name_part(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part) } inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - name_part_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part) } inline std::string* UninterpretedOption_NamePart::_internal_mutable_name_part() { _has_bits_[0] |= 0x00000001u; - return name_part_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_part_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* UninterpretedOption_NamePart::release_name_part() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part) @@ -11941,7 +11913,7 @@ inline bool UninterpretedOption::has_identifier_value() const { return _internal_has_identifier_value(); } inline void UninterpretedOption::clear_identifier_value() { - identifier_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + identifier_value_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& UninterpretedOption::identifier_value() const { @@ -11961,31 +11933,30 @@ inline const std::string& UninterpretedOption::_internal_identifier_value() cons } inline void UninterpretedOption::_internal_set_identifier_value(const std::string& value) { _has_bits_[0] |= 0x00000001u; - identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void UninterpretedOption::set_identifier_value(std::string&& value) { _has_bits_[0] |= 0x00000001u; identifier_value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.identifier_value) } inline void UninterpretedOption::set_identifier_value(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value) } inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - identifier_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value) } inline std::string* UninterpretedOption::_internal_mutable_identifier_value() { _has_bits_[0] |= 0x00000001u; - return identifier_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return identifier_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* UninterpretedOption::release_identifier_value() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value) @@ -12099,7 +12070,7 @@ inline bool UninterpretedOption::has_string_value() const { return _internal_has_string_value(); } inline void UninterpretedOption::clear_string_value() { - string_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + string_value_.ClearToEmpty(); _has_bits_[0] &= ~0x00000002u; } inline const std::string& UninterpretedOption::string_value() const { @@ -12119,31 +12090,30 @@ inline const std::string& UninterpretedOption::_internal_string_value() const { } inline void UninterpretedOption::_internal_set_string_value(const std::string& value) { _has_bits_[0] |= 0x00000002u; - string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void UninterpretedOption::set_string_value(std::string&& value) { _has_bits_[0] |= 0x00000002u; string_value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.string_value) } inline void UninterpretedOption::set_string_value(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000002u; - string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value) } inline void UninterpretedOption::set_string_value(const void* value, size_t size) { _has_bits_[0] |= 0x00000002u; - string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value) } inline std::string* UninterpretedOption::_internal_mutable_string_value() { _has_bits_[0] |= 0x00000002u; - return string_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return string_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* UninterpretedOption::release_string_value() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value) @@ -12173,7 +12143,7 @@ inline bool UninterpretedOption::has_aggregate_value() const { return _internal_has_aggregate_value(); } inline void UninterpretedOption::clear_aggregate_value() { - aggregate_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + aggregate_value_.ClearToEmpty(); _has_bits_[0] &= ~0x00000004u; } inline const std::string& UninterpretedOption::aggregate_value() const { @@ -12193,31 +12163,30 @@ inline const std::string& UninterpretedOption::_internal_aggregate_value() const } inline void UninterpretedOption::_internal_set_aggregate_value(const std::string& value) { _has_bits_[0] |= 0x00000004u; - aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void UninterpretedOption::set_aggregate_value(std::string&& value) { _has_bits_[0] |= 0x00000004u; aggregate_value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.aggregate_value) } inline void UninterpretedOption::set_aggregate_value(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000004u; - aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value) } inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { _has_bits_[0] |= 0x00000004u; - aggregate_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value) } inline std::string* UninterpretedOption::_internal_mutable_aggregate_value() { _has_bits_[0] |= 0x00000004u; - return aggregate_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return aggregate_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* UninterpretedOption::release_aggregate_value() { // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value) @@ -12345,7 +12314,7 @@ inline bool SourceCodeInfo_Location::has_leading_comments() const { return _internal_has_leading_comments(); } inline void SourceCodeInfo_Location::clear_leading_comments() { - leading_comments_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + leading_comments_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& SourceCodeInfo_Location::leading_comments() const { @@ -12365,31 +12334,30 @@ inline const std::string& SourceCodeInfo_Location::_internal_leading_comments() } inline void SourceCodeInfo_Location::_internal_set_leading_comments(const std::string& value) { _has_bits_[0] |= 0x00000001u; - leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void SourceCodeInfo_Location::set_leading_comments(std::string&& value) { _has_bits_[0] |= 0x00000001u; leading_comments_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.leading_comments) } inline void SourceCodeInfo_Location::set_leading_comments(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments) } inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - leading_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments) } inline std::string* SourceCodeInfo_Location::_internal_mutable_leading_comments() { _has_bits_[0] |= 0x00000001u; - return leading_comments_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return leading_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* SourceCodeInfo_Location::release_leading_comments() { // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments) @@ -12419,7 +12387,7 @@ inline bool SourceCodeInfo_Location::has_trailing_comments() const { return _internal_has_trailing_comments(); } inline void SourceCodeInfo_Location::clear_trailing_comments() { - trailing_comments_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + trailing_comments_.ClearToEmpty(); _has_bits_[0] &= ~0x00000002u; } inline const std::string& SourceCodeInfo_Location::trailing_comments() const { @@ -12439,31 +12407,30 @@ inline const std::string& SourceCodeInfo_Location::_internal_trailing_comments() } inline void SourceCodeInfo_Location::_internal_set_trailing_comments(const std::string& value) { _has_bits_[0] |= 0x00000002u; - trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void SourceCodeInfo_Location::set_trailing_comments(std::string&& value) { _has_bits_[0] |= 0x00000002u; trailing_comments_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.trailing_comments) } inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000002u; - trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments) } inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { _has_bits_[0] |= 0x00000002u; - trailing_comments_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments) } inline std::string* SourceCodeInfo_Location::_internal_mutable_trailing_comments() { _has_bits_[0] |= 0x00000002u; - return trailing_comments_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return trailing_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* SourceCodeInfo_Location::release_trailing_comments() { // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments) @@ -12661,7 +12628,7 @@ inline bool GeneratedCodeInfo_Annotation::has_source_file() const { return _internal_has_source_file(); } inline void GeneratedCodeInfo_Annotation::clear_source_file() { - source_file_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + source_file_.ClearToEmpty(); _has_bits_[0] &= ~0x00000001u; } inline const std::string& GeneratedCodeInfo_Annotation::source_file() const { @@ -12681,31 +12648,30 @@ inline const std::string& GeneratedCodeInfo_Annotation::_internal_source_file() } inline void GeneratedCodeInfo_Annotation::_internal_set_source_file(const std::string& value) { _has_bits_[0] |= 0x00000001u; - source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void GeneratedCodeInfo_Annotation::set_source_file(std::string&& value) { _has_bits_[0] |= 0x00000001u; source_file_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value) { GOOGLE_DCHECK(value != nullptr); _has_bits_[0] |= 0x00000001u; - source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value, size_t size) { _has_bits_[0] |= 0x00000001u; - source_file_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file) } inline std::string* GeneratedCodeInfo_Annotation::_internal_mutable_source_file() { _has_bits_[0] |= 0x00000001u; - return source_file_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return source_file_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* GeneratedCodeInfo_Annotation::release_source_file() { // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file) diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index 151b36eab8..bb6f19ce37 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -37,7 +37,6 @@ #include #include -#include #include #include @@ -553,11 +552,9 @@ class EncodedDescriptorDatabase::DescriptorIndex { bool EncodedDescriptorDatabase::Add(const void* encoded_file_descriptor, int size) { - google::protobuf::Arena arena; - auto* file = google::protobuf::Arena::CreateMessage(&arena); - if (file->ParseFromArray(encoded_file_descriptor, size)) { - return index_->AddFile(*file, - std::make_pair(encoded_file_descriptor, size)); + FileDescriptorProto file; + if (file.ParseFromArray(encoded_file_descriptor, size)) { + return index_->AddFile(file, std::make_pair(encoded_file_descriptor, size)); } else { GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to " "EncodedDescriptorDatabase::Add()."; @@ -934,8 +931,8 @@ bool DescriptorPoolDatabase::FindAllExtensionNumbers( std::vector extensions; pool_.FindAllExtensions(extendee, &extensions); - for (int i = 0; i < extensions.size(); ++i) { - output->push_back(extensions[i]->number()); + for (const FieldDescriptor* extension : extensions) { + output->push_back(extension->number()); } return true; @@ -955,8 +952,8 @@ MergedDescriptorDatabase::~MergedDescriptorDatabase() {} bool MergedDescriptorDatabase::FindFileByName(const std::string& filename, FileDescriptorProto* output) { - for (int i = 0; i < sources_.size(); i++) { - if (sources_[i]->FindFileByName(filename, output)) { + for (DescriptorDatabase* source : sources_) { + if (source->FindFileByName(filename, output)) { return true; } } @@ -1013,8 +1010,8 @@ bool MergedDescriptorDatabase::FindAllExtensionNumbers( std::vector results; bool success = false; - for (int i = 0; i < sources_.size(); i++) { - if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) { + for (DescriptorDatabase* source : sources_) { + if (source->FindAllExtensionNumbers(extendee_type, &results)) { std::copy(results.begin(), results.end(), std::insert_iterator >(merged_results, merged_results.begin())); diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h index 10e60fc535..5fb593efc6 100644 --- a/src/google/protobuf/descriptor_database.h +++ b/src/google/protobuf/descriptor_database.h @@ -187,9 +187,6 @@ class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase { bool FindAllFileNames(std::vector* output) override; private: - // So that it can use DescriptorIndex. - friend class EncodedDescriptorDatabase; - // An index mapping file names, symbol names, and extension numbers to // some sort of values. template diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 278b07f9f2..331a0c5b6f 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -287,9 +288,8 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector { break; } - strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", - filename, element_name, location_name, - message); + strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", filename, + element_name, location_name, message); } }; @@ -3148,6 +3148,11 @@ TEST(CustomOptions, OptionsFromOtherFile) { FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + // We have to import the Any dependency. + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( &file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); @@ -3206,6 +3211,10 @@ TEST(CustomOptions, MessageOptionThreeFieldsSet) { FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( &file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); @@ -3283,6 +3292,10 @@ TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) { FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( &file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); @@ -3363,6 +3376,10 @@ TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) { FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( &file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); @@ -3463,6 +3480,10 @@ TEST(CustomOptions, AggregateOptions) { message_set_extension) .s()); + protobuf_unittest::AggregateMessageSetElement any_payload; + ASSERT_TRUE(file_options.any().UnpackTo(&any_payload)); + EXPECT_EQ("EmbeddedMessageSetElement", any_payload.s()); + // Simple tests for all the other types of annotations EXPECT_EQ("MessageAnnotation", msg->options().GetExtension(protobuf_unittest::msgopt).s()); @@ -3485,6 +3506,10 @@ TEST(CustomOptions, UnusedImportError) { FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); + FileDescriptorProto any_proto; + google::protobuf::Any::descriptor()->file()->CopyTo(&any_proto); + ASSERT_TRUE(pool.BuildFile(any_proto) != nullptr); + protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo( &file_proto); ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr); @@ -7182,8 +7207,8 @@ class SourceLocationTest : public testing::Test { static std::string PrintSourceLocation(const SourceLocation& loc) { return strings::Substitute("$0:$1-$2:$3", 1 + loc.start_line, - 1 + loc.start_column, 1 + loc.end_line, - 1 + loc.end_column); + 1 + loc.start_column, 1 + loc.end_line, + 1 + loc.end_column); } private: diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h index 8a9f7f0b5c..8f4434b834 100644 --- a/src/google/protobuf/duration.pb.h +++ b/src/google/protobuf/duration.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 3d9adc200b..e57d27f51a 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -432,15 +432,10 @@ void DynamicMessage::SharedCtor(bool lock_factory) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: if (!field->is_repeated()) { - const std::string* default_value; - if (is_prototype()) { - default_value = &field->default_value_string(); - } else { - default_value = &(reinterpret_cast( - type_info_->prototype->OffsetToPointer( - type_info_->offsets[i])) - ->Get()); - } + const std::string* default_value = + field->default_value_string().empty() + ? &internal::GetEmptyStringAlreadyInited() + : nullptr; ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr(); asp->UnsafeSetDefault(default_value); } else { @@ -523,10 +518,10 @@ DynamicMessage::~DynamicMessage() { default: case FieldOptions::STRING: { const std::string* default_value = - &(reinterpret_cast( - reinterpret_cast(type_info_->prototype) + - type_info_->offsets[i]) - ->Get()); + reinterpret_cast( + reinterpret_cast(type_info_->prototype) + + type_info_->offsets[i]) + ->GetPointer(); reinterpret_cast(field_ptr)->Destroy( default_value, NULL); break; @@ -583,10 +578,10 @@ DynamicMessage::~DynamicMessage() { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { const std::string* default_value = - &(reinterpret_cast( - type_info_->prototype->OffsetToPointer( - type_info_->offsets[i])) - ->Get()); + reinterpret_cast( + type_info_->prototype->OffsetToPointer( + type_info_->offsets[i])) + ->GetPointer(); reinterpret_cast(field_ptr)->Destroy(default_value, NULL); break; diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h index 5e6f0f9364..f1e5e9207f 100644 --- a/src/google/protobuf/empty.pb.h +++ b/src/google/protobuf/empty.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 0dcabb0f47..bfa1c42a88 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -192,14 +192,6 @@ ExtensionSet::ExtensionSet(Arena* arena) ? NULL : Arena::CreateArray(arena_, flat_capacity_)} {} -ExtensionSet::ExtensionSet() - : arena_(NULL), - flat_capacity_(0), - flat_size_(0), - map_{flat_capacity_ == 0 - ? NULL - : Arena::CreateArray(arena_, flat_capacity_)} {} - ExtensionSet::~ExtensionSet() { // Deletes all allocated extensions. if (arena_ == NULL) { diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index b30a9608af..b3a6e3a07b 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -173,7 +173,7 @@ class MessageSetFieldSkipper; // off to the ExtensionSet for parsing. Etc. class PROTOBUF_EXPORT ExtensionSet { public: - ExtensionSet(); + constexpr ExtensionSet(); explicit ExtensionSet(Arena* arena); ~ExtensionSet(); @@ -850,6 +850,9 @@ class PROTOBUF_EXPORT ExtensionSet { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet); }; +constexpr ExtensionSet::ExtensionSet() + : arena_(nullptr), flat_capacity_(0), flat_size_(0), map_{nullptr} {} + // These are just for convenience... inline void ExtensionSet::SetString(int number, FieldType type, std::string value, diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index 3e6ecefe01..2c299c15ca 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -46,13 +46,15 @@ #include #include #include - #include #include #include #include #include +// Must be included last. +#include + namespace google { namespace protobuf { @@ -1324,6 +1326,11 @@ TEST(ExtensionSetTest, BoolExtension) { EXPECT_TRUE(msg.GetExtension(protobuf_unittest::optional_bool_extension)); } +TEST(ExtensionSetTest, ConstInit) { + PROTOBUF_CONSTINIT static ExtensionSet set{}; + EXPECT_EQ(set.NumExtensions(), 0); +} + } // namespace } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h index 443785bffe..d74276776b 100644 --- a/src/google/protobuf/field_mask.pb.h +++ b/src/google/protobuf/field_mask.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index b854155ab9..e8b19c862b 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -62,7 +61,6 @@ using google::protobuf::internal::DescriptorTable; using google::protobuf::internal::ExtensionSet; using google::protobuf::internal::GenericTypeHandler; using google::protobuf::internal::GetEmptyString; -using google::protobuf::internal::InlinedStringField; using google::protobuf::internal::InternalMetadata; using google::protobuf::internal::LazyField; using google::protobuf::internal::MapFieldBase; @@ -313,15 +311,8 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - if (IsInlined(field)) { - const std::string* ptr = - &GetField(message, field).GetNoArena(); - total_size += StringSpaceUsedExcludingSelfLong(*ptr); - break; - } - const std::string* ptr = - &GetField(message, field).Get(); + GetField(message, field).GetPointer(); // Initially, the string points to the default value stored // in the prototype. Only count the string if it has been @@ -329,7 +320,7 @@ size_t Reflection::SpaceUsedLong(const Message& message) const { // Except oneof fields, those never point to a default instance, // and there is no default instance to point to. if (schema_.InRealOneof(field) || - ptr != &DefaultRaw(field).Get()) { + ptr != DefaultRaw(field).GetPointer()) { // string fields are represented by just a pointer, so also // include sizeof(string) as well. total_size += @@ -450,27 +441,27 @@ void Reflection::SwapField(Message* message1, Message* message2, Arena* arena1 = GetArena(message1); Arena* arena2 = GetArena(message2); - if (IsInlined(field)) { - InlinedStringField* string1 = - MutableRaw(message1, field); - InlinedStringField* string2 = - MutableRaw(message2, field); - string1->Swap(string2); - break; - } - ArenaStringPtr* string1 = MutableRaw(message1, field); ArenaStringPtr* string2 = MutableRaw(message2, field); const std::string* default_ptr = - &DefaultRaw(field).Get(); + DefaultRaw(field).GetPointer(); if (arena1 == arena2) { string1->Swap(string2, default_ptr, arena1); + } else if (string1->IsDefault(default_ptr) && + string2->IsDefault(default_ptr)) { + // Nothing to do. + } else if (string1->IsDefault(default_ptr)) { + string1->Set(default_ptr, string2->Get(), arena1); + string2->UnsafeSetDefault(default_ptr); + } else if (string2->IsDefault(default_ptr)) { + string2->Set(default_ptr, string1->Get(), arena2); + string1->UnsafeSetDefault(default_ptr); } else { - const std::string temp = string1->Get(); + std::string temp = string1->Get(); string1->Set(default_ptr, string2->Get(), arena1); - string2->Set(default_ptr, temp, arena2); + string2->Set(default_ptr, std::move(temp), arena2); } } break; } @@ -834,16 +825,8 @@ void Reflection::ClearField(Message* message, switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - if (IsInlined(field)) { - const std::string* default_ptr = - &DefaultRaw(field).GetNoArena(); - MutableRaw(message, field) - ->SetNoArena(default_ptr, *default_ptr); - break; - } - const std::string* default_ptr = - &DefaultRaw(field).Get(); + DefaultRaw(field).GetPointer(); MutableRaw(message, field) ->SetAllocated(default_ptr, nullptr, GetArena(message)); break; @@ -1082,6 +1065,7 @@ void Reflection::ListFieldsMayFailOnStripped( output->push_back(field); } } else if (has_bits && has_bits_indices[i] != -1) { + CheckInvalidAccess(schema_, field); // Equivalent to: HasBit(message, field) if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) { output->push_back(field); @@ -1197,11 +1181,11 @@ std::string Reflection::GetString(const Message& message, switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - if (IsInlined(field)) { - return GetField(message, field).GetNoArena(); + if (auto* value = + GetField(message, field).GetPointer()) { + return *value; } - - return GetField(message, field).Get(); + return field->default_value_string(); } } } @@ -1221,11 +1205,11 @@ const std::string& Reflection::GetStringReference(const Message& message, switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - if (IsInlined(field)) { - return GetField(message, field).GetNoArena(); + if (auto* value = + GetField(message, field).GetPointer()) { + return *value; } - - return GetField(message, field).Get(); + return field->default_value_string(); } } } @@ -1242,20 +1226,14 @@ void Reflection::SetString(Message* message, const FieldDescriptor* field, switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { - if (IsInlined(field)) { - MutableField(message, field) - ->SetNoArena(nullptr, std::move(value)); - break; - } - // Oneof string fields are never set as a default instance. // We just need to pass some arbitrary default string to make it work. // This allows us to not have the real default accessible from // reflection. const std::string* default_ptr = schema_.InRealOneof(field) - ? &GetEmptyString() - : &DefaultRaw(field).Get(); + ? nullptr + : DefaultRaw(field).GetPointer(); if (schema_.InRealOneof(field) && !HasOneofField(*message, field)) { ClearOneof(message, field->containing_oneof()); MutableField(message, field) @@ -1968,10 +1946,6 @@ const Type& Reflection::GetRaw(const Message& message, return GetConstRefAtOffset(message, schema_.GetFieldOffset(field)); } -bool Reflection::IsInlined(const FieldDescriptor* field) const { - return schema_.IsFieldInlined(field); -} - template Type* Reflection::MutableRaw(Message* message, const FieldDescriptor* field) const { @@ -2058,11 +2032,6 @@ bool Reflection::HasBit(const Message& message, case FieldDescriptor::CPPTYPE_STRING: switch (field->options().ctype()) { default: { - if (IsInlined(field)) { - return !GetField(message, field) - .GetNoArena() - .empty(); - } return GetField(message, field).Get().size() > 0; } } @@ -2175,9 +2144,8 @@ void Reflection::ClearOneof(Message* message, // We just need to pass some arbitrary default string to make it // work. This allows us to not have the real default accessible // from reflection. - const std::string* default_ptr = &GetEmptyString(); MutableField(message, field) - ->Destroy(default_ptr, GetArena(message)); + ->Destroy(nullptr, GetArena(message)); break; } } diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index e3c83a2787..12abb4f97f 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -42,8 +42,6 @@ #include #include #include -// TODO(jasonh): Remove this once the compiler change to directly include this -// is released to components. #include #include #include @@ -59,7 +57,6 @@ namespace google { namespace protobuf { -class DescriptorPool; class MapKey; class MapValueRef; class MessageLayoutInspector; @@ -148,17 +145,6 @@ struct ReflectionSchema { } } - bool IsFieldInlined(const FieldDescriptor* field) const { - if (InRealOneof(field)) { - size_t offset = - static_cast(field->containing_type()->field_count() + - field->containing_oneof()->index()); - return Inlined(offsets_[offset], field->type()); - } else { - return Inlined(offsets_[field->index()], field->type()); - } - } - uint32 GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const { return static_cast(oneof_case_offset_) + static_cast(static_cast(oneof_descriptor->index()) * @@ -214,15 +200,18 @@ struct ReflectionSchema { // Returns true if the field's accessor is called by any external code (aka, // non proto library code). - bool IsFieldUsed(const FieldDescriptor* /* field */) const { + bool IsFieldUsed(const FieldDescriptor* field) const { + (void)field; return true; } - bool IsFieldStripped(const FieldDescriptor* /* field */) const { + bool IsFieldStripped(const FieldDescriptor* field) const { + (void)field; return false; } - bool IsMessageStripped(const Descriptor* /* descriptor */) const { + bool IsMessageStripped(const Descriptor* descriptor) const { + (void)descriptor; return false; } @@ -246,25 +235,9 @@ struct ReflectionSchema { int weak_field_map_offset_; // We tag offset values to provide additional data about fields (such as - // inlined). + // "unused"). static uint32 OffsetValue(uint32 v, FieldDescriptor::Type type) { - v &= 0x7FFFFFFFu; - if (type == FieldDescriptor::TYPE_STRING || - type == FieldDescriptor::TYPE_BYTES) { - return v & ~1u; - } else { - return v; - } - } - - static bool Inlined(uint32 v, FieldDescriptor::Type type) { - if (type == FieldDescriptor::TYPE_STRING || - type == FieldDescriptor::TYPE_BYTES) { - return v & 1u; - } else { - // Non string/byte fields are not inlined. - return false; - } + return v & 0x7FFFFFFFu; } }; diff --git a/src/google/protobuf/generated_message_table_driven.h b/src/google/protobuf/generated_message_table_driven.h index 9ff58e0454..731d6c5212 100644 --- a/src/google/protobuf/generated_message_table_driven.h +++ b/src/google/protobuf/generated_message_table_driven.h @@ -73,9 +73,7 @@ enum ProcessingTypes { TYPE_STRING_STRING_PIECE = 20, TYPE_BYTES_CORD = 21, TYPE_BYTES_STRING_PIECE = 22, - TYPE_STRING_INLINED = 23, - TYPE_BYTES_INLINED = 24, - TYPE_MAP = 25, + TYPE_MAP = 23, }; static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum"); @@ -106,8 +104,7 @@ struct PROTOBUF_EXPORT FieldMetadata { enum { kCordType = 19, kStringPieceType = 20, - kInlinedType = 21, - kNumTypes = 21, + kNumTypes = 20, kSpecial = kNumTypes * kNumTypeClasses, }; diff --git a/src/google/protobuf/generated_message_table_driven_lite.h b/src/google/protobuf/generated_message_table_driven_lite.h index 7405c3dc31..3c65acdfe8 100644 --- a/src/google/protobuf/generated_message_table_driven_lite.h +++ b/src/google/protobuf/generated_message_table_driven_lite.h @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -50,7 +49,6 @@ namespace internal { enum StringType { StringType_STRING = 0, - StringType_INLINED = 3 }; // Logically a superset of StringType, consisting of all field types that @@ -59,8 +57,7 @@ enum ProcessingType { ProcessingType_STRING = 0, ProcessingType_CORD = 1, ProcessingType_STRING_PIECE = 2, - ProcessingType_INLINED = 3, - ProcessingType_MESSAGE = 4, + ProcessingType_MESSAGE = 3, }; enum Cardinality { @@ -90,8 +87,7 @@ inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) { template inline Type* AddField(MessageLite* msg, int64 offset) { - static_assert(std::is_pod::value || - std::is_same::value, + static_assert(std::is_pod::value, "Do not assign"); RepeatedField* repeated = Raw>(msg, offset); @@ -157,12 +153,7 @@ inline void ClearOneofField(const ParseTableField& field, Arena* arena, case WireFormatLite::TYPE_STRING: case WireFormatLite::TYPE_BYTES: Raw(msg, field.offset) - ->Destroy(&GetEmptyStringAlreadyInited(), arena); - break; - - case TYPE_STRING_INLINED: - case TYPE_BYTES_INLINED: - Raw(msg, field.offset)->DestroyNoArena(NULL); + ->Destroy(ArenaStringPtr::EmptyDefault{}, arena); break; default: @@ -197,10 +188,6 @@ inline void ResetOneofField(const ParseTable& table, int field_number, Raw(msg, offset) ->UnsafeSetDefault(static_cast(default_ptr)); break; - case ProcessingType_INLINED: - new (Raw(msg, offset)) - InlinedStringField(*static_cast(default_ptr)); - break; case ProcessingType_MESSAGE: MessageLite** submessage = Raw(msg, offset); const MessageLite* prototype = @@ -225,35 +212,12 @@ static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg, #endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED switch (ctype) { - case StringType_INLINED: { - InlinedStringField* s = nullptr; - switch (cardinality) { - case Cardinality_SINGULAR: - // TODO(ckennelly): Is this optimal? - s = MutableField(msg, has_bits, has_bit_index, - offset); - break; - case Cardinality_REPEATED: - s = AddField(msg, offset); - break; - case Cardinality_ONEOF: - s = Raw(msg, offset); - break; - } - GOOGLE_DCHECK(s != nullptr); - std::string* value = s->MutableNoArena(NULL); - if (PROTOBUF_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) { - return false; - } - utf8_string_data = *value; - break; - } case StringType_STRING: { switch (cardinality) { case Cardinality_SINGULAR: { ArenaStringPtr* field = MutableField( msg, has_bits, has_bit_index, offset); - std::string* value = field->Mutable( + std::string* value = field->MutableNoCopy( static_cast(default_ptr), arena); if (PROTOBUF_PREDICT_FALSE( !WireFormatLite::ReadString(input, value))) { @@ -271,7 +235,7 @@ static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg, } break; case Cardinality_ONEOF: { ArenaStringPtr* field = Raw(msg, offset); - std::string* value = field->Mutable( + std::string* value = field->MutableNoCopy( static_cast(default_ptr), arena); if (PROTOBUF_PREDICT_FALSE( !WireFormatLite::ReadString(input, value))) { @@ -481,23 +445,6 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg, } break; } - case TYPE_BYTES_INLINED: -#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - case TYPE_STRING_INLINED: -#endif // !GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - { - Arena* const arena = msg->GetArena(); - const void* default_ptr = table.aux[field_number].strings.default_ptr; - - if (PROTOBUF_PREDICT_FALSE( - (!HandleString( - input, msg, arena, has_bits, presence_index, offset, - default_ptr, nullptr)))) { - return false; - } - break; - } case WireFormatLite::TYPE_BYTES | kOneofMask: #ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case WireFormatLite::TYPE_STRING | kOneofMask: @@ -521,10 +468,8 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg, break; } case (WireFormatLite::TYPE_BYTES) | kRepeatedMask: - case TYPE_BYTES_INLINED | kRepeatedMask: #ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case (WireFormatLite::TYPE_STRING) | kRepeatedMask: - case TYPE_STRING_INLINED | kRepeatedMask: #endif // !GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED { Arena* const arena = msg->GetArena(); @@ -554,7 +499,6 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg, } break; } - case TYPE_STRING_INLINED | kRepeatedMask: case (WireFormatLite::TYPE_STRING) | kRepeatedMask: { Arena* const arena = msg->GetArena(); const void* default_ptr = table.aux[field_number].strings.default_ptr; @@ -712,22 +656,6 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg, break; } -#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - case TYPE_STRING_INLINED: { - Arena* const arena = msg->GetArena(); - const void* default_ptr = table.aux[field_number].strings.default_ptr; - const char* field_name = table.aux[field_number].strings.field_name; - - if (PROTOBUF_PREDICT_FALSE( - (!HandleString( - input, msg, arena, has_bits, presence_index, offset, - default_ptr, field_name)))) { - return false; - } - break; - } -#endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED case TYPE_MAP: { if (PROTOBUF_PREDICT_FALSE(!(*table.aux[field_number].maps.parse_map)( input, Raw(msg, offset)))) { @@ -750,8 +678,6 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg, GOOGLE_DCHECK_NE(processing_type, kRepeatedMask); GOOGLE_DCHECK_EQ(0, processing_type & kOneofMask); - GOOGLE_DCHECK_NE(TYPE_BYTES_INLINED | kRepeatedMask, processing_type); - GOOGLE_DCHECK_NE(TYPE_STRING_INLINED | kRepeatedMask, processing_type); // Mask out kRepeatedMask bit, allowing the jump table to be smaller. switch (static_cast(processing_type ^ @@ -847,7 +773,7 @@ bool MergePartialFromCodedStreamInlined(MessageLite* msg, } } } -} +} // NOLINT(readability/fn_size) template bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table, diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index 01f65ae9eb..f1f6f88332 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -68,16 +68,25 @@ void DestroyString(const void* s) { static_cast(s)->~basic_string(); } -ExplicitlyConstructed fixed_address_empty_string; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT EmptyString + fixed_address_empty_string; // NOLINT +PROTOBUF_CONSTINIT std::atomic init_protobuf_defaults_state{false}; static bool InitProtobufDefaultsImpl() { - fixed_address_empty_string.DefaultConstruct(); - OnShutdownDestroyString(fixed_address_empty_string.get_mutable()); + ::new (static_cast(&fixed_address_empty_string.value)) std::string(); + OnShutdownDestroyString(&fixed_address_empty_string.value); + + // Verify that we can indeed get the address during constant evaluation. + PROTOBUF_CONSTINIT static const std::string& fixed_address_empty_string_test = + GetEmptyStringAlreadyInited(); + (void)fixed_address_empty_string_test; + + init_protobuf_defaults_state.store(true, std::memory_order_release); return true; } -void InitProtobufDefaults() { +void InitProtobufDefaultsSlow() { static bool is_inited = InitProtobufDefaultsImpl(); (void)is_inited; } @@ -246,10 +255,6 @@ struct PrimitiveTypeHelper : PrimitiveTypeHelper {}; -template <> -struct PrimitiveTypeHelper - : PrimitiveTypeHelper {}; - // We want to serialize to both CodedOutputStream and directly into byte arrays // without duplicating the code. In fact we might want extra output channels in // the future. @@ -408,15 +413,6 @@ struct SingularFieldHelper { } }; -template <> -struct SingularFieldHelper { - template - static void Serialize(const void* field, const FieldMetadata& md, O* output) { - WriteTagTo(md.tag, output); - SerializeTo(&Get(field), output); - } -}; - template struct RepeatedFieldHelper { template @@ -489,10 +485,6 @@ struct RepeatedFieldHelper { }; -template <> -struct RepeatedFieldHelper - : RepeatedFieldHelper {}; - template struct PackedFieldHelper { template @@ -528,9 +520,6 @@ struct PackedFieldHelper template <> struct PackedFieldHelper : PackedFieldHelper {}; -template <> -struct PackedFieldHelper - : PackedFieldHelper {}; template struct OneOfFieldHelper { @@ -541,15 +530,6 @@ struct OneOfFieldHelper { }; -template <> -struct OneOfFieldHelper { - template - static void Serialize(const void* field, const FieldMetadata& md, O* output) { - SingularFieldHelper::Serialize( - Get(field), md, output); - } -}; - void SerializeNotImplemented(int field) { GOOGLE_LOG(FATAL) << "Not implemented field number " << field; } @@ -590,11 +570,6 @@ bool IsNull(const void* ptr) { } -template <> -bool IsNull(const void* ptr) { - return static_cast(ptr)->empty(); -} - #define SERIALIZERS_FOR_TYPE(type) \ case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence): \ if (!IsPresent(base, field_metadata.has_offset)) continue; \ @@ -642,7 +617,6 @@ void SerializeInternal(const uint8* base, SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64); - SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType); // Special cases case FieldMetadata::kSpecial: @@ -687,7 +661,6 @@ uint8* SerializeInternalToArray(const uint8* base, SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64); - SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType); // Special cases case FieldMetadata::kSpecial: { io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX); diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index 7cae4e1266..bae0c1f760 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -85,7 +85,17 @@ inline To DownCast(From& f) { } -PROTOBUF_EXPORT void InitProtobufDefaults(); +// This fastpath inlines a single branch instead of having to make the +// InitProtobufDefaults function call. +// It also generates less inlined code than a function-scope static initializer. +PROTOBUF_EXPORT extern std::atomic init_protobuf_defaults_state; +PROTOBUF_EXPORT void InitProtobufDefaultsSlow(); +PROTOBUF_EXPORT inline void InitProtobufDefaults() { + if (PROTOBUF_PREDICT_FALSE( + !init_protobuf_defaults_state.load(std::memory_order_acquire))) { + InitProtobufDefaultsSlow(); + } +} // This used by proto1 PROTOBUF_EXPORT inline const std::string& GetEmptyString() { diff --git a/src/google/protobuf/has_bits.h b/src/google/protobuf/has_bits.h index 540cac282f..1144b9f461 100644 --- a/src/google/protobuf/has_bits.h +++ b/src/google/protobuf/has_bits.h @@ -47,7 +47,7 @@ namespace internal { template class HasBits { public: - HasBits() PROTOBUF_ALWAYS_INLINE { Clear(); } + constexpr HasBits() PROTOBUF_ALWAYS_INLINE : has_bits_{} {} void Clear() PROTOBUF_ALWAYS_INLINE { memset(has_bits_, 0, sizeof(has_bits_)); diff --git a/src/google/protobuf/implicit_weak_message.h b/src/google/protobuf/implicit_weak_message.h index ec028eb5cd..bfa6a813b3 100644 --- a/src/google/protobuf/implicit_weak_message.h +++ b/src/google/protobuf/implicit_weak_message.h @@ -129,7 +129,7 @@ class ImplicitWeakTypeHandler { template struct WeakRepeatedPtrField { using TypeHandler = internal::ImplicitWeakTypeHandler; - WeakRepeatedPtrField() : weak() {} + constexpr WeakRepeatedPtrField() : weak() {} explicit WeakRepeatedPtrField(Arena* arena) : weak(arena) {} ~WeakRepeatedPtrField() { weak.template Destroy(); } diff --git a/src/google/protobuf/inlined_string_field.h b/src/google/protobuf/inlined_string_field.h deleted file mode 100644 index 991c0e1f3f..0000000000 --- a/src/google/protobuf/inlined_string_field.h +++ /dev/null @@ -1,260 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__ -#define GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__ - -#include -#include - -#include -#include - -// Must be included last. -#include - -#ifdef SWIG -#error "You cannot SWIG proto headers" -#endif - -namespace google { -namespace protobuf { - -class Arena; - -namespace internal { - -// InlinedStringField wraps a std::string instance and exposes an API similar to -// ArenaStringPtr's wrapping of a std::string* instance. As std::string is -// never allocated on the Arena, we expose only the *NoArena methods of -// ArenaStringPtr. -// -// default_value parameters are taken for consistency with ArenaStringPtr, but -// are not used for most methods. With inlining, these should be removed from -// the generated binary. -class PROTOBUF_EXPORT InlinedStringField { - public: - InlinedStringField() PROTOBUF_ALWAYS_INLINE; - explicit InlinedStringField(const std::string& default_value); - - void AssignWithDefault(const std::string* default_value, - const InlinedStringField& from) PROTOBUF_ALWAYS_INLINE; - - void ClearToEmpty(const std::string* default_value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - ClearToEmptyNoArena(default_value); - } - void ClearNonDefaultToEmpty() PROTOBUF_ALWAYS_INLINE { - ClearNonDefaultToEmptyNoArena(); - } - void ClearToEmptyNoArena(const std::string* /*default_value*/) - PROTOBUF_ALWAYS_INLINE { - ClearNonDefaultToEmptyNoArena(); - } - void ClearNonDefaultToEmptyNoArena() PROTOBUF_ALWAYS_INLINE; - - void ClearToDefault(const std::string* default_value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - ClearToDefaultNoArena(default_value); - } - void ClearToDefaultNoArena(const std::string* default_value) - PROTOBUF_ALWAYS_INLINE; - - void Destroy(const std::string* default_value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - DestroyNoArena(default_value); - } - void DestroyNoArena(const std::string* default_value) PROTOBUF_ALWAYS_INLINE; - - const std::string& Get() const PROTOBUF_ALWAYS_INLINE { return GetNoArena(); } - const std::string& GetNoArena() const PROTOBUF_ALWAYS_INLINE; - - std::string* Mutable(const std::string* default_value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - return MutableNoArena(default_value); - } - std::string* MutableNoArena(const std::string* default_value) - PROTOBUF_ALWAYS_INLINE; - - std::string* Release(const std::string* default_value, Arena* /*arena*/) { - return ReleaseNoArena(default_value); - } - std::string* ReleaseNonDefault(const std::string* default_value, - Arena* /*arena*/) { - return ReleaseNonDefaultNoArena(default_value); - } - std::string* ReleaseNoArena(const std::string* default_value) { - return ReleaseNonDefaultNoArena(default_value); - } - std::string* ReleaseNonDefaultNoArena(const std::string* default_value); - - void Set(const std::string* default_value, StringPiece value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - SetNoArena(default_value, value); - } - void SetLite(const std::string* default_value, StringPiece value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - SetNoArena(default_value, value); - } - void SetNoArena(const std::string* default_value, - StringPiece value) PROTOBUF_ALWAYS_INLINE; - - void Set(const std::string* default_value, const std::string& value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - SetNoArena(default_value, value); - } - void SetLite(const std::string* default_value, const std::string& value, - Arena* /*arena*/) PROTOBUF_ALWAYS_INLINE { - SetNoArena(default_value, value); - } - void SetNoArena(const std::string* default_value, - const std::string& value) PROTOBUF_ALWAYS_INLINE; - - void SetNoArena(const std::string* default_value, - std::string&& value) PROTOBUF_ALWAYS_INLINE; - void SetAllocated(const std::string* default_value, std::string* value, - Arena* /*arena*/) { - SetAllocatedNoArena(default_value, value); - } - void SetAllocatedNoArena(const std::string* default_value, - std::string* value); - void Swap(InlinedStringField* from) PROTOBUF_ALWAYS_INLINE; - std::string* UnsafeMutablePointer(); - void UnsafeSetDefault(const std::string* default_value); - std::string* UnsafeArenaRelease(const std::string* default_value, - Arena* arena); - void UnsafeArenaSetAllocated(const std::string* default_value, - std::string* value, Arena* arena); - - bool IsDefault(const std::string* /*default_value*/) { return false; } - - private: - std::string value_; -}; - -inline InlinedStringField::InlinedStringField() {} - -inline InlinedStringField::InlinedStringField(const std::string& default_value) - : value_(default_value) {} - -inline void InlinedStringField::AssignWithDefault( - const std::string* /*default_value*/, const InlinedStringField& from) { - value_ = from.value_; -} - -inline const std::string& InlinedStringField::GetNoArena() const { - return value_; -} - -inline std::string* InlinedStringField::MutableNoArena(const std::string*) { - return &value_; -} - -inline void InlinedStringField::SetAllocatedNoArena( - const std::string* default_value, std::string* value) { - if (value == NULL) { - value_.assign(*default_value); - } else { - value_.assign(std::move(*value)); - delete value; - } -} - -inline void InlinedStringField::DestroyNoArena(const std::string*) { - // This is invoked from the generated message's ArenaDtor, which is used to - // clean up objects not allocated on the Arena. - this->~InlinedStringField(); -} - -inline void InlinedStringField::ClearNonDefaultToEmptyNoArena() { - value_.clear(); -} - -inline void InlinedStringField::ClearToDefaultNoArena( - const std::string* default_value) { - value_.assign(*default_value); -} - -inline std::string* InlinedStringField::ReleaseNonDefaultNoArena( - const std::string* default_value) { - std::string* released = new std::string(*default_value); - value_.swap(*released); - return released; -} - -inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/, - StringPiece value) { - value_.assign(value.data(), value.length()); -} - -inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/, - const std::string& value) { - value_.assign(value); -} - -inline void InlinedStringField::SetNoArena(const std::string* /*default_value*/, - std::string&& value) { - value_.assign(std::move(value)); -} - -inline void InlinedStringField::Swap(InlinedStringField* from) { - value_.swap(from->value_); -} - -inline std::string* InlinedStringField::UnsafeMutablePointer() { - return &value_; -} - -inline void InlinedStringField::UnsafeSetDefault( - const std::string* default_value) { - value_.assign(*default_value); -} - -inline std::string* InlinedStringField::UnsafeArenaRelease( - const std::string* default_value, Arena* /*arena*/) { - return ReleaseNoArena(default_value); -} - -inline void InlinedStringField::UnsafeArenaSetAllocated( - const std::string* default_value, std::string* value, Arena* /*arena*/) { - if (value == NULL) { - value_.assign(*default_value); - } else { - value_.assign(*value); - } -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#include - -#endif // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__ diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc index 4b1bf802e0..52617e9efe 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -165,25 +165,14 @@ int FileInputStream::CopyingFileInputStream::Skip(int count) { // =================================================================== FileOutputStream::FileOutputStream(int file_descriptor, int block_size) - : copying_output_(file_descriptor), impl_(©ing_output_, block_size) {} - -FileOutputStream::~FileOutputStream() { impl_.Flush(); } + : CopyingOutputStreamAdaptor(©ing_output_), + copying_output_(file_descriptor) {} bool FileOutputStream::Close() { - bool flush_succeeded = impl_.Flush(); + bool flush_succeeded = Flush(); return copying_output_.Close() && flush_succeeded; } -bool FileOutputStream::Flush() { return impl_.Flush(); } - -bool FileOutputStream::Next(void** data, int* size) { - return impl_.Next(data, size); -} - -void FileOutputStream::BackUp(int count) { impl_.BackUp(count); } - -int64_t FileOutputStream::ByteCount() const { return impl_.ByteCount(); } - FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream( int file_descriptor) : file_(file_descriptor), @@ -191,6 +180,8 @@ FileOutputStream::CopyingFileOutputStream::CopyingFileOutputStream( is_closed_(false), errno_(0) {} +FileOutputStream::~FileOutputStream() { Flush(); } + FileOutputStream::CopyingFileOutputStream::~CopyingFileOutputStream() { if (close_on_delete_) { if (!Close()) { diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h index 6e5cdebbf1..0206e3887e 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.h +++ b/src/google/protobuf/io/zero_copy_stream_impl.h @@ -139,13 +139,14 @@ class PROTOBUF_EXPORT FileInputStream : public ZeroCopyInputStream { // harming performance. Also, it's conceivable that FileOutputStream could // someday be enhanced to use zero-copy file descriptors on OSs which // support them. -class PROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { +class PROTOBUF_EXPORT FileOutputStream : public CopyingOutputStreamAdaptor { public: // Creates a stream that writes to the given Unix file descriptor. // If a block_size is given, it specifies the size of the buffers // that should be returned by Next(). Otherwise, a reasonable default // is used. explicit FileOutputStream(int file_descriptor, int block_size = -1); + ~FileOutputStream() override; // Flushes any buffers and closes the underlying file. Returns false if @@ -153,11 +154,6 @@ class PROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { // Even if an error occurs, the file descriptor is closed when this returns. bool Close(); - // Flushes FileOutputStream's buffers but does not close the - // underlying file. No special measures are taken to ensure that - // underlying operating system file object is synchronized to disk. - bool Flush(); - // By default, the file descriptor is not closed when the stream is // destroyed. Call SetCloseOnDelete(true) to change that. WARNING: // This leaves no way for the caller to detect if close() fails. If @@ -171,11 +167,6 @@ class PROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { // fail. int GetErrno() const { return copying_output_.GetErrno(); } - // implements ZeroCopyOutputStream --------------------------------- - bool Next(void** data, int* size) override; - void BackUp(int count) override; - int64_t ByteCount() const override; - private: class PROTOBUF_EXPORT CopyingFileOutputStream : public CopyingOutputStream { public: @@ -202,7 +193,6 @@ class PROTOBUF_EXPORT FileOutputStream : public ZeroCopyOutputStream { }; CopyingFileOutputStream copying_output_; - CopyingOutputStreamAdaptor impl_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream); }; 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 34bf45ff70..54c5db945e 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -342,6 +342,37 @@ int64_t CopyingOutputStreamAdaptor::ByteCount() const { return position_ + buffer_used_; } +bool CopyingOutputStreamAdaptor::WriteAliasedRaw(const void* data, int size) { + if (size >= buffer_size_) { + if (!Flush() || !copying_stream_->Write(data, size)) { + return false; + } + GOOGLE_DCHECK_EQ(buffer_used_, 0); + position_ += size; + return true; + } + + void* out; + int out_size; + while (true) { + if (!Next(&out, &out_size)) { + return false; + } + + if (size <= out_size) { + std::memcpy(out, data, size); + BackUp(out_size - size); + return true; + } + + std::memcpy(out, data, out_size); + data = static_cast(data) + out_size; + size -= out_size; + } + return true; +} + + bool CopyingOutputStreamAdaptor::WriteBuffer() { if (failed_) { // Already failed on a previous write. 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 2f0c662274..cfe81d2cc1 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -307,6 +307,8 @@ class PROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStream { bool Next(void** data, int* size) override; void BackUp(int count) override; int64_t ByteCount() const override; + bool WriteAliasedRaw(const void* data, int size) override; + bool AllowsAliasing() const override { return true; } private: // Write the current buffer, if it is present. diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index ea18a20883..deb5f06b83 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -1187,5 +1189,84 @@ TEST(Lite, AliasedEnum) { EXPECT_EQ(protobuf_unittest::DupEnum::FOO2, value); } + +TEST(Lite, CodedInputStreamRollback) { + { + protobuf_unittest::TestAllTypesLite m; + m.set_optional_bytes(std::string(30, 'a')); + std::string serialized = m.SerializeAsString(); + serialized += '\014'; + serialized += std::string(3, ' '); + io::ArrayInputStream is(serialized.data(), serialized.size(), + serialized.size() - 6); + { + io::CodedInputStream cis(&is); + m.Clear(); + m.MergePartialFromCodedStream(&cis); + EXPECT_TRUE(cis.LastTagWas(12)); + EXPECT_FALSE(cis.ConsumedEntireMessage()); + // Should leave is with 3 spaces; + } + const void* data; + int size; + ASSERT_TRUE(is.Next(&data, &size)); + ASSERT_EQ(size, 3); + EXPECT_EQ(memcmp(data, " ", 3), 0); + } + { + protobuf_unittest::TestPackedTypesLite m; + constexpr int kCount = 30; + for (int i = 0; i < kCount; i++) m.add_packed_fixed32(i); + std::string serialized = m.SerializeAsString(); + serialized += '\014'; + serialized += std::string(3, ' '); + // Buffer breaks in middle of a fixed32. + io::ArrayInputStream is(serialized.data(), serialized.size(), + serialized.size() - 7); + { + io::CodedInputStream cis(&is); + m.Clear(); + m.MergePartialFromCodedStream(&cis); + EXPECT_TRUE(cis.LastTagWas(12)); + EXPECT_FALSE(cis.ConsumedEntireMessage()); + // Should leave is with 3 spaces; + } + ASSERT_EQ(m.packed_fixed32_size(), kCount); + for (int i = 0; i < kCount; i++) EXPECT_EQ(m.packed_fixed32(i), i); + const void* data; + int size; + ASSERT_TRUE(is.Next(&data, &size)); + ASSERT_EQ(size, 3); + EXPECT_EQ(memcmp(data, " ", 3), 0); + } + { + protobuf_unittest::TestPackedTypesLite m; + constexpr int kCount = 30; + // Make sure we output 2 byte varints + for (int i = 0; i < kCount; i++) m.add_packed_fixed32(128 + i); + std::string serialized = m.SerializeAsString(); + serialized += '\014'; + serialized += std::string(3, ' '); + // Buffer breaks in middle of a 2 byte varint. + io::ArrayInputStream is(serialized.data(), serialized.size(), + serialized.size() - 5); + { + io::CodedInputStream cis(&is); + m.Clear(); + m.MergePartialFromCodedStream(&cis); + EXPECT_TRUE(cis.LastTagWas(12)); + EXPECT_FALSE(cis.ConsumedEntireMessage()); + // Should leave is with 3 spaces; + } + ASSERT_EQ(m.packed_fixed32_size(), kCount); + for (int i = 0; i < kCount; i++) EXPECT_EQ(m.packed_fixed32(i), i + 128); + const void* data; + int size; + ASSERT_TRUE(is.Next(&data, &size)); + ASSERT_EQ(size, 3); + EXPECT_EQ(memcmp(data, " ", 3), 0); + } +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 527d52b4ef..2453246d20 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -105,8 +105,8 @@ class MapAllocator { using size_type = size_t; using difference_type = ptrdiff_t; - MapAllocator() : arena_(nullptr) {} - explicit MapAllocator(Arena* arena) : arena_(arena) {} + constexpr MapAllocator() : arena_(nullptr) {} + explicit constexpr MapAllocator(Arena* arena) : arena_(arena) {} template MapAllocator(const MapAllocator& allocator) // NOLINT(runtime/explicit) : arena_(allocator.arena()) {} @@ -337,6 +337,8 @@ struct MapPair { MapPair(const Key& other_first, const T& other_second) : first(other_first), second(other_second) {} explicit MapPair(const Key& other_first) : first(other_first), second() {} + explicit MapPair(Key&& other_first) + : first(std::move(other_first)), second() {} MapPair(const MapPair& other) : first(other.first), second(other.second) {} ~MapPair() {} @@ -380,7 +382,7 @@ class Map { using size_type = size_t; using hasher = typename internal::TransparentSupport::hash; - Map() : elements_(nullptr) {} + constexpr Map() : elements_(nullptr) {} explicit Map(Arena* arena) : elements_(arena) {} Map(const Map& other) : Map() { insert(other.begin(), other.end()); } @@ -448,12 +450,12 @@ class Map { // otherwise. This avoids unnecessary copies of string keys, for example. class InnerMap : private hasher { public: - explicit InnerMap(Arena* arena) + explicit constexpr InnerMap(Arena* arena) : hasher(), num_elements_(0), num_buckets_(internal::kGlobalEmptyTableSize), - seed_(Seed()), - index_of_first_non_null_(num_buckets_), + seed_(0), + index_of_first_non_null_(internal::kGlobalEmptyTableSize), table_(const_cast(internal::kGlobalEmptyTable)), alloc_(arena) {} @@ -685,7 +687,8 @@ class Map { // Insert the key into the map, if not present. In that case, the value will // be value initialized. - std::pair insert(const Key& k) { + template + std::pair insert(K&& k) { std::pair p = FindHelper(k); // Case 1: key was already present. if (p.first.node_ != nullptr) @@ -696,12 +699,18 @@ class Map { } const size_type b = p.second; // bucket number Node* node; + // If K is not key_type, make the conversion to key_type explicit. + using TypeToInit = typename std::conditional< + std::is_same::type, key_type>::value, K&&, + key_type>::type; if (alloc_.arena() == nullptr) { - node = new Node{value_type(k), nullptr}; + node = new Node{value_type(static_cast(std::forward(k))), + nullptr}; } else { node = Alloc(1); - Arena::CreateInArenaStorage(const_cast(&node->kv.first), - alloc_.arena(), k); + Arena::CreateInArenaStorage( + const_cast(&node->kv.first), alloc_.arena(), + static_cast(std::forward(k))); Arena::CreateInArenaStorage(&node->kv.second, alloc_.arena()); } @@ -710,7 +719,10 @@ class Map { return std::make_pair(result, true); } - value_type& operator[](const Key& k) { return *insert(k).first; } + template + value_type& operator[](K&& k) { + return *insert(std::forward(k)).first; + } void erase(iterator it) { GOOGLE_DCHECK_EQ(it.m_, this); @@ -908,6 +920,7 @@ class Map { // Just overwrite with a new one. No need to transfer or free anything. num_buckets_ = index_of_first_non_null_ = kMinTableSize; table_ = CreateEmptyTable(num_buckets_); + seed_ = Seed(); return; } @@ -1183,7 +1196,17 @@ class Map { bool empty() const { return size() == 0; } // Element access - T& operator[](const key_type& key) { return elements_[key].second; } + template + T& operator[](const key_arg& key) { + return elements_[key].second; + } + template < + typename K = key_type, + // Disable for integral types to reduce code bloat. + typename = typename std::enable_if::value>::type> + T& operator[](key_arg&& key) { + return elements_[std::forward(key)].second; + } template const T& at(const key_arg& key) const { diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index 180ff0e70a..9e35795f9b 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -93,7 +93,7 @@ template { public: - MapEntry() : _internal_metadata_(NULL) {} + constexpr MapEntry() : _internal_metadata_() {} explicit MapEntry(Arena* arena) : MapEntryImpl(arena), diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 92cb4ac4d1..1caf59dfed 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -182,17 +182,16 @@ class MapEntryImpl : public Base { static const WireFormatLite::FieldType kEntryKeyFieldType = kKeyFieldType; static const WireFormatLite::FieldType kEntryValueFieldType = kValueFieldType; - MapEntryImpl() { - KeyTypeHandler::Initialize(&key_, NULL); - ValueTypeHandler::Initialize(&value_, NULL); - _has_bits_[0] = 0; - } + constexpr MapEntryImpl() + : key_(KeyTypeHandler::Constinit()), + value_(ValueTypeHandler::Constinit()), + _has_bits_{} {} - explicit MapEntryImpl(Arena* arena) : Base(arena) { - KeyTypeHandler::Initialize(&key_, arena); - ValueTypeHandler::Initialize(&value_, arena); - _has_bits_[0] = 0; - } + explicit MapEntryImpl(Arena* arena) + : Base(arena), + key_(KeyTypeHandler::Constinit()), + value_(ValueTypeHandler::Constinit()), + _has_bits_{} {} ~MapEntryImpl() { if (Base::GetArena() != NULL) return; @@ -523,7 +522,7 @@ class MapEntryLite : public MapEntryImpl SuperType; - MapEntryLite() {} + constexpr MapEntryLite() {} explicit MapEntryLite(Arena* arena) : SuperType(arena) {} ~MapEntryLite() { MessageLite::_internal_metadata_.Delete(); } void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); } diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index f4e034cd3d..9fbd06ade9 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -324,6 +324,16 @@ class PROTOBUF_EXPORT MapFieldBase { public: MapFieldBase() : arena_(NULL), repeated_field_(NULL), state_(STATE_MODIFIED_MAP) {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + // Except in MSVC, where we can't have a constinit mutex. + explicit PROTOBUF_MAYBE_CONSTEXPR MapFieldBase(ConstantInitialized) + : arena_(nullptr), + repeated_field_(nullptr), + mutex_(GOOGLE_PROTOBUF_LINKER_INITIALIZED), + state_(STATE_MODIFIED_MAP) {} explicit MapFieldBase(Arena* arena) : arena_(arena), repeated_field_(NULL), state_(STATE_MODIFIED_MAP) { // Mutex's destructor needs to be called explicitly to release resources @@ -466,6 +476,12 @@ template class TypeDefinedMapFieldBase : public MapFieldBase { public: TypeDefinedMapFieldBase() {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + explicit constexpr TypeDefinedMapFieldBase(ConstantInitialized tag) + : MapFieldBase(tag) {} explicit TypeDefinedMapFieldBase(Arena* arena) : MapFieldBase(arena) {} ~TypeDefinedMapFieldBase() override {} void MapBegin(MapIterator* map_iter) const override; @@ -521,6 +537,12 @@ class MapField : public TypeDefinedMapFieldBase { typedef Map MapType; MapField() {} + + // This constructor is for constant initialized global instances. + // It uses a linker initialized mutex, so it is not compatible with regular + // runtime instances. + explicit constexpr MapField(ConstantInitialized tag) + : TypeDefinedMapFieldBase(tag), impl_() {} explicit MapField(Arena* arena) : TypeDefinedMapFieldBase(arena), impl_(arena) {} diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h index a47b87710a..665cb0eebe 100644 --- a/src/google/protobuf/map_field_lite.h +++ b/src/google/protobuf/map_field_lite.h @@ -63,7 +63,7 @@ class MapFieldLite { typedef Map MapType; typedef EntryType EntryTypeTrait; - MapFieldLite() {} + constexpr MapFieldLite() {} explicit MapFieldLite(Arena* arena) : map_(arena) {} diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 39544a3d24..f6274c0da3 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -45,6 +45,9 @@ #include #include +// Must be included last. +#include + namespace google { namespace protobuf { @@ -478,6 +481,22 @@ TEST_P(MapFieldStateTest, MutableMapField) { } } +class MyMapField + : public MapField { + public: + constexpr MyMapField() + : MyMapField::MapField(internal::ConstantInitialized{}) {} +}; + +TEST(MapFieldTest, ConstInit) { + // This tests that `MapField` and all its base classes can be constant + // initialized. + PROTOBUF_CONSTINIT static MyMapField field; // NOLINT + EXPECT_EQ(field.size(), 0); +} + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index 267abfb9a3..9c53b510f4 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -80,6 +80,7 @@ #include +// Must be included last. #include namespace google { @@ -194,6 +195,62 @@ TEST_F(MapImplTest, OperatorBracket) { ExpectSingleElement(key, value2); } +struct MoveTestKey { + MoveTestKey(int data, int* copies) : data(data), copies(copies) {} + + MoveTestKey(const MoveTestKey& other) + : data(other.data), copies(other.copies) { + ++*copies; + } + + MoveTestKey(MoveTestKey&& other) noexcept + : data(other.data), copies(other.copies) {} + + friend bool operator==(const MoveTestKey& lhs, const MoveTestKey& rhs) { + return lhs.data == rhs.data; + } + friend bool operator<(const MoveTestKey& lhs, const MoveTestKey& rhs) { + return lhs.data < rhs.data; + } + + int data; + int* copies; +}; + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google + +namespace std { + +template <> // NOLINT +struct hash { + size_t operator()(const google::protobuf::internal::MoveTestKey& key) const { + return hash{}(key.data); + } +}; +} // namespace std + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +TEST_F(MapImplTest, OperatorBracketRValue) { + Arena arena; + for (Arena* arena_to_use : {&arena, static_cast(nullptr)}) { + int copies = 0; + Map map(arena_to_use); + MoveTestKey key1(1, &copies); + EXPECT_EQ(copies, 0); + map[key1] = 0; + EXPECT_EQ(copies, 1); + map[MoveTestKey(2, &copies)] = 2; + EXPECT_EQ(copies, 1); + } +} + TEST_F(MapImplTest, OperatorBracketNonExist) { int32 key = 0; int32 default_value = 0; @@ -1104,6 +1161,11 @@ void TestTransparent(const Key& key, const Key& miss_key) { EXPECT_EQ(m.erase(key), 0); EXPECT_EQ(m.erase(miss_key), 0); EXPECT_THAT(m, UnorderedElementsAre(Pair("DEF", 2))); + + m[key]; + EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 0), Pair("DEF", 2))); + m[key] = 1; + EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 1), Pair("DEF", 2))); } TEST_F(MapImplTest, TransparentLookupForString) { @@ -1119,6 +1181,11 @@ TEST_F(MapImplTest, TransparentLookupForString) { TestTransparent(std::cref(abc), std::cref(lkj)); } +TEST_F(MapImplTest, ConstInit) { + PROTOBUF_CONSTINIT static Map map; // NOLINT + EXPECT_TRUE(map.empty()); +} + // Map Field Reflection Test ======================================== static int Func(int i, int j) { return i * j; } @@ -1986,6 +2053,39 @@ TEST_F(MapFieldReflectionTest, UninitializedEntry) { EXPECT_FALSE(message.IsInitialized()); } +class MyMapEntry + : public internal::MapEntry { + public: + constexpr MyMapEntry() {} + MyMapEntry(Arena*) { std::abort(); } + Metadata GetMetadata() const override { std::abort(); } + static bool ValidateKey(void*) { return true; } + static bool ValidateValue(void*) { return true; } +}; + +class MyMapEntryLite + : public internal::MapEntryLite { + public: + constexpr MyMapEntryLite() {} + explicit MyMapEntryLite(Arena*) { std::abort(); } + static bool ValidateKey(void*) { return true; } + static bool ValidateValue(void*) { return true; } +}; + +TEST(MapEntryTest, ConstInit) { + // This verifies that `MapEntry`, `MapEntryLite` and `MapEntryImpl` can be + // constant initialized. + PROTOBUF_CONSTINIT static MyMapEntry entry{}; + EXPECT_NE(entry.SpaceUsed(), 0); + + PROTOBUF_CONSTINIT static MyMapEntryLite entry_lite{}; // NOLINT + EXPECT_TRUE(entry_lite.IsInitialized()); +} + // Generated Message Test =========================================== TEST(GeneratedMapFieldTest, Accessors) { diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index 7908544286..8b8fd14c2d 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -157,7 +157,7 @@ class MapTypeHandler { 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 Initialize(Type** x, Arena* arena); + static constexpr TypeOnMemory Constinit(); static inline Type* EnsureMutable(Type** value, Arena* arena); // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding @@ -207,7 +207,7 @@ class MapTypeHandler { const TypeOnMemory& value); \ static inline bool IsInitialized(const TypeOnMemory& value); \ static void DeleteNoArena(TypeOnMemory& value); \ - static inline void Initialize(TypeOnMemory* value, Arena* arena); \ + static constexpr TypeOnMemory Constinit(); \ static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value, \ Arena* arena); \ }; @@ -522,9 +522,9 @@ void MapTypeHandler::DeleteNoArena( } template -inline void MapTypeHandler::Initialize( - Type** x, Arena* /* arena */) { - *x = NULL; +constexpr auto MapTypeHandler::Constinit() + -> TypeOnMemory { + return nullptr; } template @@ -570,7 +570,7 @@ inline bool MapTypeHandler::IsInitialized( template \ inline void MapTypeHandler::Clear( \ TypeOnMemory* value, Arena* arena) { \ - value->ClearToEmpty(&internal::GetEmptyStringAlreadyInited(), arena); \ + value->ClearToEmpty(); \ } \ template \ inline void MapTypeHandler::Merge( \ @@ -583,17 +583,17 @@ inline bool MapTypeHandler::IsInitialized( value.DestroyNoArena(&internal::GetEmptyStringAlreadyInited()); \ } \ template \ - inline void \ - MapTypeHandler::Initialize( \ - TypeOnMemory* value, Arena* /* arena */) { \ - value->UnsafeSetDefault(&internal::GetEmptyStringAlreadyInited()); \ + constexpr auto \ + MapTypeHandler::Constinit() \ + ->TypeOnMemory { \ + return TypeOnMemory(&internal::GetEmptyStringAlreadyInited()); \ } \ template \ inline typename MapTypeHandler::MapEntryAccessorType* \ MapTypeHandler::EnsureMutable( \ TypeOnMemory* value, Arena* arena) { \ - return value->Mutable(&internal::GetEmptyStringAlreadyInited(), arena); \ + return value->Mutable(ArenaStringPtr::EmptyDefault{}, arena); \ } \ template \ inline const typename MapTypeHandler::DeleteNoArena(TypeOnMemory& /* x */) {} \ template \ - inline void \ - MapTypeHandler::Initialize( \ - TypeOnMemory* value, Arena* /* arena */) { \ - *value = 0; \ + constexpr auto \ + MapTypeHandler::Constinit() \ + ->TypeOnMemory { \ + return 0; \ } \ template \ inline typename MapTypeHandlerSpaceUsedLong(*this); } -size_t Message::GetInvariantPerBuild(size_t salt) { +uint64 Message::GetInvariantPerBuild(uint64 salt) { return salt; } @@ -175,7 +175,7 @@ namespace { #define HASH_MAP std::unordered_map -#define STR_HASH_FXN hash +#define STR_HASH_FXN hash<::google::protobuf::StringPiece> class GeneratedMessageFactory : public MessageFactory { @@ -190,8 +190,8 @@ class GeneratedMessageFactory : public MessageFactory { private: // Only written at static init time, so does not require locking. - HASH_MAP + HASH_MAP file_map_; internal::WrappedMutex mutex_; diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index b4fddecf7c..feb9a8f57f 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -231,7 +231,7 @@ bool CreateUnknownEnumValues(const FieldDescriptor* field); // the internal library are allowed to create subclasses. class PROTOBUF_EXPORT Message : public MessageLite { public: - inline Message() {} + constexpr Message() = default; // Basic Operations ------------------------------------------------ @@ -367,7 +367,7 @@ class PROTOBUF_EXPORT Message : public MessageLite { protected: - static size_t GetInvariantPerBuild(size_t salt); + static uint64 GetInvariantPerBuild(uint64 salt); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message); @@ -1057,8 +1057,6 @@ class PROTOBUF_EXPORT Reflection final { internal::InternalMetadata* MutableInternalMetadata(Message* message) const; - inline bool IsInlined(const FieldDescriptor* field) const; - inline bool HasBit(const Message& message, const FieldDescriptor* field) const; inline void SetBit(Message* message, const FieldDescriptor* field) const; diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 5b1db7b9be..0e85991476 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -313,11 +313,11 @@ bool MessageLite::ParsePartialFromBoundedZeroCopyStream( return ParseFrom(internal::BoundedZCIS{input, size}); } -bool MessageLite::ParseFromString(const std::string& data) { +bool MessageLite::ParseFromString(ConstStringParam data) { return ParseFrom(data); } -bool MessageLite::ParsePartialFromString(const std::string& data) { +bool MessageLite::ParsePartialFromString(ConstStringParam data) { return ParseFrom(data); } @@ -329,7 +329,7 @@ bool MessageLite::ParsePartialFromArray(const void* data, int size) { return ParseFrom(as_string_view(data, size)); } -bool MessageLite::MergeFromString(const std::string& data) { +bool MessageLite::MergeFromString(ConstStringParam data) { return ParseFrom(data); } diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index c95e74c389..a76c16e5a4 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -74,6 +74,12 @@ class ZeroCopyOutputStream; } // namespace io namespace internal { +// Tag type used to invoke the constinit constructor overload of some classes. +// Such constructors are internal implementation details of the library. +struct ConstantInitialized { + explicit ConstantInitialized() = default; +}; + // See parse_context.h for explanation class ParseContext; @@ -145,14 +151,27 @@ class ExplicitlyConstructed { } union_; }; +PROTOBUF_DISABLE_MSVC_UNION_WARNING +// We need a publicly accessible `value` object to allow constexpr +// support in C++11. +// A constexpr accessor does not work portably. +union EmptyString { + constexpr EmptyString() : dummy{} {} + ~EmptyString() {} + + // We need a dummy object for constant initialization. + std::false_type dummy; + std::string value; +}; +PROTOBUF_ENABLE_MSVC_UNION_WARNING + // Default empty string object. Don't use this directly. Instead, call // GetEmptyString() to get the reference. -PROTOBUF_EXPORT extern ExplicitlyConstructed - fixed_address_empty_string; +PROTOBUF_EXPORT extern EmptyString fixed_address_empty_string; -PROTOBUF_EXPORT inline const std::string& GetEmptyStringAlreadyInited() { - return fixed_address_empty_string.get(); +PROTOBUF_EXPORT constexpr const std::string& GetEmptyStringAlreadyInited() { + return fixed_address_empty_string.value; } PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str); @@ -187,7 +206,7 @@ PROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const std::string& str); // the internal library are allowed to create subclasses. class PROTOBUF_EXPORT MessageLite { public: - inline MessageLite() {} + constexpr MessageLite() = default; virtual ~MessageLite() = default; // Basic Operations ------------------------------------------------ @@ -315,12 +334,11 @@ class PROTOBUF_EXPORT MessageLite { // format, matching the encoding output by MessageLite::SerializeToString(). // If you'd like to convert a human-readable string into a protocol buffer // object, see google::protobuf::TextFormat::ParseFromString(). - PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString( - const std::string& data); + PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data); // Like ParseFromString(), but accepts messages that are missing // required fields. PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString( - const std::string& data); + ConstStringParam data); // Parse a protocol buffer contained in an array of bytes. PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data, int size); @@ -351,7 +369,7 @@ class PROTOBUF_EXPORT MessageLite { bool MergePartialFromCodedStream(io::CodedInputStream* input); // Merge a protocol buffer contained in a string. - bool MergeFromString(const std::string& data); + bool MergeFromString(ConstStringParam data); // Serialization --------------------------------------------------- diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h index 781a1f54e7..ec5f923890 100644 --- a/src/google/protobuf/metadata_lite.h +++ b/src/google/protobuf/metadata_lite.h @@ -58,7 +58,7 @@ namespace internal { // pointer. class InternalMetadata { public: - InternalMetadata() : ptr_(nullptr) {} + constexpr InternalMetadata() : ptr_(nullptr) {} explicit InternalMetadata(Arena* arena) : ptr_(arena) {} template diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc index 2a57465dfc..22cdcbba5b 100644 --- a/src/google/protobuf/parse_context.cc +++ b/src/google/protobuf/parse_context.cc @@ -48,7 +48,7 @@ namespace internal { namespace { // Only call if at start of tag. -bool ParseEndsInSlopRegion(const char* begin, int overrun, int d) { +bool ParseEndsInSlopRegion(const char* begin, int overrun, int depth) { constexpr int kSlopBytes = EpsCopyInputStream::kSlopBytes; GOOGLE_DCHECK(overrun >= 0); GOOGLE_DCHECK(overrun <= kSlopBytes); @@ -79,11 +79,11 @@ bool ParseEndsInSlopRegion(const char* begin, int overrun, int d) { break; } case 3: { // start group - d++; + depth++; break; } case 4: { // end group - if (--d < 0) return true; // We exit early + if (--depth < 0) return true; // We exit early break; } case 5: { // fixed32 @@ -99,7 +99,7 @@ bool ParseEndsInSlopRegion(const char* begin, int overrun, int d) { } // namespace -const char* EpsCopyInputStream::Next(int overrun, int d) { +const char* EpsCopyInputStream::NextBuffer(int overrun, int depth) { if (next_chunk_ == nullptr) return nullptr; // We've reached end of stream. if (next_chunk_ != buffer_) { GOOGLE_DCHECK(size_ > kSlopBytes); @@ -115,7 +115,7 @@ const char* EpsCopyInputStream::Next(int overrun, int d) { // buffer_. std::memmove(buffer_, buffer_end_, kSlopBytes); if (overall_limit_ > 0 && - (d < 0 || !ParseEndsInSlopRegion(buffer_, overrun, d))) { + (depth < 0 || !ParseEndsInSlopRegion(buffer_, overrun, depth))) { const void* data; // ZeroCopyInputStream indicates Next may return 0 size buffers. Hence // we loop. @@ -154,11 +154,22 @@ const char* EpsCopyInputStream::Next(int overrun, int d) { return buffer_; } -std::pair EpsCopyInputStream::DoneFallback(const char* ptr, - int d) { - GOOGLE_DCHECK(ptr >= limit_end_); - int overrun = ptr - buffer_end_; - GOOGLE_DCHECK(overrun <= kSlopBytes); // Guaranteed by parse loop. +const char* EpsCopyInputStream::Next() { + GOOGLE_DCHECK(limit_ > kSlopBytes); + auto p = NextBuffer(0 /* immaterial */, -1); + if (p == nullptr) { + limit_end_ = buffer_end_; + // Distinguish ending on a pushed limit or ending on end-of-stream. + SetEndOfStream(); + return nullptr; + } + limit_ -= buffer_end_ - p; // Adjust limit_ relative to new anchor + limit_end_ = buffer_end_ + std::min(0, limit_); + return p; +} + +std::pair EpsCopyInputStream::DoneFallback(int overrun, + int depth) { // Did we exceeded the limit (parse error). if (PROTOBUF_PREDICT_FALSE(overrun > limit_)) return {nullptr, true}; GOOGLE_DCHECK(overrun != limit_); // Guaranteed by caller. @@ -171,10 +182,11 @@ std::pair EpsCopyInputStream::DoneFallback(const char* ptr, // At this point we know the following assertion holds. GOOGLE_DCHECK(limit_ > 0); GOOGLE_DCHECK(limit_end_ == buffer_end_); // because limit_ > 0 + const char* p; do { // We are past the end of buffer_end_, in the slop region. GOOGLE_DCHECK(overrun >= 0); - auto p = Next(overrun, d); + p = NextBuffer(overrun, depth); if (p == nullptr) { // We are at the end of the stream if (PROTOBUF_PREDICT_FALSE(overrun != 0)) return {nullptr, true}; @@ -182,14 +194,14 @@ std::pair EpsCopyInputStream::DoneFallback(const char* ptr, limit_end_ = buffer_end_; // Distinguish ending on a pushed limit or ending on end-of-stream. SetEndOfStream(); - return {ptr, true}; + return {buffer_end_, true}; } limit_ -= buffer_end_ - p; // Adjust limit_ relative to new anchor - ptr = p + overrun; - overrun = ptr - buffer_end_; + p += overrun; + overrun = p - buffer_end_; } while (overrun >= 0); limit_end_ = buffer_end_ + std::min(0, limit_); - return {ptr, false}; + return {p, false}; } const char* EpsCopyInputStream::SkipFallback(const char* ptr, int size) { @@ -263,9 +275,11 @@ const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size, for (int i = 0; i < num; i++) dst[i] = UnalignedLoad(ptr + i * sizeof(T)); #endif - ptr += block_size; size -= block_size; - if (DoneWithCheck(&ptr, -1)) return nullptr; + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; + ptr += kSlopBytes - (nbytes - block_size); nbytes = buffer_end_ + kSlopBytes - ptr; } int num = size / sizeof(T); diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h index c5e3fda016..661008589d 100644 --- a/src/google/protobuf/parse_context.h +++ b/src/google/protobuf/parse_context.h @@ -208,9 +208,16 @@ class PROTOBUF_EXPORT EpsCopyInputStream { bool DoneWithCheck(const char** ptr, int d) { GOOGLE_DCHECK(*ptr); if (PROTOBUF_PREDICT_TRUE(*ptr < limit_end_)) return false; - // No need to fetch buffer if we ended on a limit in the slop region - if ((*ptr - buffer_end_) == limit_) return true; - auto res = DoneFallback(*ptr, d); + int overrun = *ptr - buffer_end_; + GOOGLE_DCHECK_LE(overrun, kSlopBytes); // Guaranteed by parse loop. + if (overrun == + limit_) { // No need to flip buffers if we ended on a limit. + // If we actually overrun the buffer and next_chunk_ is null. It means + // the stream ended and we passed the stream end. + if (overrun > 0 && next_chunk_ == nullptr) *ptr = nullptr; + return true; + } + auto res = DoneFallback(overrun, d); *ptr = res.first; return res.second; } @@ -276,8 +283,26 @@ class PROTOBUF_EXPORT EpsCopyInputStream { // systems. TODO(gerbens) do we need to set this as build flag? enum { kSafeStringSize = 50000000 }; - std::pair DoneFallback(const char* ptr, int d); - const char* Next(int overrun, int d); + // Advances to next buffer chunk returns a pointer to the same logical place + // in the stream as set by overrun. Overrun indicates the position in the slop + // region the parse was left (0 <= overrun <= kSlopBytes). Returns true if at + // limit, at which point the returned pointer maybe null if there was an + // error. The invariant of this function is that it's guaranteed that + // kSlopBytes bytes can be accessed from the returned ptr. This function might + // advance more buffers than one in the underlying ZeroCopyInputStream. + std::pair DoneFallback(int overrun, int depth); + // Advances to the next buffer, at most one call to Next() on the underlying + // ZeroCopyInputStream is made. This function DOES NOT match the returned + // pointer to where in the slop region the parse ends, hence no overrun + // parameter. This is useful for string operations where you always copy + // to the end of the buffer (including the slop region). + const char* Next(); + // overrun is the location in the slop region the stream currently is + // (0 <= overrun <= kSlopBytes). To prevent flipping to the next buffer of + // the ZeroCopyInputStream in the case the parse will end in the last + // kSlopBytes of the current buffer. depth is the current depth of nested + // groups (or negative if the use case does not need careful tracking). + inline const char* NextBuffer(int overrun, int depth); const char* SkipFallback(const char* ptr, int size); const char* AppendStringFallback(const char* ptr, int size, std::string* str); const char* ReadStringFallback(const char* ptr, int size, std::string* str); @@ -296,16 +321,17 @@ class PROTOBUF_EXPORT EpsCopyInputStream { int chunk_size = buffer_end_ + kSlopBytes - ptr; do { GOOGLE_DCHECK(size > chunk_size); + if (next_chunk_ == nullptr) return nullptr; append(ptr, chunk_size); ptr += chunk_size; size -= chunk_size; - // DoneFallBack asserts it isn't called when exactly on the limit. If this - // happens we fail the parse, as we are at the limit and still more bytes - // to read. - if (limit_ == kSlopBytes) return nullptr; - auto res = DoneFallback(ptr, -1); - if (res.second) return nullptr; // If done we passed the limit - ptr = res.first; + // TODO(gerbens) Next calls NextBuffer which generates buffers with + // overlap and thus incurs cost of copying the slop regions. This is not + // necessary for reading strings. We should just call Next buffers. + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; // passed the limit + ptr += kSlopBytes; chunk_size = buffer_end_ + kSlopBytes - ptr; } while (size > chunk_size); append(ptr, size); @@ -319,11 +345,19 @@ class PROTOBUF_EXPORT EpsCopyInputStream { // implicit weak messages. We keep these methods private and friend them. template const char* AppendUntilEnd(const char* ptr, const A& append) { - while (!DoneWithCheck(&ptr, -1)) { - append(ptr, limit_end_ - ptr); - ptr = limit_end_; + if (ptr - buffer_end_ > limit_) return nullptr; + while (limit_ > kSlopBytes) { + int chunk_size = buffer_end_ + kSlopBytes - ptr; + GOOGLE_DCHECK_GE(chunk_size, 0); + append(ptr, chunk_size); + ptr = Next(); + if (ptr == nullptr) return limit_end_; + ptr += kSlopBytes; } - return ptr; + auto end = buffer_end_ + limit_; + GOOGLE_DCHECK(end >= ptr); + append(ptr, end - ptr); + return end; } PROTOBUF_MUST_USE_RESULT const char* AppendString(const char* ptr, @@ -354,7 +388,6 @@ class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream { void TrackCorrectEnding() { group_depth_ = 0; } bool Done(const char** ptr) { return DoneWithCheck(ptr, group_depth_); } - bool DoneNoSlopCheck(const char** ptr) { return DoneWithCheck(ptr, -1); } int depth() const { return depth_; } @@ -619,21 +652,52 @@ PROTOBUF_MUST_USE_RESULT const char* ParseContext::ParseMessage( } template -const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) { - int size = ReadSize(&ptr); - if (ptr == nullptr) return nullptr; - auto old = PushLimit(ptr, size); - if (old < 0) return nullptr; - while (!DoneWithCheck(&ptr, -1)) { +const char* ReadPackedVarintArray(const char* ptr, const char* end, Add add) { + while (ptr < end) { uint64 varint; ptr = VarintParse(ptr, &varint); - if (!ptr) return nullptr; + if (ptr == nullptr) return nullptr; add(varint); } - if (!PopLimit(old)) return nullptr; return ptr; } +template +const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) { + int size = ReadSize(&ptr); + if (ptr == nullptr) return nullptr; + int chunk_size = buffer_end_ - ptr; + while (size > chunk_size) { + ptr = ReadPackedVarintArray(ptr, buffer_end_, add); + if (ptr == nullptr) return nullptr; + int overrun = ptr - buffer_end_; + GOOGLE_DCHECK(overrun >= 0 && overrun <= kSlopBytes); + if (size - chunk_size <= kSlopBytes) { + // The current buffer contains all the information needed, we don't need + // to flip buffers. However we must parse from a buffer with enough space + // so we are not prone to a buffer overflow. + char buf[kSlopBytes + 10] = {}; + std::memcpy(buf, buffer_end_, kSlopBytes); + GOOGLE_CHECK_LE(size - chunk_size, kSlopBytes); + auto end = buf + (size - chunk_size); + auto res = ReadPackedVarintArray(buf + overrun, end, add); + if (res == nullptr || res != end) return nullptr; + return buffer_end_ + (res - buf); + } + size -= overrun + chunk_size; + GOOGLE_DCHECK_GT(size, 0); + // We must flip buffers + if (limit_ <= kSlopBytes) return nullptr; + ptr = Next(); + if (ptr == nullptr) return nullptr; + ptr += overrun; + chunk_size = buffer_end_ - ptr; + } + auto end = ptr + size; + ptr = ReadPackedVarintArray(ptr, end, add); + return end == ptr ? ptr : nullptr; +} + // Helper for verification of utf8 PROTOBUF_EXPORT bool VerifyUTF8(StringPiece s, const char* field_name); diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index 74c2518096..8b39d69896 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc @@ -139,6 +139,21 @@ #ifdef PROTOBUF_FINAL #error PROTOBUF_FINAL was previously defined #endif +#ifdef PROTOBUF_DISABLE_MSVC_UNION_WARNING +#error PROTOBUF_DISABLE_MSVC_UNION_WARNING was previously defined +#endif +#ifdef PROTOBUF_ENABLE_MSVC_UNION_WARNING +#error PROTOBUF_ENABLE_MSVC_UNION_WARNING was previously defined +#endif +#ifdef PROTOBUF_CONSTINIT +#error PROTOBUF_CONSTINIT was previously defined +#endif +#ifdef PROTOBUF_MAYBE_CONSTEXPR +#error PROTOBUF_MAYBE_CONSTEXPR was previously defined +#endif +#ifdef PROTOBUF_ATTRIBUTE_NO_DESTROY +#error PROTOBUF_ATTRIBUTE_NO_DESTROY was previously defined +#endif #define PROTOBUF_NAMESPACE "google::protobuf" @@ -238,12 +253,15 @@ #ifdef GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL #define PROTOBUF_RETURNS_NONNULL GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL #else -#ifdef __GNUC__ +#if defined(__has_attribute) +#if __has_attribute(returns_nonnull) #define PROTOBUF_RETURNS_NONNULL __attribute__((returns_nonnull)) -#else -#define PROTOBUF_RETURNS_NONNULL #endif #endif +#endif +#ifndef PROTOBUF_RETURNS_NONNULL +#define PROTOBUF_RETURNS_NONNULL +#endif #if defined(__has_cpp_attribute) #if __has_cpp_attribute(clang::reinitializes) @@ -425,6 +443,10 @@ #undef min #pragma push_macro("max") #undef max +#pragma push_macro("NEAR") +#undef NEAR +#pragma push_macro("NO_DATA") +#undef NO_DATA #pragma push_macro("REASON_UNKNOWN") #undef REASON_UNKNOWN #pragma push_macro("SERVICE_DISABLED") @@ -433,15 +455,13 @@ #undef SEVERITY_ERROR #pragma push_macro("STRICT") #undef STRICT +#pragma push_macro("timezone") +#undef timezone #endif // _MSC_VER #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) // Don't let Objective-C Macros interfere with proto identifiers with the same // name. -#pragma push_macro("YES") -#undef YES -#pragma push_macro("NO") -#undef NO #pragma push_macro("DEBUG") #undef DEBUG #pragma push_macro("TRUE") @@ -528,3 +548,59 @@ // This experiment is purely for the purpose of gathering data. All code guarded // by this flag is supposed to be removed after this experiment. // #define PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT + +#if defined(__cpp_constinit) +#define PROTOBUF_CONSTINIT constinit +#elif defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::require_constant_initialization) +#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]] +#endif +#endif +#ifndef PROTOBUF_CONSTINIT +#define PROTOBUF_CONSTINIT +#endif + +// Some constructors can't be constexpr under MSVC, but given that MSVC will not +// do constant initialization of globals anyway we can omit `constexpr` from +// them. These constructors are marked with PROTOBUF_MAYBE_CONSTEXPR +#if defined(_MSC_VER) +#define PROTOBUF_MAYBE_CONSTEXPR +#else +#define PROTOBUF_MAYBE_CONSTEXPR constexpr +#endif + +#if _MSC_VER +#define PROTOBUF_DISABLE_MSVC_UNION_WARNING \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4582)) \ + __pragma(warning(disable : 4583)) + +#define PROTOBUF_ENABLE_MSVC_UNION_WARNING \ + __pragma(warning(pop)) +#else +#define PROTOBUF_DISABLE_MSVC_UNION_WARNING +#define PROTOBUF_ENABLE_MSVC_UNION_WARNING +#endif + +#if defined(__cpp_constinit) +#define PROTOBUF_CONSTINIT constinit +#elif defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::require_constant_initialization) +#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]] +#endif +#endif +#ifndef PROTOBUF_CONSTINIT +#define PROTOBUF_CONSTINIT +#endif + +// Some globals with an empty non-trivial destructor are annotated with +// no_destroy for performance reasons. It reduces the cost of these globals in +// non-opt mode and under sanitizers. +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::no_destroy) +#define PROTOBUF_ATTRIBUTE_NO_DESTROY [[clang::no_destroy]] +#endif +#endif +#if !defined(PROTOBUF_ATTRIBUTE_NO_DESTROY) +#define PROTOBUF_ATTRIBUTE_NO_DESTROY +#endif diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc index 6b3751055f..d1414285e4 100644 --- a/src/google/protobuf/port_undef.inc +++ b/src/google/protobuf/port_undef.inc @@ -72,6 +72,11 @@ #undef PROTOBUF_FINAL #undef PROTOBUF_THREAD_LOCAL #undef PROTOBUF_MESSAGE_OWNED_ARENA_EXPERIMENT +#undef PROTOBUF_DISABLE_MSVC_UNION_WARNING +#undef PROTOBUF_ENABLE_MSVC_UNION_WARNING +#undef PROTOBUF_CONSTINIT +#undef PROTOBUF_MAYBE_CONSTEXPR +#undef PROTOBUF_ATTRIBUTE_NO_DESTROY // Restore macro that may have been #undef'd in port_def.inc. #ifdef _MSC_VER @@ -88,16 +93,17 @@ #pragma pop_macro("OPTIONAL") #pragma pop_macro("min") #pragma pop_macro("max") +#pragma pop_macro("NEAR") +#pragma pop_macro("NO_DATA") #pragma pop_macro("NO_ERROR") #pragma pop_macro("REASON_UNKNOWN") #pragma pop_macro("SERVICE_DISABLED") #pragma pop_macro("SEVERITY_ERROR") #pragma pop_macro("STRICT") +#pragma pop_macro("timezone") #endif #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER) -#pragma pop_macro("YES") -#pragma pop_macro("NO") #pragma pop_macro("DEBUG") #pragma pop_macro("TRUE") #pragma pop_macro("FALSE") diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc index ce3f091df9..29fc5dbaaf 100644 --- a/src/google/protobuf/reflection_ops.cc +++ b/src/google/protobuf/reflection_ops.cc @@ -43,7 +43,6 @@ #include #include #include -#include #include @@ -86,9 +85,7 @@ void ReflectionOps::Merge(const Message& from, Message* to) { std::vector fields; from_reflection->ListFieldsOmitStripped(from, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; - + for (const FieldDescriptor* field : fields) { if (field->is_repeated()) { // Use map reflection if both are in map status and have the // same map type to avoid sync with repeated field. @@ -181,8 +178,8 @@ void ReflectionOps::Clear(Message* message) { std::vector fields; reflection->ListFieldsOmitStripped(*message, &fields); - for (int i = 0; i < fields.size(); i++) { - reflection->ClearField(message, fields[i]); + for (const FieldDescriptor* field : fields) { + reflection->ClearField(message, field); } reflection->MutableUnknownFields(message)->Clear(); @@ -271,8 +268,7 @@ bool ReflectionOps::IsInitialized(const Message& message) { // Should be safe to skip stripped fields because required fields are not // stripped. reflection->ListFieldsOmitStripped(message, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; + for (const FieldDescriptor* field : fields) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field->is_map()) { @@ -330,8 +326,7 @@ void ReflectionOps::DiscardUnknownFields(Message* message) { // messages present. std::vector fields; reflection->ListFields(*message, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; + for (const FieldDescriptor* field : fields) { // Skip over non-message fields. if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { continue; @@ -402,8 +397,7 @@ void ReflectionOps::FindInitializationErrors(const Message& message, // Check sub-messages. std::vector fields; reflection->ListFieldsOmitStripped(message, &fields); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; + for (const FieldDescriptor* field : fields) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (field->is_repeated()) { diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index c1c4774685..26d5847331 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -169,7 +169,7 @@ class RepeatedField final { "We only support types that have an alignment smaller than Arena"); public: - RepeatedField(); + constexpr RepeatedField(); explicit RepeatedField(Arena* arena); RepeatedField(const RepeatedField& other); template @@ -577,7 +577,7 @@ struct IsMovable // }; class PROTOBUF_EXPORT RepeatedPtrFieldBase { protected: - RepeatedPtrFieldBase(); + constexpr RepeatedPtrFieldBase(); explicit RepeatedPtrFieldBase(Arena* arena); ~RepeatedPtrFieldBase() { #ifndef NDEBUG @@ -920,7 +920,7 @@ class StringTypeHandler { template class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { public: - RepeatedPtrField(); + constexpr RepeatedPtrField(); explicit RepeatedPtrField(Arena* arena); RepeatedPtrField(const RepeatedPtrField& other); @@ -1180,7 +1180,7 @@ class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { // implementation ==================================================== template -inline RepeatedField::RepeatedField() +constexpr RepeatedField::RepeatedField() : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {} template @@ -1647,7 +1647,7 @@ struct ElementCopier { namespace internal { -inline RepeatedPtrFieldBase::RepeatedPtrFieldBase() +constexpr RepeatedPtrFieldBase::RepeatedPtrFieldBase() : arena_(NULL), current_size_(0), total_size_(0), rep_(NULL) {} inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(Arena* arena) @@ -2090,7 +2090,8 @@ class RepeatedPtrField::TypeHandler : public internal::StringTypeHandler {}; template -inline RepeatedPtrField::RepeatedPtrField() : RepeatedPtrFieldBase() {} +constexpr RepeatedPtrField::RepeatedPtrField() + : RepeatedPtrFieldBase() {} template inline RepeatedPtrField::RepeatedPtrField(Arena* arena) diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 8de9504dc0..4072f47b6c 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -65,6 +65,11 @@ namespace { using ::protobuf_unittest::TestAllTypes; using ::testing::ElementsAre; +TEST(RepeatedField, ConstInit) { + PROTOBUF_CONSTINIT static RepeatedField field{}; // NOLINT + EXPECT_TRUE(field.empty()); +} + // Test operations on a small RepeatedField. TEST(RepeatedField, Small) { RepeatedField field; @@ -827,6 +832,11 @@ TEST(RepeatedField, TestSAddFromSelf) { // RepeatedPtrField tests. These pretty much just mirror the RepeatedField // tests above. +TEST(RepeatedPtrField, ConstInit) { + PROTOBUF_CONSTINIT static RepeatedPtrField field{}; // NOLINT + EXPECT_TRUE(field.empty()); +} + TEST(RepeatedPtrField, Small) { RepeatedPtrField field; diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index c0eec7ae52..9a1520f2f3 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -95,7 +95,7 @@ SourceContext::SourceContext(const SourceContext& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_file_name().empty()) { - file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(), + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_file_name(), GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext) @@ -138,7 +138,7 @@ void SourceContext::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + file_name_.ClearToEmpty(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h index 4722d10ef6..9d08789d46 100644 --- a/src/google/protobuf/source_context.pb.h +++ b/src/google/protobuf/source_context.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -220,7 +219,7 @@ class PROTOBUF_EXPORT SourceContext PROTOBUF_FINAL : // string file_name = 1; inline void SourceContext::clear_file_name() { - file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + file_name_.ClearToEmpty(); } inline const std::string& SourceContext::file_name() const { // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name) @@ -239,31 +238,30 @@ inline const std::string& SourceContext::_internal_file_name() const { } inline void SourceContext::_internal_set_file_name(const std::string& value) { - file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void SourceContext::set_file_name(std::string&& value) { file_name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceContext.file_name) } inline void SourceContext::set_file_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name) } inline void SourceContext::set_file_name(const char* value, size_t size) { - file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name) } inline std::string* SourceContext::_internal_mutable_file_name() { - return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return file_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* SourceContext::release_file_name() { // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name) diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index fa08803277..3c837ecc84 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -546,7 +546,7 @@ void Value::clear_kind() { break; } case kStringValue: { - kind_.string_value_.Destroy(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + kind_.string_value_.Destroy(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); break; } case kBoolValue: { diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 315193c421..b28bdc8461 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -807,7 +806,7 @@ inline void Value::set_has_string_value() { } inline void Value::clear_string_value() { if (_internal_has_string_value()) { - kind_.string_value_.Destroy(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + kind_.string_value_.Destroy(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); clear_has_kind(); } } @@ -827,7 +826,7 @@ inline const std::string& Value::_internal_string_value() const { if (_internal_has_string_value()) { return kind_.string_value_.Get(); } - return *&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(); + return ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(); } inline void Value::_internal_set_string_value(const std::string& value) { if (!_internal_has_string_value()) { @@ -835,7 +834,7 @@ inline void Value::_internal_set_string_value(const std::string& value) { set_has_string_value(); kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } - kind_.string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Value::set_string_value(std::string&& value) { // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) @@ -845,7 +844,7 @@ inline void Value::set_string_value(std::string&& value) { kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } kind_.string_value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value) } inline void Value::set_string_value(const char* value) { @@ -855,7 +854,7 @@ inline void Value::set_string_value(const char* value) { set_has_string_value(); kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } - kind_.string_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value) } @@ -867,7 +866,7 @@ inline void Value::set_string_value(const char* value, kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } kind_.string_value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value) @@ -878,13 +877,14 @@ inline std::string* Value::_internal_mutable_string_value() { set_has_string_value(); kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); } - return kind_.string_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return kind_.string_value_.Mutable( + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Value::release_string_value() { // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value) if (_internal_has_string_value()) { clear_has_kind(); - return kind_.string_value_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return kind_.string_value_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); } else { return nullptr; } diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h index 0193301a22..c7a48dea54 100644 --- a/src/google/protobuf/stubs/bytestream.h +++ b/src/google/protobuf/stubs/bytestream.h @@ -256,11 +256,11 @@ class PROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink { // class PROTOBUF_EXPORT StringByteSink : public ByteSink { public: - explicit StringByteSink(string* dest) : dest_(dest) {} + explicit StringByteSink(std::string* dest) : dest_(dest) {} virtual void Append(const char* data, size_t n) override; private: - string* dest_; + std::string* dest_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink); }; diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc index 06f114abc7..cb11825ef7 100644 --- a/src/google/protobuf/stubs/bytestream_unittest.cc +++ b/src/google/protobuf/stubs/bytestream_unittest.cc @@ -64,7 +64,7 @@ class MockByteSource : public ByteSource { TEST(ByteSourceTest, CopyTo) { StringPiece data("Hello world!"); MockByteSource source(data, 3); - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, data.size()); @@ -75,7 +75,7 @@ TEST(ByteSourceTest, CopySubstringTo) { StringPiece data("Hello world!"); MockByteSource source(data, 3); source.Skip(1); - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, data.size() - 2); @@ -92,7 +92,7 @@ TEST(ByteSourceTest, LimitByteSource) { EXPECT_EQ(5, limit_source.Available()); { - string str; + std::string str; StringByteSink sink(&str); limit_source.CopyTo(&sink, limit_source.Available()); EXPECT_EQ("ello ", str); @@ -101,7 +101,7 @@ TEST(ByteSourceTest, LimitByteSource) { } { - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, source.Available()); EXPECT_EQ("world!", str); @@ -112,7 +112,7 @@ TEST(ByteSourceTest, LimitByteSource) { TEST(ByteSourceTest, CopyToStringByteSink) { StringPiece data("Hello world!"); MockByteSource source(data, 3); - string str; + std::string str; StringByteSink sink(&str); source.CopyTo(&sink, data.size()); EXPECT_EQ(data, str); @@ -121,7 +121,7 @@ TEST(ByteSourceTest, CopyToStringByteSink) { // Verify that ByteSink is subclassable and Flush() overridable. class FlushingByteSink : public StringByteSink { public: - explicit FlushingByteSink(string* dest) : StringByteSink(dest) {} + explicit FlushingByteSink(std::string* dest) : StringByteSink(dest) {} virtual void Flush() { Append("z", 1); } private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink); @@ -134,7 +134,7 @@ void WriteAndFlush(ByteSink* s) { } TEST(ByteSinkTest, Flush) { - string str; + std::string str; FlushingByteSink f_sink(&str); WriteAndFlush(&f_sink); EXPECT_STREQ("abcz", str.c_str()); diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h index b7a3a82910..43d546d199 100644 --- a/src/google/protobuf/stubs/callback.h +++ b/src/google/protobuf/stubs/callback.h @@ -62,12 +62,12 @@ namespace protobuf { // Note that NewCallback() is a bit touchy regarding argument types. Generally, // the values you provide for the parameter bindings must exactly match the // types accepted by the callback function. For example: -// void Foo(string s); +// void Foo(std::string s); // NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string -// NewCallback(&Foo, string("foo")); // WORKS +// NewCallback(&Foo, std::string("foo")); // WORKS // Also note that the arguments cannot be references: -// void Foo(const string& s); -// string my_str; +// void Foo(const std::string& s); +// std::string my_str; // NewCallback(&Foo, my_str); // WON'T WORK: Can't use references. // However, correctly-typed pointers will work just fine. class PROTOBUF_EXPORT Closure { diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc index 30802b1bb4..bc150f56a9 100644 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -96,7 +96,7 @@ void VerifyVersion(int headerVersion, } } -string VersionString(int version) { +std::string VersionString(int version) { int major = version / 1000000; int minor = (version / 1000) % 1000; int micro = version % 1000; @@ -127,7 +127,7 @@ namespace internal { #if defined(__ANDROID__) inline void DefaultLogHandler(LogLevel level, const char* filename, int line, - const string& message) { + const std::string& message) { if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { return; } @@ -162,7 +162,7 @@ inline void DefaultLogHandler(LogLevel level, const char* filename, int line, #else void DefaultLogHandler(LogLevel level, const char* filename, int line, - const string& message) { + const std::string& message) { if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { return; } @@ -177,14 +177,14 @@ void DefaultLogHandler(LogLevel level, const char* filename, int line, #endif void NullLogHandler(LogLevel /* level */, const char* /* filename */, - int /* line */, const string& /* message */) { + int /* line */, const std::string& /* message */) { // Nothing. } static LogHandler* log_handler_ = &DefaultLogHandler; static std::atomic log_silencer_count_ = ATOMIC_VAR_INIT(0); -LogMessage& LogMessage::operator<<(const string& value) { +LogMessage& LogMessage::operator<<(const std::string& value) { message_ += value; return *this; } diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index 5852458922..c55e452505 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -53,7 +53,7 @@ TEST(VersionTest, VersionMatchesConfig) { // Verify that the version string specified in config.h matches the one // in common.h. The config.h version is a string which may have a suffix // like "beta" or "rc1", so we remove that. - string version = PACKAGE_VERSION; + std::string version = PACKAGE_VERSION; int pos = 0; while (pos < version.size() && (ascii_isdigit(version[pos]) || version[pos] == '.')) { @@ -77,10 +77,10 @@ TEST(CommonTest, IntMinMaxConstants) { EXPECT_EQ(0, kuint64max + 1); } -std::vector captured_messages_; +std::vector captured_messages_; void CaptureLog(LogLevel level, const char* filename, int line, - const string& message) { + const std::string& message) { captured_messages_.push_back( strings::Substitute("$0 $1:$2: $3", implicit_cast(level), filename, line, message)); @@ -93,7 +93,7 @@ TEST(LoggingTest, DefaultLogging) { GOOGLE_LOG(WARNING) << "A warning."; GOOGLE_LOG(ERROR ) << "An error."; - string text = GetCapturedTestStderr(); + std::string text = GetCapturedTestStderr(); EXPECT_EQ( "[libprotobuf INFO " __FILE__ ":" + SimpleItoa(line + 1) + "] A message.\n" "[libprotobuf WARNING " __FILE__ ":" + SimpleItoa(line + 2) + "] A warning.\n" @@ -111,7 +111,7 @@ TEST(LoggingTest, NullLogging) { EXPECT_TRUE(SetLogHandler(old_handler) == nullptr); - string text = GetCapturedTestStderr(); + std::string text = GetCapturedTestStderr(); EXPECT_EQ("", text); } @@ -167,10 +167,10 @@ class ClosureTest : public testing::Test { static void SetA123Function() { current_instance_->a_ = 123; } void SetAMethod(int a) { a_ = a; } - void SetCMethod(string c) { c_ = c; } + void SetCMethod(std::string c) { c_ = c; } static void SetAFunction(int a) { current_instance_->a_ = a; } - static void SetCFunction(string c) { current_instance_->c_ = c; } + static void SetCFunction(std::string c) { current_instance_->c_ = c; } void SetABMethod(int a, const char* b) { a_ = a; b_ = b; } static void SetABFunction(int a, const char* b) { @@ -192,7 +192,7 @@ class ClosureTest : public testing::Test { int a_; const char* b_; - string c_; + std::string c_; Closure* permanent_closure_; static ClosureTest* current_instance_; @@ -231,15 +231,15 @@ TEST_F(ClosureTest, TestClosureMethod1) { } TEST_F(ClosureTest, TestClosureFunction1String) { - Closure* closure = NewCallback(&SetCFunction, string("test")); + Closure* closure = NewCallback(&SetCFunction, std::string("test")); EXPECT_NE("test", c_); closure->Run(); EXPECT_EQ("test", c_); } TEST_F(ClosureTest, TestClosureMethod1String) { - Closure* closure = NewCallback(current_instance_, - &ClosureTest::SetCMethod, string("test")); + Closure* closure = NewCallback(current_instance_, &ClosureTest::SetCMethod, + std::string("test")); EXPECT_NE("test", c_); closure->Run(); EXPECT_EQ("test", c_); diff --git a/src/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h deleted file mode 100644 index 76c8a3aea6..0000000000 --- a/src/google/protobuf/stubs/fastmem.h +++ /dev/null @@ -1,157 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Fast memory copying and comparison routines. -// strings::fastmemcmp_inlined() replaces memcmp() -// strings::memcpy_inlined() replaces memcpy() -// strings::memeq(a, b, n) replaces memcmp(a, b, n) == 0 -// -// strings::*_inlined() routines are inline versions of the -// routines exported by this module. Sometimes using the inlined -// versions is faster. Measure before using the inlined versions. -// -// Performance measurement: -// strings::fastmemcmp_inlined -// Analysis: memcmp, fastmemcmp_inlined, fastmemcmp -// 2012-01-30 - -#ifndef GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ -#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ - -#include -#include -#include - -#include - -#include - -namespace google { -namespace protobuf { -namespace internal { - -// Return true if the n bytes at a equal the n bytes at b. -// The regions are allowed to overlap. -// -// The performance is similar to the performance memcmp(), but faster for -// moderately-sized inputs, or inputs that share a common prefix and differ -// somewhere in their last 8 bytes. Further optimizations can be added later -// if it makes sense to do so.:w -inline bool memeq(const char* a, const char* b, size_t n) { - size_t n_rounded_down = n & ~static_cast(7); - if (PROTOBUF_PREDICT_FALSE(n_rounded_down == 0)) { // n <= 7 - return memcmp(a, b, n) == 0; - } - // n >= 8 - uint64 u = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b); - uint64 v = GOOGLE_UNALIGNED_LOAD64(a + n - 8) ^ GOOGLE_UNALIGNED_LOAD64(b + n - 8); - if ((u | v) != 0) { // The first or last 8 bytes differ. - return false; - } - a += 8; - b += 8; - n = n_rounded_down - 8; - if (n > 128) { - // As of 2012, memcmp on x86-64 uses a big unrolled loop with SSE2 - // instructions, and while we could try to do something faster, it - // doesn't seem worth pursuing. - return memcmp(a, b, n) == 0; - } - for (; n >= 16; n -= 16) { - uint64 x = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b); - uint64 y = GOOGLE_UNALIGNED_LOAD64(a + 8) ^ GOOGLE_UNALIGNED_LOAD64(b + 8); - if ((x | y) != 0) { - return false; - } - a += 16; - b += 16; - } - // n must be 0 or 8 now because it was a multiple of 8 at the top of the loop. - return n == 0 || GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b); -} - -inline int fastmemcmp_inlined(const char *a, const char *b, size_t n) { - if (n >= 64) { - return memcmp(a, b, n); - } - const char* a_limit = a + n; - while (a + sizeof(uint64) <= a_limit && - GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b)) { - a += sizeof(uint64); - b += sizeof(uint64); - } - if (a + sizeof(uint32) <= a_limit && - GOOGLE_UNALIGNED_LOAD32(a) == GOOGLE_UNALIGNED_LOAD32(b)) { - a += sizeof(uint32); - b += sizeof(uint32); - } - while (a < a_limit) { - int d = - static_cast(static_cast(*a++) - static_cast(*b++)); - if (d) return d; - } - return 0; -} - -// The standard memcpy operation is slow for variable small sizes. -// This implementation inlines the optimal realization for sizes 1 to 16. -// To avoid code bloat don't use it in case of not performance-critical spots, -// nor when you don't expect very frequent values of size <= 16. -inline void memcpy_inlined(char *dst, const char *src, size_t size) { - // Compiler inlines code with minimal amount of data movement when third - // parameter of memcpy is a constant. - switch (size) { - case 1: memcpy(dst, src, 1); break; - case 2: memcpy(dst, src, 2); break; - case 3: memcpy(dst, src, 3); break; - case 4: memcpy(dst, src, 4); break; - case 5: memcpy(dst, src, 5); break; - case 6: memcpy(dst, src, 6); break; - case 7: memcpy(dst, src, 7); break; - case 8: memcpy(dst, src, 8); break; - case 9: memcpy(dst, src, 9); break; - case 10: memcpy(dst, src, 10); break; - case 11: memcpy(dst, src, 11); break; - case 12: memcpy(dst, src, 12); break; - case 13: memcpy(dst, src, 13); break; - case 14: memcpy(dst, src, 14); break; - case 15: memcpy(dst, src, 15); break; - case 16: memcpy(dst, src, 16); break; - default: memcpy(dst, src, size); break; - } -} - -} // namespace internal -} // namespace protobuf -} // namespace google - -#include - -#endif // GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index e2d239279f..a7ec068074 100644 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h @@ -108,14 +108,6 @@ struct hash > { } }; -// Used by GCC/SGI STL only. (Why isn't this provided by the standard -// library? :( ) -struct streq { - inline bool operator()(const char* a, const char* b) const { - return strcmp(a, b) == 0; - } -}; - } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc index 2bfbe0b42b..03b37c365b 100644 --- a/src/google/protobuf/stubs/status.cc +++ b/src/google/protobuf/stubs/status.cc @@ -38,7 +38,7 @@ namespace google { namespace protobuf { namespace util { namespace error { -inline string CodeEnumToString(error::Code code) { +inline std::string CodeEnumToString(error::Code code) { switch (code) { case OK: return "OK"; @@ -111,7 +111,7 @@ bool Status::operator==(const Status& x) const { error_message_ == x.error_message_; } -string Status::ToString() const { +std::string Status::ToString() const { if (error_code_ == error::OK) { return "OK"; } else { diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h index 04ecc633bc..bededad541 100644 --- a/src/google/protobuf/stubs/status.h +++ b/src/google/protobuf/stubs/status.h @@ -106,11 +106,11 @@ class PROTOBUF_EXPORT Status { } // Return a combination of the error code name and message. - string ToString() const; + std::string ToString() const; private: error::Code error_code_; - string error_message_; + std::string error_message_; }; // Prints a human-readable representation of 'x' to 'os'. diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc index 9a18778fba..8f4398c9c9 100644 --- a/src/google/protobuf/stubs/status_test.cc +++ b/src/google/protobuf/stubs/status_test.cc @@ -101,7 +101,7 @@ TEST(Status, AssignEmpty) { util::Status a(util::error::UNKNOWN, "message"); util::Status b; a = b; - ASSERT_EQ(string("OK"), a.ToString()); + ASSERT_EQ(std::string("OK"), a.ToString()); ASSERT_TRUE(b.ok()); ASSERT_TRUE(a.ok()); } diff --git a/src/google/protobuf/stubs/stl_util.h b/src/google/protobuf/stubs/stl_util.h index aa81eb6f72..d01f9ec944 100644 --- a/src/google/protobuf/stubs/stl_util.h +++ b/src/google/protobuf/stubs/stl_util.h @@ -44,7 +44,7 @@ namespace protobuf { // improve performance. However, since it's totally non-portable it has no // place in open source code. Feel free to fill this function in with your // own disgusting hack if you want the perf boost. -inline void STLStringResizeUninitialized(string* s, size_t new_size) { +inline void STLStringResizeUninitialized(std::string* s, size_t new_size) { s->resize(new_size); } @@ -60,7 +60,7 @@ inline void STLStringResizeUninitialized(string* s, size_t new_size) { // (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530) // proposes this as the method. According to Matt Austern, this should // already work on all current implementations. -inline char* string_as_array(string* str) { +inline char* string_as_array(std::string* str) { // DO NOT USE const_cast(str->data())! See the unittest for why. return str->empty() ? nullptr : &*str->begin(); } diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc index d9a32d03aa..846e1aed3d 100644 --- a/src/google/protobuf/stubs/stringpiece_unittest.cc +++ b/src/google/protobuf/stubs/stringpiece_unittest.cc @@ -87,7 +87,7 @@ TEST(StringPiece, Ctor) { #if defined(HAS_GLOBAL_STRING) { // ::string - string bonjour = "bonjour"; + std::string bonjour = "bonjour"; StringPiece s40(bonjour); EXPECT_TRUE(s40.data() == bonjour.data()); EXPECT_EQ(7, s40.length()); @@ -100,9 +100,9 @@ TEST(StringPiece, Ctor) { } TEST(StringPiece, STLComparator) { - string s1("foo"); - string s2("bar"); - string s3("baz"); + std::string s1("foo"); + std::string s2("bar"); + std::string s3("baz"); StringPiece p1(s1); StringPiece p2(s2); @@ -207,13 +207,13 @@ TEST(StringPiece, ComparisonOperators) { COMPARE(true, >, "b", "aa"); COMPARE(true, >, "bb", "aa"); - string x; + std::string x; for (int i = 0; i < 256; i++) { x += 'a'; - string y = x; + std::string y = x; COMPARE(true, ==, x, y); for (int j = 0; j < i; j++) { - string z = x; + std::string z = x; z[j] = 'b'; // Differs in position 'j' COMPARE(false, ==, x, z); COMPARE(true, <, x, z); @@ -240,7 +240,7 @@ TEST(StringPiece, STL1) { const StringPiece c("xyz"); const StringPiece d("foobar"); const StringPiece e; - string temp("123"); + std::string temp("123"); temp += '\0'; temp += "456"; const StringPiece f(temp); @@ -315,7 +315,7 @@ TEST(StringPiece, STL2) { EXPECT_TRUE(d.data() == nullptr); EXPECT_TRUE(d.begin() == d.end()); - EXPECT_EQ(StringPiece::npos, string::npos); + EXPECT_EQ(StringPiece::npos, std::string::npos); EXPECT_EQ(a.find(b), 0); EXPECT_EQ(a.find(b, 1), StringPiece::npos); @@ -336,15 +336,15 @@ TEST(StringPiece, STL2) { EXPECT_EQ(d.find(b, 4), StringPiece::npos); EXPECT_EQ(e.find(b, 7), StringPiece::npos); - size_t empty_search_pos = string().find(string()); + size_t empty_search_pos = std::string().find(std::string()); EXPECT_EQ(d.find(d), empty_search_pos); EXPECT_EQ(d.find(e), empty_search_pos); EXPECT_EQ(e.find(d), empty_search_pos); EXPECT_EQ(e.find(e), empty_search_pos); - EXPECT_EQ(d.find(d, 4), string().find(string(), 4)); - EXPECT_EQ(d.find(e, 4), string().find(string(), 4)); - EXPECT_EQ(e.find(d, 4), string().find(string(), 4)); - EXPECT_EQ(e.find(e, 4), string().find(string(), 4)); + EXPECT_EQ(d.find(d, 4), std::string().find(std::string(), 4)); + EXPECT_EQ(d.find(e, 4), std::string().find(std::string(), 4)); + EXPECT_EQ(e.find(d, 4), std::string().find(std::string(), 4)); + EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4)); EXPECT_EQ(a.find('a'), 0); EXPECT_EQ(a.find('c'), 2); @@ -376,8 +376,8 @@ TEST(StringPiece, STL2) { EXPECT_EQ(a.rfind(c, 0), StringPiece::npos); EXPECT_EQ(b.rfind(c), StringPiece::npos); EXPECT_EQ(b.rfind(c, 0), StringPiece::npos); - EXPECT_EQ(a.rfind(d), a.as_string().rfind(string())); - EXPECT_EQ(a.rfind(e), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(d), a.as_string().rfind(std::string())); + EXPECT_EQ(a.rfind(e), a.as_string().rfind(std::string())); EXPECT_EQ(a.rfind(d, 12), 12); EXPECT_EQ(a.rfind(e, 17), 17); EXPECT_EQ(a.rfind(g), StringPiece::npos); @@ -386,14 +386,14 @@ TEST(StringPiece, STL2) { EXPECT_EQ(d.rfind(b, 4), StringPiece::npos); EXPECT_EQ(e.rfind(b, 7), StringPiece::npos); // empty string nonsense - EXPECT_EQ(d.rfind(d, 4), string().rfind(string())); - EXPECT_EQ(e.rfind(d, 7), string().rfind(string())); - EXPECT_EQ(d.rfind(e, 4), string().rfind(string())); - EXPECT_EQ(e.rfind(e, 7), string().rfind(string())); - EXPECT_EQ(d.rfind(d), string().rfind(string())); - EXPECT_EQ(e.rfind(d), string().rfind(string())); - EXPECT_EQ(d.rfind(e), string().rfind(string())); - EXPECT_EQ(e.rfind(e), string().rfind(string())); + EXPECT_EQ(d.rfind(d, 4), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(d, 7), std::string().rfind(std::string())); + EXPECT_EQ(d.rfind(e, 4), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(e, 7), std::string().rfind(std::string())); + EXPECT_EQ(d.rfind(d), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(d), std::string().rfind(std::string())); + EXPECT_EQ(d.rfind(e), std::string().rfind(std::string())); + EXPECT_EQ(e.rfind(e), std::string().rfind(std::string())); EXPECT_EQ(g.rfind('o'), 8); EXPECT_EQ(g.rfind('q'), StringPiece::npos); @@ -566,7 +566,7 @@ TEST(StringPiece, STL2) { // empty string nonsense EXPECT_EQ(StringPiece(d, 0, 99), e); // Verify that they work taking an actual string, not just a StringPiece. - string a2 = a.as_string(); + std::string a2 = a.as_string(); EXPECT_EQ(StringPiece(a2, 0, 3), b); EXPECT_EQ(StringPiece(a2, 23), c); EXPECT_EQ(StringPiece(a2, 23, 3), c); @@ -577,12 +577,12 @@ TEST(StringPiece, STL2) { TEST(StringPiece, Custom) { StringPiece a("foobar"); - string s1("123"); + std::string s1("123"); s1 += '\0'; s1 += "456"; StringPiece b(s1); StringPiece e; - string s2; + std::string s2; // CopyToString a.CopyToString(&s2); @@ -666,16 +666,16 @@ TEST(StringPiece, Custom) { EXPECT_NE(c, a); // as_string - string s3(a.as_string().c_str(), 7); + std::string s3(a.as_string().c_str(), 7); EXPECT_EQ(c, s3); - string s4(e.as_string()); + std::string s4(e.as_string()); EXPECT_TRUE(s4.empty()); // ToString { - string s5(a.ToString().c_str(), 7); + std::string s5(a.ToString().c_str(), 7); EXPECT_EQ(c, s5); - string s6(e.ToString()); + std::string s6(e.ToString()); EXPECT_TRUE(s6.empty()); } @@ -747,12 +747,12 @@ TEST(StringPiece, Comparisons2) { } TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { - EXPECT_EQ("hello", string("hello")); - EXPECT_LT("hello", string("world")); + EXPECT_EQ("hello", std::string("hello")); + EXPECT_LT("hello", std::string("world")); } TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) { - EXPECT_EQ(StringPiece("hello"), string("hello")); + EXPECT_EQ(StringPiece("hello"), std::string("hello")); EXPECT_EQ("hello", StringPiece("hello")); } diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc index e6019fc664..2603164936 100644 --- a/src/google/protobuf/stubs/stringprintf.cc +++ b/src/google/protobuf/stubs/stringprintf.cc @@ -54,7 +54,7 @@ enum { IS_COMPILER_MSVC = 1 }; enum { IS_COMPILER_MSVC = 0 }; #endif -void StringAppendV(string* dst, const char* format, va_list ap) { +void StringAppendV(std::string* dst, const char* format, va_list ap) { // First try with a small fixed size buffer static const int kSpaceLength = 1024; char space[kSpaceLength]; @@ -105,17 +105,16 @@ void StringAppendV(string* dst, const char* format, va_list ap) { delete[] buf; } - -string StringPrintf(const char* format, ...) { +std::string StringPrintf(const char* format, ...) { va_list ap; va_start(ap, format); - string result; + std::string result; StringAppendV(&result, format, ap); va_end(ap); return result; } -const string& SStringPrintf(string* dst, const char* format, ...) { +const std::string& SStringPrintf(std::string* dst, const char* format, ...) { va_list ap; va_start(ap, format); dst->clear(); @@ -124,7 +123,7 @@ const string& SStringPrintf(string* dst, const char* format, ...) { return *dst; } -void StringAppendF(string* dst, const char* format, ...) { +void StringAppendF(std::string* dst, const char* format, ...) { va_list ap; va_start(ap, format); StringAppendV(dst, format, ap); @@ -139,7 +138,8 @@ const int kStringPrintfVectorMaxArgs = 32; // and we can fix the problem or protect against an attack. static const char string_printf_empty_block[256] = { '\0' }; -string StringPrintfVector(const char* format, const std::vector& v) { +std::string StringPrintfVector(const char* format, + const std::vector& v) { GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs) << "StringPrintfVector currently only supports up to " << kStringPrintfVectorMaxArgs << " arguments. " diff --git a/src/google/protobuf/stubs/stringprintf.h b/src/google/protobuf/stubs/stringprintf.h index 253d736a21..e3858be130 100644 --- a/src/google/protobuf/stubs/stringprintf.h +++ b/src/google/protobuf/stubs/stringprintf.h @@ -52,18 +52,20 @@ namespace google { namespace protobuf { // Return a C++ string -PROTOBUF_EXPORT extern string StringPrintf(const char* format, ...); +PROTOBUF_EXPORT extern std::string StringPrintf(const char* format, ...); // Store result into a supplied string and return it -PROTOBUF_EXPORT extern const string& SStringPrintf(string* dst, - const char* format, ...); +PROTOBUF_EXPORT extern const std::string& SStringPrintf(std::string* dst, + const char* format, + ...); // Append result to a supplied string -PROTOBUF_EXPORT extern void StringAppendF(string* dst, const char* format, ...); +PROTOBUF_EXPORT extern void StringAppendF(std::string* dst, const char* format, + ...); // Lower-level routine that takes a va_list and appends to a specified // string. All other routines are just convenience wrappers around it. -PROTOBUF_EXPORT extern void StringAppendV(string* dst, const char* format, +PROTOBUF_EXPORT extern void StringAppendV(std::string* dst, const char* format, va_list ap); // The max arguments supported by StringPrintfVector @@ -72,8 +74,8 @@ PROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs; // You can use this version when all your arguments are strings, but // you don't know how many arguments you'll have at compile time. // StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs -PROTOBUF_EXPORT extern string StringPrintfVector(const char* format, - const std::vector& v); +PROTOBUF_EXPORT extern std::string StringPrintfVector( + const char* format, const std::vector& v); } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/stringprintf_unittest.cc b/src/google/protobuf/stubs/stringprintf_unittest.cc index 7fcbf500eb..37172a9d97 100644 --- a/src/google/protobuf/stubs/stringprintf_unittest.cc +++ b/src/google/protobuf/stubs/stringprintf_unittest.cc @@ -49,7 +49,7 @@ TEST(StringPrintfTest, Empty) { // so we do not allow them in google3. EXPECT_EQ("", StringPrintf("")); #endif - EXPECT_EQ("", StringPrintf("%s", string().c_str())); + EXPECT_EQ("", StringPrintf("%s", std::string().c_str())); EXPECT_EQ("", StringPrintf("%s", "")); } @@ -61,26 +61,26 @@ TEST(StringPrintfTest, Misc) { } TEST(StringAppendFTest, Empty) { - string value("Hello"); + std::string value("Hello"); const char* empty = ""; StringAppendF(&value, "%s", empty); EXPECT_EQ("Hello", value); } TEST(StringAppendFTest, EmptyString) { - string value("Hello"); + std::string value("Hello"); StringAppendF(&value, "%s", ""); EXPECT_EQ("Hello", value); } TEST(StringAppendFTest, String) { - string value("Hello"); + std::string value("Hello"); StringAppendF(&value, " %s", "World"); EXPECT_EQ("Hello World", value); } TEST(StringAppendFTest, Int) { - string value("Hello"); + std::string value("Hello"); StringAppendF(&value, " %d", 123); EXPECT_EQ("Hello 123", value); } @@ -96,7 +96,7 @@ TEST(StringPrintfTest, Multibyte) { setlocale(LC_CTYPE, "en_US.utf8"); const char kInvalidCodePoint[] = "\375\067s"; - string value = StringPrintf("%.*s", 3, kInvalidCodePoint); + std::string value = StringPrintf("%.*s", 3, kInvalidCodePoint); // In some versions of glibc (e.g. eglibc-2.11.1, aka GRTEv2), snprintf // returns error given an invalid codepoint. Other versions @@ -122,7 +122,7 @@ TEST(StringPrintfTest, NoMultibyte) { // No multibyte handling, but the string contains funny chars. char* old_locale = setlocale(LC_CTYPE, nullptr); setlocale(LC_CTYPE, "POSIX"); - string value = StringPrintf("%.*s", 3, "\375\067s"); + std::string value = StringPrintf("%.*s", 3, "\375\067s"); setlocale(LC_CTYPE, old_locale); EXPECT_EQ("\375\067s", value); } @@ -132,7 +132,7 @@ TEST(StringPrintfTest, DontOverwriteErrno) { // something significantly larger than what people are normally // printing in their badly written PLOG() statements. errno = ECHILD; - string value = StringPrintf("Hello, %s!", "World"); + std::string value = StringPrintf("Hello, %s!", "World"); EXPECT_EQ(ECHILD, errno); } @@ -142,7 +142,7 @@ TEST(StringPrintfTest, LargeBuf) { char* buf = new char[n+1]; memset(buf, ' ', n); buf[n] = 0; - string value = StringPrintf("%s", buf); + std::string value = StringPrintf("%s", buf); EXPECT_EQ(buf, value); delete[] buf; } diff --git a/src/google/protobuf/stubs/structurally_valid_unittest.cc b/src/google/protobuf/stubs/structurally_valid_unittest.cc index eec07a87ab..ebd9c42306 100644 --- a/src/google/protobuf/stubs/structurally_valid_unittest.cc +++ b/src/google/protobuf/stubs/structurally_valid_unittest.cc @@ -43,7 +43,8 @@ TEST(StructurallyValidTest, ValidUTF8String) { // On GCC, this string can be written as: // "abcd 1234 - \u2014\u2013\u2212" // MSVC seems to interpret \u differently. - string valid_str("abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789"); + std::string valid_str( + "abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789"); EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data(), valid_str.size())); // Additional check for pointer alignment @@ -54,7 +55,7 @@ TEST(StructurallyValidTest, ValidUTF8String) { } TEST(StructurallyValidTest, InvalidUTF8String) { - const string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789"); + const std::string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789"); EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data(), invalid_str.size())); // Additional check for pointer alignment diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 27225942ac..2ecdb2bf72 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -84,7 +84,7 @@ inline bool isprint(char c) { // Replaces any occurrence of the character 'remove' (or the characters // in 'remove') with the character 'replacewith'. // ---------------------------------------------------------------------- -void ReplaceCharacters(string *s, const char *remove, char replacewith) { +void ReplaceCharacters(std::string *s, const char *remove, char replacewith) { const char *str_start = s->c_str(); const char *str = str_start; for (str = strpbrk(str, remove); @@ -94,7 +94,7 @@ void ReplaceCharacters(string *s, const char *remove, char replacewith) { } } -void StripWhitespace(string* str) { +void StripWhitespace(std::string *str) { int str_length = str->length(); // Strip off leading whitespace. @@ -118,7 +118,7 @@ void StripWhitespace(string* str) { --last; } if (last != (str_length - 1) && last >= 0) { - str->erase(last + 1, string::npos); + str->erase(last + 1, std::string::npos); } } @@ -129,19 +129,19 @@ void StripWhitespace(string* str) { // it only replaces the first instance of "old." // ---------------------------------------------------------------------- -void StringReplace(const string& s, const string& oldsub, - const string& newsub, bool replace_all, - string* res) { +void StringReplace(const std::string &s, const std::string &oldsub, + const std::string &newsub, bool replace_all, + std::string *res) { if (oldsub.empty()) { res->append(s); // if empty, append the given string. return; } - string::size_type start_pos = 0; - string::size_type pos; + std::string::size_type start_pos = 0; + std::string::size_type pos; do { pos = s.find(oldsub, start_pos); - if (pos == string::npos) { + if (pos == std::string::npos) { break; } res->append(s, start_pos, pos - start_pos); @@ -160,9 +160,9 @@ void StringReplace(const string& s, const string& oldsub, // happened or not. // ---------------------------------------------------------------------- -string StringReplace(const string& s, const string& oldsub, - const string& newsub, bool replace_all) { - string ret; +std::string StringReplace(const std::string &s, const std::string &oldsub, + const std::string &newsub, bool replace_all) { + std::string ret; StringReplace(s, oldsub, newsub, replace_all, &ret); return ret; } @@ -195,11 +195,11 @@ static inline void SplitStringToIteratorUsing(StringPiece full, return; } - string::size_type begin_index, end_index; + std::string::size_type begin_index, end_index; begin_index = full.find_first_not_of(delim); - while (begin_index != string::npos) { + while (begin_index != std::string::npos) { end_index = full.find_first_of(delim, begin_index); - if (end_index == string::npos) { + if (end_index == std::string::npos) { *result++ = std::string(full.substr(begin_index)); return; } @@ -210,8 +210,8 @@ static inline void SplitStringToIteratorUsing(StringPiece full, } void SplitStringUsing(StringPiece full, const char *delim, - std::vector *result) { - std::back_insert_iterator< std::vector > it(*result); + std::vector *result) { + std::back_insert_iterator > it(*result); SplitStringToIteratorUsing(full, delim, it); } @@ -230,12 +230,12 @@ template static inline void SplitStringToIteratorAllowEmpty(StringPiece full, const char *delim, int pieces, ITR &result) { - string::size_type begin_index, end_index; + std::string::size_type begin_index, end_index; begin_index = 0; for (int i = 0; (i < pieces-1) || (pieces == 0); i++) { end_index = full.find_first_of(delim, begin_index); - if (end_index == string::npos) { + if (end_index == std::string::npos) { *result++ = std::string(full.substr(begin_index)); return; } @@ -247,8 +247,8 @@ static inline void SplitStringToIteratorAllowEmpty(StringPiece full, } void SplitStringAllowEmpty(StringPiece full, const char *delim, - std::vector *result) { - std::back_insert_iterator > it(*result); + std::vector *result) { + std::back_insert_iterator > it(*result); SplitStringToIteratorAllowEmpty(full, delim, 0, it); } @@ -259,10 +259,8 @@ void SplitStringAllowEmpty(StringPiece full, const char *delim, // // ---------------------------------------------------------------------- template -static void JoinStringsIterator(const ITERATOR& start, - const ITERATOR& end, - const char* delim, - string* result) { +static void JoinStringsIterator(const ITERATOR &start, const ITERATOR &end, + const char *delim, std::string *result) { GOOGLE_CHECK(result != nullptr); result->clear(); int delim_length = strlen(delim); @@ -286,9 +284,8 @@ static void JoinStringsIterator(const ITERATOR& start, } } -void JoinStrings(const std::vector& components, - const char* delim, - string * result) { +void JoinStrings(const std::vector &components, const char *delim, + std::string *result) { JoinStringsIterator(components.begin(), components.end(), delim, result); } @@ -314,8 +311,8 @@ int UnescapeCEscapeSequences(const char* source, char* dest) { return UnescapeCEscapeSequences(source, dest, nullptr); } -int UnescapeCEscapeSequences(const char* source, char* dest, - std::vector *errors) { +int UnescapeCEscapeSequences(const char *source, char *dest, + std::vector *errors) { GOOGLE_DCHECK(errors == nullptr) << "Error reporting not implemented."; char* d = dest; @@ -370,8 +367,10 @@ int UnescapeCEscapeSequences(const char* source, char* dest, while (isxdigit(p[1])) // arbitrarily many hex digits ch = (ch << 4) + hex_digit_to_int(*++p); if (ch > 0xFF) - LOG_STRING(ERROR, errors) << "Value of " << - "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits"; + LOG_STRING(ERROR, errors) + << "Value of " + << "\\" << std::string(hex_start, p + 1 - hex_start) + << " exceeds 8 bits"; *d++ = ch; break; } @@ -386,7 +385,7 @@ int UnescapeCEscapeSequences(const char* source, char* dest, } else { LOG_STRING(ERROR, errors) << "\\u must be followed by 4 hex digits: \\" - << string(hex_start, p+1-hex_start); + << std::string(hex_start, p+1-hex_start); break; } } @@ -405,7 +404,7 @@ int UnescapeCEscapeSequences(const char* source, char* dest, if (newrune > 0x10FFFF) { LOG_STRING(ERROR, errors) << "Value of \\" - << string(hex_start, p + 1 - hex_start) + << std::string(hex_start, p + 1 - hex_start) << " exceeds Unicode limit (0x10FFFF)"; break; } else { @@ -414,7 +413,7 @@ int UnescapeCEscapeSequences(const char* source, char* dest, } else { LOG_STRING(ERROR, errors) << "\\U must be followed by 8 hex digits: \\" - << string(hex_start, p+1-hex_start); + << std::string(hex_start, p+1-hex_start); break; } } @@ -446,12 +445,12 @@ int UnescapeCEscapeSequences(const char* source, char* dest, // In the first and second calls, the length of dest is returned. In the // the third call, the new string is returned. // ---------------------------------------------------------------------- -int UnescapeCEscapeString(const string& src, string* dest) { +int UnescapeCEscapeString(const std::string &src, std::string *dest) { return UnescapeCEscapeString(src, dest, nullptr); } -int UnescapeCEscapeString(const string& src, string* dest, - std::vector *errors) { +int UnescapeCEscapeString(const std::string &src, std::string *dest, + std::vector *errors) { std::unique_ptr unescaped(new char[src.size() + 1]); int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors); GOOGLE_CHECK(dest); @@ -459,10 +458,10 @@ int UnescapeCEscapeString(const string& src, string* dest, return len; } -string UnescapeCEscapeString(const string& src) { +std::string UnescapeCEscapeString(const std::string &src) { std::unique_ptr unescaped(new char[src.size() + 1]); int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), nullptr); - return string(unescaped.get(), len); + return std::string(unescaped.get(), len); } // ---------------------------------------------------------------------- @@ -559,7 +558,7 @@ static inline size_t CEscapedLength(StringPiece src) { // the required space using a lookup table, and also does not do any special // handling for Hex or UTF-8 characters. // ---------------------------------------------------------------------- -void CEscapeAndAppend(StringPiece src, string* dest) { +void CEscapeAndAppend(StringPiece src, std::string *dest) { size_t escaped_len = CEscapedLength(src); if (escaped_len == src.size()) { dest->append(src.data(), src.size()); @@ -593,30 +592,30 @@ void CEscapeAndAppend(StringPiece src, string* dest) { } } -string CEscape(const string& src) { - string dest; +std::string CEscape(const std::string &src) { + std::string dest; CEscapeAndAppend(src, &dest); return dest; } namespace strings { -string Utf8SafeCEscape(const string& src) { +std::string Utf8SafeCEscape(const std::string &src) { const int dest_length = src.size() * 4 + 1; // Maximum possible expansion std::unique_ptr dest(new char[dest_length]); const int len = CEscapeInternal(src.data(), src.size(), dest.get(), dest_length, false, true); GOOGLE_DCHECK_GE(len, 0); - return string(dest.get(), len); + return std::string(dest.get(), len); } -string CHexEscape(const string& src) { +std::string CHexEscape(const std::string &src) { const int dest_length = src.size() * 4 + 1; // Maximum possible expansion std::unique_ptr dest(new char[dest_length]); const int len = CEscapeInternal(src.data(), src.size(), dest.get(), dest_length, true, false); GOOGLE_DCHECK_GE(len, 0); - return string(dest.get(), len); + return std::string(dest.get(), len); } } // namespace strings @@ -664,8 +663,8 @@ uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) { return static_cast(result); } -inline bool safe_parse_sign(string* text /*inout*/, - bool* negative_ptr /*output*/) { +inline bool safe_parse_sign(std::string *text /*inout*/, + bool *negative_ptr /*output*/) { const char* start = text->data(); const char* end = start + text->size(); @@ -692,9 +691,8 @@ inline bool safe_parse_sign(string* text /*inout*/, return true; } -template -bool safe_parse_positive_int( - string text, IntType* value_p) { +template +bool safe_parse_positive_int(std::string text, IntType *value_p) { int base = 10; IntType value = 0; const IntType vmax = std::numeric_limits::max(); @@ -726,9 +724,8 @@ bool safe_parse_positive_int( return true; } -template -bool safe_parse_negative_int( - const string& text, IntType* value_p) { +template +bool safe_parse_negative_int(const std::string &text, IntType *value_p) { int base = 10; IntType value = 0; const IntType vmin = std::numeric_limits::min(); @@ -767,8 +764,8 @@ bool safe_parse_negative_int( return true; } -template -bool safe_int_internal(string text, IntType* value_p) { +template +bool safe_int_internal(std::string text, IntType *value_p) { *value_p = 0; bool negative; if (!safe_parse_sign(&text, &negative)) { @@ -781,8 +778,8 @@ bool safe_int_internal(string text, IntType* value_p) { } } -template -bool safe_uint_internal(string text, IntType* value_p) { +template +bool safe_uint_internal(std::string text, IntType *value_p) { *value_p = 0; bool negative; if (!safe_parse_sign(&text, &negative) || negative) { @@ -1116,46 +1113,46 @@ char* FastInt64ToBufferLeft(int64 i, char* buffer) { // Return value: string // ---------------------------------------------------------------------- -string SimpleItoa(int i) { +std::string SimpleItoa(int i) { char buffer[kFastToBufferSize]; return (sizeof(i) == 4) ? FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer); } -string SimpleItoa(unsigned int i) { +std::string SimpleItoa(unsigned int i) { char buffer[kFastToBufferSize]; - return string(buffer, (sizeof(i) == 4) ? - FastUInt32ToBufferLeft(i, buffer) : - FastUInt64ToBufferLeft(i, buffer)); + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); } -string SimpleItoa(long i) { +std::string SimpleItoa(long i) { char buffer[kFastToBufferSize]; return (sizeof(i) == 4) ? FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer); } -string SimpleItoa(unsigned long i) { +std::string SimpleItoa(unsigned long i) { char buffer[kFastToBufferSize]; - return string(buffer, (sizeof(i) == 4) ? - FastUInt32ToBufferLeft(i, buffer) : - FastUInt64ToBufferLeft(i, buffer)); + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); } -string SimpleItoa(long long i) { +std::string SimpleItoa(long long i) { char buffer[kFastToBufferSize]; return (sizeof(i) == 4) ? FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer); } -string SimpleItoa(unsigned long long i) { +std::string SimpleItoa(unsigned long long i) { char buffer[kFastToBufferSize]; - return string(buffer, (sizeof(i) == 4) ? - FastUInt32ToBufferLeft(i, buffer) : - FastUInt64ToBufferLeft(i, buffer)); + return std::string(buffer, (sizeof(i) == 4) + ? FastUInt32ToBufferLeft(i, buffer) + : FastUInt64ToBufferLeft(i, buffer)); } // ---------------------------------------------------------------------- @@ -1199,12 +1196,12 @@ string SimpleItoa(unsigned long long i) { // implementation. // ---------------------------------------------------------------------- -string SimpleDtoa(double value) { +std::string SimpleDtoa(double value) { char buffer[kDoubleToBufferSize]; return DoubleToBuffer(value, buffer); } -string SimpleFtoa(float value) { +std::string SimpleFtoa(float value) { char buffer[kFloatToBufferSize]; return FloatToBuffer(value, buffer); } @@ -1344,19 +1341,19 @@ bool safe_strtod(const char* str, double* value) { return *str != '\0' && *endptr == '\0'; } -bool safe_strto32(const string& str, int32* value) { +bool safe_strto32(const std::string &str, int32 *value) { return safe_int_internal(str, value); } -bool safe_strtou32(const string& str, uint32* value) { +bool safe_strtou32(const std::string &str, uint32 *value) { return safe_uint_internal(str, value); } -bool safe_strto64(const string& str, int64* value) { +bool safe_strto64(const std::string &str, int64 *value) { return safe_int_internal(str, value); } -bool safe_strtou64(const string& str, uint64* value) { +bool safe_strtou64(const std::string &str, uint64 *value) { return safe_uint_internal(str, value); } @@ -1472,8 +1469,8 @@ static char *Append4(char *out, const AlphaNum &x1, const AlphaNum &x2, return out; } -string StrCat(const AlphaNum &a, const AlphaNum &b) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b) { + std::string result; result.resize(a.size() + b.size()); char *const begin = &*result.begin(); char *out = Append2(begin, a, b); @@ -1481,8 +1478,8 @@ string StrCat(const AlphaNum &a, const AlphaNum &b) { return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + std::string result; result.resize(a.size() + b.size() + c.size()); char *const begin = &*result.begin(); char *out = Append2(begin, a, b); @@ -1491,9 +1488,9 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size()); char *const begin = &*result.begin(); char *out = Append4(begin, a, b, c, d); @@ -1501,9 +1498,9 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size()); char *const begin = &*result.begin(); char *out = Append4(begin, a, b, c, d); @@ -1512,9 +1509,9 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size()); char *const begin = &*result.begin(); @@ -1524,10 +1521,10 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + g.size()); char *const begin = &*result.begin(); @@ -1538,10 +1535,10 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g, const AlphaNum &h) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + g.size() + h.size()); char *const begin = &*result.begin(); @@ -1551,10 +1548,10 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, return result; } -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { - string result; +std::string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { + std::string result; result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + f.size() + g.size() + h.size() + i.size()); char *const begin = &*result.begin(); @@ -1573,27 +1570,27 @@ string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \ uintptr_t((dest).size())) -void StrAppend(string *result, const AlphaNum &a) { +void StrAppend(std::string *result, const AlphaNum &a) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); result->append(a.data(), a.size()); } -void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) { +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); GOOGLE_DCHECK_NO_OVERLAP(*result, b); - string::size_type old_size = result->size(); + std::string::size_type old_size = result->size(); result->resize(old_size + a.size() + b.size()); char *const begin = &*result->begin(); char *out = Append2(begin + old_size, a, b); GOOGLE_DCHECK_EQ(out, begin + result->size()); } -void StrAppend(string *result, - const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b, + const AlphaNum &c) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); GOOGLE_DCHECK_NO_OVERLAP(*result, b); GOOGLE_DCHECK_NO_OVERLAP(*result, c); - string::size_type old_size = result->size(); + std::string::size_type old_size = result->size(); result->resize(old_size + a.size() + b.size() + c.size()); char *const begin = &*result->begin(); char *out = Append2(begin + old_size, a, b); @@ -1601,32 +1598,29 @@ void StrAppend(string *result, GOOGLE_DCHECK_EQ(out, begin + result->size()); } -void StrAppend(string *result, - const AlphaNum &a, const AlphaNum &b, +void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, const AlphaNum &d) { GOOGLE_DCHECK_NO_OVERLAP(*result, a); GOOGLE_DCHECK_NO_OVERLAP(*result, b); GOOGLE_DCHECK_NO_OVERLAP(*result, c); GOOGLE_DCHECK_NO_OVERLAP(*result, d); - string::size_type old_size = result->size(); + std::string::size_type old_size = result->size(); result->resize(old_size + a.size() + b.size() + c.size() + d.size()); char *const begin = &*result->begin(); char *out = Append4(begin + old_size, a, b, c, d); GOOGLE_DCHECK_EQ(out, begin + result->size()); } -int GlobalReplaceSubstring(const string& substring, - const string& replacement, - string* s) { +int GlobalReplaceSubstring(const std::string &substring, + const std::string &replacement, std::string *s) { GOOGLE_CHECK(s != nullptr); if (s->empty() || substring.empty()) return 0; - string tmp; + std::string tmp; int num_replacements = 0; int pos = 0; for (int match_pos = s->find(substring.data(), pos, substring.length()); - match_pos != string::npos; - pos = match_pos + substring.length(), + match_pos != std::string::npos; pos = match_pos + substring.length(), match_pos = s->find(substring.data(), pos, substring.length())) { ++num_replacements; // Append the original content before the match. @@ -2057,8 +2051,8 @@ int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) { return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64); } -static bool Base64UnescapeInternal(const char* src, int slen, string* dest, - const signed char* unbase64) { +static bool Base64UnescapeInternal(const char *src, int slen, std::string *dest, + const signed char *unbase64) { // Determine the size of the output string. Base64 encodes every 3 bytes into // 4 characters. any leftover chars are added directly for good measure. // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548 @@ -2082,11 +2076,11 @@ static bool Base64UnescapeInternal(const char* src, int slen, string* dest, return true; } -bool Base64Unescape(StringPiece src, string* dest) { +bool Base64Unescape(StringPiece src, std::string *dest) { return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64); } -bool WebSafeBase64Unescape(StringPiece src, string* dest) { +bool WebSafeBase64Unescape(StringPiece src, std::string *dest) { return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64); } @@ -2205,9 +2199,9 @@ int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest, kWebSafeBase64Chars, do_padding); } -void Base64EscapeInternal(const unsigned char* src, int szsrc, - string* dest, bool do_padding, - const char* base64_chars) { +void Base64EscapeInternal(const unsigned char *src, int szsrc, + std::string *dest, bool do_padding, + const char *base64_chars) { const int calc_escaped_size = CalculateBase64EscapedLen(szsrc, do_padding); dest->resize(calc_escaped_size); @@ -2220,27 +2214,27 @@ void Base64EscapeInternal(const unsigned char* src, int szsrc, dest->erase(escaped_len); } -void Base64Escape(const unsigned char *src, int szsrc, - string* dest, bool do_padding) { +void Base64Escape(const unsigned char *src, int szsrc, std::string *dest, + bool do_padding) { Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars); } -void WebSafeBase64Escape(const unsigned char *src, int szsrc, - string *dest, bool do_padding) { +void WebSafeBase64Escape(const unsigned char *src, int szsrc, std::string *dest, + bool do_padding) { Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars); } -void Base64Escape(StringPiece src, string* dest) { +void Base64Escape(StringPiece src, std::string *dest) { Base64Escape(reinterpret_cast(src.data()), src.size(), dest, true); } -void WebSafeBase64Escape(StringPiece src, string* dest) { +void WebSafeBase64Escape(StringPiece src, std::string *dest) { WebSafeBase64Escape(reinterpret_cast(src.data()), src.size(), dest, false); } -void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) { +void WebSafeBase64EscapeWithPadding(StringPiece src, std::string *dest) { WebSafeBase64Escape(reinterpret_cast(src.data()), src.size(), dest, true); } @@ -2336,19 +2330,19 @@ int UTF8FirstLetterNumBytes(const char* src, int len) { // (1) determines the presence of LF (first one is ok) // (2) if yes, removes any CR, else convert every CR to LF -void CleanStringLineEndings(const string &src, string *dst, +void CleanStringLineEndings(const std::string &src, std::string *dst, bool auto_end_last_line) { if (dst->empty()) { dst->append(src); CleanStringLineEndings(dst, auto_end_last_line); } else { - string tmp = src; + std::string tmp = src; CleanStringLineEndings(&tmp, auto_end_last_line); dst->append(tmp); } } -void CleanStringLineEndings(string *str, bool auto_end_last_line) { +void CleanStringLineEndings(std::string *str, bool auto_end_last_line) { ptrdiff_t output_pos = 0; bool r_seen = false; ptrdiff_t len = str->size(); @@ -2379,7 +2373,7 @@ void CleanStringLineEndings(string *str, bool auto_end_last_line) { continue; } } - string::const_reference in = p[input_pos]; + std::string::const_reference in = p[input_pos]; if (in == '\r') { if (r_seen) p[output_pos++] = '\n'; r_seen = true; diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index c070a05fd4..8ce81f28c3 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -118,7 +118,8 @@ inline bool HasPrefixString(StringPiece str, StringPiece prefix) { memcmp(str.data(), prefix.data(), prefix.size()) == 0; } -inline string StripPrefixString(const string& str, const string& prefix) { +inline std::string StripPrefixString(const std::string& str, + const std::string& prefix) { if (HasPrefixString(str, prefix)) { return str.substr(prefix.size()); } else { @@ -140,7 +141,8 @@ inline bool HasSuffixString(StringPiece str, StringPiece suffix) { suffix.size()) == 0; } -inline string StripSuffixString(const string& str, const string& suffix) { +inline std::string StripSuffixString(const std::string& str, + const std::string& suffix) { if (HasSuffixString(str, suffix)) { return str.substr(0, str.size() - suffix.size()); } else { @@ -157,10 +159,10 @@ inline string StripSuffixString(const string& str, const string& suffix) { // StripWhitespace // Removes whitespaces from both ends of the given string. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT void ReplaceCharacters(string* s, const char* remove, +PROTOBUF_EXPORT void ReplaceCharacters(std::string* s, const char* remove, char replacewith); -PROTOBUF_EXPORT void StripWhitespace(string* s); +PROTOBUF_EXPORT void StripWhitespace(std::string* s); // ---------------------------------------------------------------------- // LowerString() @@ -172,26 +174,26 @@ PROTOBUF_EXPORT void StripWhitespace(string* s); // strings. // ---------------------------------------------------------------------- -inline void LowerString(string * s) { - string::iterator end = s->end(); - for (string::iterator i = s->begin(); i != end; ++i) { +inline void LowerString(std::string* s) { + std::string::iterator end = s->end(); + for (std::string::iterator i = s->begin(); i != end; ++i) { // tolower() changes based on locale. We don't want this! if ('A' <= *i && *i <= 'Z') *i += 'a' - 'A'; } } -inline void UpperString(string * s) { - string::iterator end = s->end(); - for (string::iterator i = s->begin(); i != end; ++i) { +inline void UpperString(std::string* s) { + std::string::iterator end = s->end(); + for (std::string::iterator i = s->begin(); i != end; ++i) { // toupper() changes based on locale. We don't want this! if ('a' <= *i && *i <= 'z') *i += 'A' - 'a'; } } -inline void ToUpper(string* s) { UpperString(s); } +inline void ToUpper(std::string* s) { UpperString(s); } -inline string ToUpper(const string& s) { - string out = s; +inline std::string ToUpper(const std::string& s) { + std::string out = s; UpperString(&out); return out; } @@ -204,8 +206,10 @@ inline string ToUpper(const string& s) { // happened or not. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub, - const string& newsub, bool replace_all); +PROTOBUF_EXPORT std::string StringReplace(const std::string& s, + const std::string& oldsub, + const std::string& newsub, + bool replace_all); // ---------------------------------------------------------------------- // SplitStringUsing() @@ -214,7 +218,7 @@ PROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub, // over all of them. // ---------------------------------------------------------------------- PROTOBUF_EXPORT void SplitStringUsing(StringPiece full, const char* delim, - std::vector* res); + std::vector* res); // Split a string using one or more byte delimiters, presented // as a nul-terminated c string. Append the components to 'result'. @@ -225,15 +229,15 @@ PROTOBUF_EXPORT void SplitStringUsing(StringPiece full, const char* delim, // If "full" is the empty string, yields an empty string as the only value. // ---------------------------------------------------------------------- PROTOBUF_EXPORT void SplitStringAllowEmpty(StringPiece full, const char* delim, - std::vector* result); + std::vector* result); // ---------------------------------------------------------------------- // Split() // Split a string using a character delimiter. // ---------------------------------------------------------------------- -inline std::vector Split(StringPiece full, const char* delim, - bool skip_empty = true) { - std::vector result; +inline std::vector Split(StringPiece full, const char* delim, + bool skip_empty = true) { + std::vector result; if (skip_empty) { SplitStringUsing(full, delim, &result); } else { @@ -250,12 +254,12 @@ inline std::vector Split(StringPiece full, const char* delim, // another takes a pointer to the target string. In the latter case the // target string is cleared and overwritten. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT void JoinStrings(const std::vector& components, - const char* delim, string* result); +PROTOBUF_EXPORT void JoinStrings(const std::vector& components, + const char* delim, std::string* result); -inline string JoinStrings(const std::vector& components, - const char* delim) { - string result; +inline std::string JoinStrings(const std::vector& components, + const char* delim) { + std::string result; JoinStrings(components, delim, &result); return result; } @@ -293,7 +297,7 @@ inline string JoinStrings(const std::vector& components, PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest); PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, - std::vector* errors); + std::vector* errors); // ---------------------------------------------------------------------- // UnescapeCEscapeString() @@ -310,10 +314,12 @@ PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, // the third call, the new string is returned. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest); -PROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest, - std::vector* errors); -PROTOBUF_EXPORT string UnescapeCEscapeString(const string& src); +PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src, + std::string* dest); +PROTOBUF_EXPORT int UnescapeCEscapeString(const std::string& src, + std::string* dest, + std::vector* errors); +PROTOBUF_EXPORT std::string UnescapeCEscapeString(const std::string& src); // ---------------------------------------------------------------------- // CEscape() @@ -322,21 +328,21 @@ PROTOBUF_EXPORT string UnescapeCEscapeString(const string& src); // // Escaped chars: \n, \r, \t, ", ', \, and !isprint(). // ---------------------------------------------------------------------- -PROTOBUF_EXPORT string CEscape(const string& src); +PROTOBUF_EXPORT std::string CEscape(const std::string& src); // ---------------------------------------------------------------------- // CEscapeAndAppend() // Escapes 'src' using C-style escape sequences, and appends the escaped // string to 'dest'. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, string* dest); +PROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, std::string* dest); namespace strings { // Like CEscape() but does not escape bytes with the upper bit set. -PROTOBUF_EXPORT string Utf8SafeCEscape(const string& src); +PROTOBUF_EXPORT std::string Utf8SafeCEscape(const std::string& src); // Like CEscape() but uses hex (\x) escapes instead of octals. -PROTOBUF_EXPORT string CHexEscape(const string& src); +PROTOBUF_EXPORT std::string CHexEscape(const std::string& src); } // namespace strings // ---------------------------------------------------------------------- @@ -393,31 +399,31 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) { // ---------------------------------------------------------------------- PROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value); -PROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value); -PROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value); +PROTOBUF_EXPORT bool safe_strto32(const std::string& str, int32* value); +PROTOBUF_EXPORT bool safe_strtou32(const std::string& str, uint32* value); inline bool safe_strto32(const char* str, int32* value) { - return safe_strto32(string(str), value); + return safe_strto32(std::string(str), value); } inline bool safe_strto32(StringPiece str, int32* value) { return safe_strto32(str.ToString(), value); } inline bool safe_strtou32(const char* str, uint32* value) { - return safe_strtou32(string(str), value); + return safe_strtou32(std::string(str), value); } inline bool safe_strtou32(StringPiece str, uint32* value) { return safe_strtou32(str.ToString(), value); } -PROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value); -PROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value); +PROTOBUF_EXPORT bool safe_strto64(const std::string& str, int64* value); +PROTOBUF_EXPORT bool safe_strtou64(const std::string& str, uint64* value); inline bool safe_strto64(const char* str, int64* value) { - return safe_strto64(string(str), value); + return safe_strto64(std::string(str), value); } inline bool safe_strto64(StringPiece str, int64* value) { return safe_strto64(str.ToString(), value); } inline bool safe_strtou64(const char* str, uint64* value) { - return safe_strtou64(string(str), value); + return safe_strtou64(std::string(str), value); } inline bool safe_strtou64(StringPiece str, uint64* value) { return safe_strtou64(str.ToString(), value); @@ -425,10 +431,10 @@ inline bool safe_strtou64(StringPiece str, uint64* value) { PROTOBUF_EXPORT bool safe_strtof(const char* str, float* value); PROTOBUF_EXPORT bool safe_strtod(const char* str, double* value); -inline bool safe_strtof(const string& str, float* value) { +inline bool safe_strtof(const std::string& str, float* value) { return safe_strtof(str.c_str(), value); } -inline bool safe_strtod(const string& str, double* value) { +inline bool safe_strtod(const std::string& str, double* value) { return safe_strtod(str.c_str(), value); } inline bool safe_strtof(StringPiece str, float* value) { @@ -521,9 +527,7 @@ inline char* FastUInt64ToBuffer(uint64 i, char* buffer) { return buffer; } -inline string SimpleBtoa(bool value) { - return value ? "true" : "false"; -} +inline std::string SimpleBtoa(bool value) { return value ? "true" : "false"; } // ---------------------------------------------------------------------- // SimpleItoa() @@ -531,12 +535,12 @@ inline string SimpleBtoa(bool value) { // // Return value: string // ---------------------------------------------------------------------- -PROTOBUF_EXPORT string SimpleItoa(int i); -PROTOBUF_EXPORT string SimpleItoa(unsigned int i); -PROTOBUF_EXPORT string SimpleItoa(long i); -PROTOBUF_EXPORT string SimpleItoa(unsigned long i); -PROTOBUF_EXPORT string SimpleItoa(long long i); -PROTOBUF_EXPORT string SimpleItoa(unsigned long long i); +PROTOBUF_EXPORT std::string SimpleItoa(int i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned int i); +PROTOBUF_EXPORT std::string SimpleItoa(long i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned long i); +PROTOBUF_EXPORT std::string SimpleItoa(long long i); +PROTOBUF_EXPORT std::string SimpleItoa(unsigned long long i); // ---------------------------------------------------------------------- // SimpleDtoa() @@ -557,8 +561,8 @@ PROTOBUF_EXPORT string SimpleItoa(unsigned long long i); // // Return value: string // ---------------------------------------------------------------------- -PROTOBUF_EXPORT string SimpleDtoa(double value); -PROTOBUF_EXPORT string SimpleFtoa(float value); +PROTOBUF_EXPORT std::string SimpleDtoa(double value); +PROTOBUF_EXPORT std::string SimpleFtoa(float value); PROTOBUF_EXPORT char* DoubleToBuffer(double i, char* buffer); PROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); @@ -654,7 +658,7 @@ struct PROTOBUF_EXPORT AlphaNum { // TODO: Add a string_ref constructor, eventually // AlphaNum(const StringPiece &pc) : piece(pc) {} - AlphaNum(const string& str) + AlphaNum(const std::string& str) : piece_data_(str.data()), piece_size_(str.size()) {} AlphaNum(StringPiece str) @@ -702,32 +706,34 @@ using strings::AlphaNum; // be a reference into str. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b); -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c); -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d); -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e); -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f); -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f, - const AlphaNum& g); -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f, - const AlphaNum& g, const AlphaNum& h); -PROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d, - const AlphaNum& e, const AlphaNum& f, - const AlphaNum& g, const AlphaNum& h, - const AlphaNum& i); - -inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h); +PROTOBUF_EXPORT std::string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h, + const AlphaNum& i); + +inline std::string StrCat(const AlphaNum& a) { + return std::string(a.data(), a.size()); +} // ---------------------------------------------------------------------- // StrAppend() @@ -750,12 +756,12 @@ inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } // worked around as consecutive calls to StrAppend are quite efficient. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a); -PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a); +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b); -PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c); -PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, +PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d); @@ -765,8 +771,8 @@ PROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, // the C-string "delim" as a separator between components. // ---------------------------------------------------------------------- template -void Join(Iterator start, Iterator end, - const char* delim, string* result) { +void Join(Iterator start, Iterator end, const char* delim, + std::string* result) { for (Iterator it = start; it != end; ++it) { if (it != start) { result->append(delim); @@ -776,9 +782,8 @@ void Join(Iterator start, Iterator end, } template -string Join(const Range& components, - const char* delim) { - string result; +std::string Join(const Range& components, const char* delim) { + std::string result; Join(components.begin(), components.end(), delim, &result); return result; } @@ -787,7 +792,7 @@ string Join(const Range& components, // ToHex() // Return a lower-case hex string representation of the given integer. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT string ToHex(uint64 num); +PROTOBUF_EXPORT std::string ToHex(uint64 num); // ---------------------------------------------------------------------- // GlobalReplaceSubstring() @@ -796,9 +801,9 @@ PROTOBUF_EXPORT string ToHex(uint64 num); // // NOTE: The string pieces must not overlap s. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring, - const string& replacement, - string* s); +PROTOBUF_EXPORT int GlobalReplaceSubstring(const std::string& substring, + const std::string& replacement, + std::string* s); // ---------------------------------------------------------------------- // Base64Unescape() @@ -806,7 +811,7 @@ PROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring, // writes it to "dest". If src contains invalid characters, dest is cleared // and the function returns false. Returns true on success. // ---------------------------------------------------------------------- -PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest); +PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, std::string* dest); // ---------------------------------------------------------------------- // WebSafeBase64Unescape() @@ -821,7 +826,7 @@ PROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest); // ---------------------------------------------------------------------- PROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, char* dest, int szdest); -PROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, string* dest); +PROTOBUF_EXPORT bool WebSafeBase64Unescape(StringPiece src, std::string* dest); // Return the length to use for the output buffer given to the base64 escape // routines. Make sure to use the same value for do_padding in both. @@ -849,17 +854,17 @@ PROTOBUF_EXPORT int WebSafeBase64Escape(const unsigned char* src, int slen, char* dest, int szdest, bool do_padding); // Encode src into dest with padding. -PROTOBUF_EXPORT void Base64Escape(StringPiece src, string* dest); +PROTOBUF_EXPORT void Base64Escape(StringPiece src, std::string* dest); // Encode src into dest web-safely without padding. -PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, string* dest); +PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, std::string* dest); // Encode src into dest web-safely with padding. PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src, - string* dest); + std::string* dest); PROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc, - string* dest, bool do_padding); + std::string* dest, bool do_padding); PROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc, - string* dest, bool do_padding); + std::string* dest, bool do_padding); inline bool IsValidCodePoint(uint32 code_point) { return code_point < 0xD800 || @@ -915,11 +920,12 @@ PROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len); // // (1) determines the presence of LF (first one is ok) // (2) if yes, removes any CR, else convert every CR to LF -PROTOBUF_EXPORT void CleanStringLineEndings(const string& src, string* dst, +PROTOBUF_EXPORT void CleanStringLineEndings(const std::string& src, + std::string* dst, bool auto_end_last_line); // Same as above, but transforms the argument in place. -PROTOBUF_EXPORT void CleanStringLineEndings(string* str, +PROTOBUF_EXPORT void CleanStringLineEndings(std::string* str, bool auto_end_last_line); namespace strings { diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc index 141d263a40..fc9a63f3f2 100644 --- a/src/google/protobuf/stubs/strutil_unittest.cc +++ b/src/google/protobuf/stubs/strutil_unittest.cc @@ -52,7 +52,7 @@ TEST(StringUtilityTest, ImmuneToLocales) { // Remember the old locale. char* old_locale_cstr = setlocale(LC_NUMERIC, nullptr); ASSERT_TRUE(old_locale_cstr != nullptr); - string old_locale = old_locale_cstr; + std::string old_locale = old_locale_cstr; // Set the locale to "C". ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != nullptr); @@ -442,7 +442,7 @@ TEST(Base64, EscapeAndUnescape) { char decode_buffer[100]; int decode_length; int cypher_length; - string decode_str; + std::string decode_str; const unsigned char* unsigned_plaintext = reinterpret_cast(base64_tests[i].plaintext); @@ -491,13 +491,13 @@ TEST(Base64, EscapeAndUnescape) { EXPECT_EQ(plaintext, decode_str); // Let's try with a pre-populated string. - string encoded("this junk should be ignored"); - Base64Escape(string(base64_tests[i].plaintext, - base64_tests[i].plain_length), - &encoded); - EXPECT_EQ(encoded, string(encode_buffer, cypher_length)); + std::string encoded("this junk should be ignored"); + Base64Escape( + std::string(base64_tests[i].plaintext, base64_tests[i].plain_length), + &encoded); + EXPECT_EQ(encoded, std::string(encode_buffer, cypher_length)); - string decoded("this junk should be ignored"); + std::string decoded("this junk should be ignored"); EXPECT_TRUE(Base64Unescape( StringPiece(encode_buffer, cypher_length), &decoded)); EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); @@ -514,7 +514,7 @@ TEST(Base64, EscapeAndUnescape) { // Try chopping off the equals sign(s) entirely. The decoder // should still be okay with this. - string decoded2("this junk should also be ignored"); + std::string decoded2("this junk should also be ignored"); *first_equals = '\0'; EXPECT_TRUE(Base64Unescape( StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2)); @@ -730,7 +730,7 @@ TEST(Base64, EscapeAndUnescape) { EXPECT_STREQ(encode_buffer, websafe); // Let's try the (other) string version of the encoder - string plain(base64_tests[i].plaintext, base64_tests[i].plain_length); + std::string plain(base64_tests[i].plaintext, base64_tests[i].plain_length); encoded = "this junk should be ignored"; WebSafeBase64Escape(plain, &encoded); EXPECT_EQ(encoded.size(), cypher_length); @@ -798,7 +798,7 @@ TEST(Base64, EscapeAndUnescape) { // Verify the behavior when decoding bad data { const char* bad_data = "ab-/"; - string buf; + std::string buf; EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf)); EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf)); EXPECT_TRUE(buf.empty()); @@ -819,7 +819,7 @@ TEST(StrCat, Ints) { const size_t size = 10; const intptr_t intptr = -12; const uintptr_t uintptr = 13; - string answer; + std::string answer; answer = StrCat(s, us); EXPECT_EQ(answer, "-12"); answer = StrCat(i, ui); @@ -836,12 +836,13 @@ TEST(StrCat, Ints) { EXPECT_EQ(answer, "130"); } -class ReplaceChars : public ::testing::TestWithParam< - std::tuple> {}; +class ReplaceChars + : public ::testing::TestWithParam< + std::tuple> {}; TEST_P(ReplaceChars, ReplacesAllOccurencesOfAnyCharInReplaceWithAReplaceChar) { - string expected = std::get<0>(GetParam()); - string string_to_replace_in = std::get<1>(GetParam()); + std::string expected = std::get<0>(GetParam()); + std::string string_to_replace_in = std::get<1>(GetParam()); const char* what_to_replace = std::get<2>(GetParam()); char replacement = std::get<3>(GetParam()); ReplaceCharacters(&string_to_replace_in, what_to_replace, replacement); @@ -864,11 +865,12 @@ INSTANTIATE_TEST_CASE_P( std::make_tuple("qvvvvvng v T", "queueing a T", "aeiou", 'v'))); // replace all voewls -class StripWs : public ::testing::TestWithParam> {}; +class StripWs + : public ::testing::TestWithParam> {}; TEST_P(StripWs, AlwaysStripsLeadingAndTrailingWhitespace) { - string expected = std::get<0>(GetParam()); - string string_to_strip = std::get<1>(GetParam()); + std::string expected = std::get<0>(GetParam()); + std::string string_to_strip = std::get<1>(GetParam()); StripWhitespace(&string_to_strip); ASSERT_EQ(expected, string_to_strip); } diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc index a36f2f026c..92107416eb 100644 --- a/src/google/protobuf/stubs/substitute.cc +++ b/src/google/protobuf/stubs/substitute.cc @@ -52,26 +52,24 @@ static int CountSubstituteArgs(const SubstituteArg* const* args_array) { return count; } -string Substitute( - const char* format, - const SubstituteArg& arg0, const SubstituteArg& arg1, - const SubstituteArg& arg2, const SubstituteArg& arg3, - const SubstituteArg& arg4, const SubstituteArg& arg5, - const SubstituteArg& arg6, const SubstituteArg& arg7, - const SubstituteArg& arg8, const SubstituteArg& arg9) { - string result; +std::string Substitute(const char* format, const SubstituteArg& arg0, + const SubstituteArg& arg1, const SubstituteArg& arg2, + const SubstituteArg& arg3, const SubstituteArg& arg4, + const SubstituteArg& arg5, const SubstituteArg& arg6, + const SubstituteArg& arg7, const SubstituteArg& arg8, + const SubstituteArg& arg9) { + std::string result; SubstituteAndAppend(&result, format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); return result; } -void SubstituteAndAppend( - string* output, const char* format, - const SubstituteArg& arg0, const SubstituteArg& arg1, - const SubstituteArg& arg2, const SubstituteArg& arg3, - const SubstituteArg& arg4, const SubstituteArg& arg5, - const SubstituteArg& arg6, const SubstituteArg& arg7, - const SubstituteArg& arg8, const SubstituteArg& arg9) { +void SubstituteAndAppend(std::string* output, const char* format, + const SubstituteArg& arg0, const SubstituteArg& arg1, + const SubstituteArg& arg2, const SubstituteArg& arg3, + const SubstituteArg& arg4, const SubstituteArg& arg5, + const SubstituteArg& arg6, const SubstituteArg& arg7, + const SubstituteArg& arg8, const SubstituteArg& arg9) { const SubstituteArg* const args_array[] = { &arg0, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8, &arg9, nullptr }; diff --git a/src/google/protobuf/stubs/substitute.h b/src/google/protobuf/stubs/substitute.h index 267dead236..d4e72e1c51 100644 --- a/src/google/protobuf/stubs/substitute.h +++ b/src/google/protobuf/stubs/substitute.h @@ -90,8 +90,8 @@ class SubstituteArg { public: inline SubstituteArg(const char* value) : text_(value), size_(strlen(text_)) {} - inline SubstituteArg(const string& value) - : text_(value.data()), size_(value.size()) {} + inline SubstituteArg(const std::string& value) + : text_(value.data()), size_(value.size()) {} // Indicates that no argument was given. inline explicit SubstituteArg() @@ -139,21 +139,21 @@ class SubstituteArg { } // namespace internal -PROTOBUF_EXPORT string -Substitute(const char* format, - const internal::SubstituteArg& arg0 = internal::SubstituteArg(), - const internal::SubstituteArg& arg1 = internal::SubstituteArg(), - const internal::SubstituteArg& arg2 = internal::SubstituteArg(), - const internal::SubstituteArg& arg3 = internal::SubstituteArg(), - const internal::SubstituteArg& arg4 = internal::SubstituteArg(), - const internal::SubstituteArg& arg5 = internal::SubstituteArg(), - const internal::SubstituteArg& arg6 = internal::SubstituteArg(), - const internal::SubstituteArg& arg7 = internal::SubstituteArg(), - const internal::SubstituteArg& arg8 = internal::SubstituteArg(), - const internal::SubstituteArg& arg9 = internal::SubstituteArg()); +PROTOBUF_EXPORT std::string Substitute( + const char* format, + const internal::SubstituteArg& arg0 = internal::SubstituteArg(), + const internal::SubstituteArg& arg1 = internal::SubstituteArg(), + const internal::SubstituteArg& arg2 = internal::SubstituteArg(), + const internal::SubstituteArg& arg3 = internal::SubstituteArg(), + const internal::SubstituteArg& arg4 = internal::SubstituteArg(), + const internal::SubstituteArg& arg5 = internal::SubstituteArg(), + const internal::SubstituteArg& arg6 = internal::SubstituteArg(), + const internal::SubstituteArg& arg7 = internal::SubstituteArg(), + const internal::SubstituteArg& arg8 = internal::SubstituteArg(), + const internal::SubstituteArg& arg9 = internal::SubstituteArg()); PROTOBUF_EXPORT void SubstituteAndAppend( - string* output, const char* format, + std::string* output, const char* format, const internal::SubstituteArg& arg0 = internal::SubstituteArg(), const internal::SubstituteArg& arg1 = internal::SubstituteArg(), const internal::SubstituteArg& arg2 = internal::SubstituteArg(), diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc index 64f3ceb9f6..922be76d1b 100644 --- a/src/google/protobuf/stubs/time.cc +++ b/src/google/protobuf/stubs/time.cc @@ -130,7 +130,7 @@ int64 SecondsSinceCommonEra(const DateTime& time) { // Format nanoseconds with either 3, 6, or 9 digits depending on the required // precision to represent the exact value. -string FormatNanos(int32 nanos) { +std::string FormatNanos(int32 nanos) { if (nanos % kNanosPerMillisecond == 0) { return StringPrintf("%03d", nanos / kNanosPerMillisecond); } else if (nanos % kNanosPerMicrosecond == 0) { @@ -268,21 +268,21 @@ void GetCurrentTime(int64* seconds, int32* nanos) { *nanos = 0; } -string FormatTime(int64 seconds, int32 nanos) { +std::string FormatTime(int64 seconds, int32 nanos) { DateTime time; if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) { return "InvalidTime"; } - string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", - time.year, time.month, time.day, - time.hour, time.minute, time.second); + std::string result = + StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", time.year, time.month, + time.day, time.hour, time.minute, time.second); if (nanos != 0) { result += "." + FormatNanos(nanos); } return result + "Z"; } -bool ParseTime(const string& value, int64* seconds, int32* nanos) { +bool ParseTime(const std::string& value, int64* seconds, int32* nanos) { DateTime time; const char* data = value.c_str(); // We only accept: diff --git a/src/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h index b52f3f9632..b06117689e 100644 --- a/src/google/protobuf/stubs/time.h +++ b/src/google/protobuf/stubs/time.h @@ -65,10 +65,10 @@ void PROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos); // value. // // Note that "nanos" must in the range of [0, 999999999]. -string PROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos); +std::string PROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos); // Parses a time string. This method accepts RFC3339 date/time string with UTC // offset. For example, "2015-05-20T13:29:35.120-08:00". -bool PROTOBUF_EXPORT ParseTime(const string& value, int64* seconds, +bool PROTOBUF_EXPORT ParseTime(const std::string& value, int64* seconds, int32* nanos); } // namespace internal diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index 7d3708e3d6..7b628879c6 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -66,11 +66,12 @@ using google::protobuf::io::win32::mkdir; using google::protobuf::io::win32::stat; #endif -bool File::Exists(const string& name) { +bool File::Exists(const std::string& name) { return access(name.c_str(), F_OK) == 0; } -bool File::ReadFileToString(const string& name, string* output, bool text_mode) { +bool File::ReadFileToString(const std::string& name, std::string* output, + bool text_mode) { char buffer[1024]; FILE* file = fopen(name.c_str(), text_mode ? "rt" : "rb"); if (file == NULL) return false; @@ -86,11 +87,12 @@ bool File::ReadFileToString(const string& name, string* output, bool text_mode) return error == 0; } -void File::ReadFileToStringOrDie(const string& name, string* output) { +void File::ReadFileToStringOrDie(const std::string& name, std::string* output) { GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name; } -bool File::WriteStringToFile(const string& contents, const string& name) { +bool File::WriteStringToFile(const std::string& contents, + const std::string& name) { FILE* file = fopen(name.c_str(), "wb"); if (file == NULL) { GOOGLE_LOG(ERROR) << "fopen(" << name << ", \"wb\"): " << strerror(errno); @@ -109,7 +111,8 @@ bool File::WriteStringToFile(const string& contents, const string& name) { return true; } -void File::WriteStringToFileOrDie(const string& contents, const string& name) { +void File::WriteStringToFileOrDie(const std::string& contents, + const std::string& name) { FILE* file = fopen(name.c_str(), "wb"); GOOGLE_CHECK(file != NULL) << "fopen(" << name << ", \"wb\"): " << strerror(errno); @@ -120,21 +123,21 @@ void File::WriteStringToFileOrDie(const string& contents, const string& name) { << "fclose(" << name << "): " << strerror(errno); } -bool File::CreateDir(const string& name, int mode) { +bool File::CreateDir(const std::string& name, int mode) { if (!name.empty()) { GOOGLE_CHECK_OK(name[name.size() - 1] != '.'); } return mkdir(name.c_str(), mode) == 0; } -bool File::RecursivelyCreateDir(const string& path, int mode) { +bool File::RecursivelyCreateDir(const std::string& path, int mode) { if (CreateDir(path, mode)) return true; if (Exists(path)) return false; // Try creating the parent. - string::size_type slashpos = path.find_last_of('/'); - if (slashpos == string::npos) { + std::string::size_type slashpos = path.find_last_of('/'); + if (slashpos == std::string::npos) { // No parent given. return false; } @@ -143,8 +146,8 @@ bool File::RecursivelyCreateDir(const string& path, int mode) { CreateDir(path, mode); } -void File::DeleteRecursively(const string& name, - void* dummy1, void* dummy2) { +void File::DeleteRecursively(const std::string& name, void* dummy1, + void* dummy2) { if (name.empty()) return; // We don't care too much about error checking here since this is only used @@ -162,9 +165,9 @@ void File::DeleteRecursively(const string& name, } do { - string entry_name = find_data.cFileName; + std::string entry_name = find_data.cFileName; if (entry_name != "." && entry_name != "..") { - string path = name + "/" + entry_name; + std::string path = name + "/" + entry_name; if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { DeleteRecursively(path, NULL, NULL); RemoveDirectoryA(path.c_str()); @@ -188,7 +191,7 @@ void File::DeleteRecursively(const string& name, while (true) { struct dirent* entry = readdir(dir); if (entry == NULL) break; - string entry_name = entry->d_name; + std::string entry_name = entry->d_name; if (entry_name != "." && entry_name != "..") { DeleteRecursively(name + "/" + entry_name, NULL, NULL); } @@ -204,7 +207,7 @@ void File::DeleteRecursively(const string& name, #endif } -bool File::ChangeWorkingDirectory(const string& new_working_directory) { +bool File::ChangeWorkingDirectory(const std::string& new_working_directory) { return chdir(new_working_directory.c_str()) == 0; } diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h index 45989967c9..f18f685865 100644 --- a/src/google/protobuf/testing/file.h +++ b/src/google/protobuf/testing/file.h @@ -46,52 +46,54 @@ const int DEFAULT_FILE_MODE = 0777; class File { public: // Check if the file exists. - static bool Exists(const string& name); + static bool Exists(const std::string& name); // Read an entire file to a string. Return true if successful, false // otherwise. - static bool ReadFileToString(const string& name, string* output, bool text_mode = false); + static bool ReadFileToString(const std::string& name, std::string* output, + bool text_mode = false); // Same as above, but crash on failure. - static void ReadFileToStringOrDie(const string& name, string* output); + static void ReadFileToStringOrDie(const std::string& name, + std::string* output); // Create a file and write a string to it. - static bool WriteStringToFile(const string& contents, - const string& name); + static bool WriteStringToFile(const std::string& contents, + const std::string& name); // Same as above, but crash on failure. - static void WriteStringToFileOrDie(const string& contents, - const string& name); + static void WriteStringToFileOrDie(const std::string& contents, + const std::string& name); // Create a directory. - static bool CreateDir(const string& name, int mode); + static bool CreateDir(const std::string& name, int mode); // Create a directory and all parent directories if necessary. - static bool RecursivelyCreateDir(const string& path, int mode); + static bool RecursivelyCreateDir(const std::string& path, int mode); // If "name" is a file, we delete it. If it is a directory, we // call DeleteRecursively() for each file or directory (other than // dot and double-dot) within it, and then delete the directory itself. // The "dummy" parameters have a meaning in the original version of this // method but they are not used anywhere in protocol buffers. - static void DeleteRecursively(const string& name, - void* dummy1, void* dummy2); + static void DeleteRecursively(const std::string& name, void* dummy1, + void* dummy2); // Change working directory to given directory. - static bool ChangeWorkingDirectory(const string& new_working_directory); + static bool ChangeWorkingDirectory(const std::string& new_working_directory); - static bool GetContents( - const string& name, string* output, bool /*is_default*/) { + static bool GetContents(const std::string& name, std::string* output, + bool /*is_default*/) { return ReadFileToString(name, output); } - static bool GetContentsAsText( - const string& name, string* output, bool /*is_default*/) { + static bool GetContentsAsText(const std::string& name, std::string* output, + bool /*is_default*/) { return ReadFileToString(name, output, true); } - static bool SetContents( - const string& name, const string& contents, bool /*is_default*/) { + static bool SetContents(const std::string& name, const std::string& contents, + bool /*is_default*/) { return WriteStringToFile(contents, name); } diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc index 1856971cb8..88343f9347 100644 --- a/src/google/protobuf/testing/googletest.cc +++ b/src/google/protobuf/testing/googletest.cc @@ -70,7 +70,7 @@ using google::protobuf::io::win32::open; #endif #endif -string TestSourceDir() { +std::string TestSourceDir() { #ifndef GOOGLE_THIRD_PARTY_PROTOBUF #ifdef GOOGLE_PROTOBUF_TEST_SOURCE_PATH return GOOGLE_PROTOBUF_TEST_SOURCE_PATH; @@ -84,7 +84,7 @@ string TestSourceDir() { #endif // _MSC_VER // Look for the "src" directory. - string prefix = "."; + std::string prefix = "."; // Keep looking further up the directory tree until we find // src/.../descriptor.cc. It is important to look for a particular file, @@ -107,12 +107,12 @@ string TestSourceDir() { namespace { -string GetTemporaryDirectoryName() { +std::string GetTemporaryDirectoryName() { // Tests run under Bazel "should not" use /tmp. Bazel sets this environment // variable for tests to use instead. char *from_environment = getenv("TEST_TMPDIR"); if (from_environment != NULL && from_environment[0] != '\0') { - return string(from_environment) + "/protobuf_tmpdir"; + return std::string(from_environment) + "/protobuf_tmpdir"; } // tmpnam() is generally not considered safe but we're only using it for @@ -121,7 +121,7 @@ string GetTemporaryDirectoryName() { char b[L_tmpnam + 1]; // HPUX multithread return 0 if s is 0 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - string result = tmpnam(b); + std::string result = tmpnam(b); #pragma GCC diagnostic pop #ifdef _WIN32 // Avoid a trailing dot by changing it to an underscore. On Win32 the names of @@ -166,7 +166,7 @@ class TempDirDeleter { } } - string GetTempDir() { + std::string GetTempDir() { if (name_.empty()) { name_ = GetTemporaryDirectoryName(); GOOGLE_CHECK(mkdir(name_.c_str(), 0777) == 0) << strerror(errno); @@ -179,21 +179,19 @@ class TempDirDeleter { } private: - string name_; + std::string name_; }; TempDirDeleter temp_dir_deleter_; } // namespace -string TestTempDir() { - return temp_dir_deleter_.GetTempDir(); -} +std::string TestTempDir() { return temp_dir_deleter_.GetTempDir(); } // TODO(kenton): Share duplicated code below. Too busy/lazy for now. -static string stdout_capture_filename_; -static string stderr_capture_filename_; +static std::string stdout_capture_filename_; +static std::string stderr_capture_filename_; static int original_stdout_ = -1; static int original_stderr_ = -1; @@ -227,14 +225,14 @@ void CaptureTestStderr() { close(fd); } -string GetCapturedTestStdout() { +std::string GetCapturedTestStdout() { GOOGLE_CHECK_NE(original_stdout_, -1) << "Not capturing."; close(1); dup2(original_stdout_, 1); original_stdout_ = -1; - string result; + std::string result; File::ReadFileToStringOrDie(stdout_capture_filename_, &result); remove(stdout_capture_filename_.c_str()); @@ -242,14 +240,14 @@ string GetCapturedTestStdout() { return result; } -string GetCapturedTestStderr() { +std::string GetCapturedTestStderr() { GOOGLE_CHECK_NE(original_stderr_, -1) << "Not capturing."; close(2); dup2(original_stderr_, 2); original_stderr_ = -1; - string result; + std::string result; File::ReadFileToStringOrDie(stderr_capture_filename_, &result); remove(stderr_capture_filename_.c_str()); @@ -270,14 +268,14 @@ ScopedMemoryLog::~ScopedMemoryLog() { active_log_ = NULL; } -const std::vector& ScopedMemoryLog::GetMessages(LogLevel level) { +const std::vector& ScopedMemoryLog::GetMessages(LogLevel level) { GOOGLE_CHECK(level == ERROR || level == WARNING); return messages_[level]; } -void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, - int line, const string& message) { +void ScopedMemoryLog::HandleLog(LogLevel level, const char* filename, int line, + const std::string& message) { GOOGLE_CHECK(active_log_ != NULL); if (level == ERROR || level == WARNING) { active_log_->messages_[level].push_back(message); diff --git a/src/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h index 4e0cb83a85..6a0c694e71 100644 --- a/src/google/protobuf/testing/googletest.h +++ b/src/google/protobuf/testing/googletest.h @@ -49,19 +49,19 @@ namespace google { namespace protobuf { // When running unittests, get the directory containing the source code. -string TestSourceDir(); +std::string TestSourceDir(); // When running unittests, get a directory where temporary files may be // placed. -string TestTempDir(); +std::string TestTempDir(); // Capture all text written to stdout or stderr. void CaptureTestStdout(); void CaptureTestStderr(); // Stop capturing stdout or stderr and return the text captured. -string GetCapturedTestStdout(); -string GetCapturedTestStderr(); +std::string GetCapturedTestStdout(); +std::string GetCapturedTestStderr(); // For use with ScopedMemoryLog::GetMessages(). Inside Google the LogLevel // constants don't have the LOGLEVEL_ prefix, so the code that used @@ -84,14 +84,14 @@ class ScopedMemoryLog { virtual ~ScopedMemoryLog(); // Fetches all messages with the given severity level. - const std::vector& GetMessages(LogLevel error); + const std::vector& GetMessages(LogLevel error); private: - std::map > messages_; + std::map > messages_; LogHandler* old_handler_; static void HandleLog(LogLevel level, const char* filename, int line, - const string& message); + const std::string& message); static ScopedMemoryLog* active_log_; diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 11e9b0001f..f47d4e8d01 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -456,8 +456,7 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeIdentifier(&field_name)); int32 field_number; - if (allow_field_number_ && - safe_strto32(field_name, &field_number)) { + if (allow_field_number_ && safe_strto32(field_name, &field_number)) { if (descriptor->IsExtensionNumber(field_number)) { field = finder_ ? finder_->FindExtensionByNumber(descriptor, field_number) @@ -1473,7 +1472,7 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, return MergeUsingImpl(input, output, &parser); } -bool TextFormat::Parser::MergeFromString(const std::string& input, +bool TextFormat::Parser::MergeFromString(ConstStringParam input, Message* output) { DO(CheckParseInputSize(input, error_collector_)); io::ArrayInputStream input_stream(input.data(), input.size()); @@ -1524,7 +1523,7 @@ bool TextFormat::Parser::ParseFieldValueFromString(const std::string& input, return Parser().ParseFromString(input, output); } -/* static */ bool TextFormat::MergeFromString(const std::string& input, +/* static */ bool TextFormat::MergeFromString(ConstStringParam input, Message* output) { return Parser().MergeFromString(input, output); } @@ -2053,8 +2052,8 @@ void TextFormat::Printer::Print(const Message& message, if (print_message_fields_in_index_order_) { std::sort(fields.begin(), fields.end(), FieldIndexSorter()); } - for (int i = 0; i < fields.size(); i++) { - PrintField(message, reflection, fields[i], generator); + for (const FieldDescriptor* field : fields) { + PrintField(message, reflection, field, generator); } if (!hide_unknown_fields_) { PrintUnknownFields(reflection->GetUnknownFields(message), generator, @@ -2313,8 +2312,8 @@ void TextFormat::Printer::PrintField(const Message& message, } if (need_release) { - for (int j = 0; j < sorted_map_field.size(); ++j) { - delete sorted_map_field[j]; + for (const Message* message_to_delete : sorted_map_field) { + delete message_to_delete; } } } diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index e4b32557f4..3a3ee1563a 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -460,7 +460,7 @@ class PROTOBUF_EXPORT TextFormat { // using Message::MergeFrom(). static bool Merge(io::ZeroCopyInputStream* input, Message* output); // Like Merge(), but reads directly from a string. - static bool MergeFromString(const std::string& input, Message* output); + static bool MergeFromString(ConstStringParam input, Message* output); // Parse the given text as a single field value and store it into the // given field of the given message. If the field is a repeated field, @@ -535,7 +535,7 @@ class PROTOBUF_EXPORT TextFormat { // Like TextFormat::Merge(). bool Merge(io::ZeroCopyInputStream* input, Message* output); // Like TextFormat::MergeFromString(). - bool MergeFromString(const std::string& input, Message* output); + bool MergeFromString(ConstStringParam input, Message* output); // Set where to report parse errors. If NULL (the default), errors will // be printed to stderr. @@ -569,16 +569,22 @@ class PROTOBUF_EXPORT TextFormat { const FieldDescriptor* field, Message* output); - // When an unknown extension is met, parsing will fail if this option is set - // to false (the default). If true, unknown extensions will be ignored and - // a warning message will be generated. + // When an unknown extension is met, parsing will fail if this option is + // set to false (the default). If true, unknown extensions will be ignored + // and a warning message will be generated. + // Beware! Setting this option true may hide some errors (e.g. spelling + // error on extension name). This allows data loss; unlike binary format, + // text format cannot preserve unknown extensions. Avoid using this option + // if possible. void AllowUnknownExtension(bool allow) { allow_unknown_extension_ = allow; } // When an unknown field is met, parsing will fail if this option is set - // to false(the default). If true, unknown fields will be ignored and + // to false (the default). If true, unknown fields will be ignored and // a warning message will be generated. - // Please aware that set this option true may hide some errors (e.g. - // spelling error on field name). Avoid to use this option if possible. + // Beware! Setting this option true may hide some errors (e.g. spelling + // error on field name). This allows data loss; unlike binary format, text + // format cannot preserve unknown fields. Avoid using this option + // if possible. void AllowUnknownField(bool allow) { allow_unknown_field_ = allow; } diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h index da7ebe9f72..875f8f3069 100644 --- a/src/google/protobuf/timestamp.pb.h +++ b/src/google/protobuf/timestamp.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index 45fac085c6..2ff8ce1709 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -381,7 +381,7 @@ Type::Type(const Type& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_source_context()) { @@ -438,7 +438,7 @@ void Type::Clear() { fields_.Clear(); oneofs_.Clear(); options_.Clear(); - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); if (GetArena() == nullptr && source_context_ != nullptr) { delete source_context_; } @@ -755,22 +755,22 @@ Field::Field(const Field& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } type_url_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_type_url().empty()) { - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_type_url(), + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_type_url(), GetArena()); } json_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_json_name().empty()) { - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_json_name(), + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_json_name(), GetArena()); } default_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_default_value().empty()) { - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_default_value(), + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_default_value(), GetArena()); } ::memcpy(&kind_, &from.kind_, @@ -827,10 +827,10 @@ void Field::Clear() { (void) cached_has_bits; options_.Clear(); - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - json_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); - default_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); + type_url_.ClearToEmpty(); + json_name_.ClearToEmpty(); + default_value_.ClearToEmpty(); ::memset(&kind_, 0, static_cast( reinterpret_cast(&packed_) - reinterpret_cast(&kind_)) + sizeof(packed_)); @@ -1251,7 +1251,7 @@ Enum::Enum(const Enum& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_source_context()) { @@ -1307,7 +1307,7 @@ void Enum::Clear() { enumvalue_.Clear(); options_.Clear(); - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); if (GetArena() == nullptr && source_context_ != nullptr) { delete source_context_; } @@ -1590,7 +1590,7 @@ EnumValue::EnumValue(const EnumValue& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } number_ = from.number_; @@ -1636,7 +1636,7 @@ void EnumValue::Clear() { (void) cached_has_bits; options_.Clear(); - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); number_ = 0; _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } @@ -1864,7 +1864,7 @@ Option::Option(const Option& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_name().empty()) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), GetArena()); } if (from._internal_has_value()) { @@ -1914,7 +1914,7 @@ void Option::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); if (GetArena() == nullptr && value_ != nullptr) { delete value_; } diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h index f761361790..a11617b13c 100644 --- a/src/google/protobuf/type.pb.h +++ b/src/google/protobuf/type.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -1351,7 +1350,7 @@ class PROTOBUF_EXPORT Option PROTOBUF_FINAL : // string name = 1; inline void Type::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& Type::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Type.name) @@ -1370,31 +1369,30 @@ inline const std::string& Type::_internal_name() const { } inline void Type::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Type::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Type.name) } inline void Type::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name) } inline void Type::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name) } inline std::string* Type::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Type::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Type.name) @@ -1726,7 +1724,7 @@ inline void Field::set_number(::PROTOBUF_NAMESPACE_ID::int32 value) { // string name = 4; inline void Field::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& Field::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Field.name) @@ -1745,31 +1743,30 @@ inline const std::string& Field::_internal_name() const { } inline void Field::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Field::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.name) } inline void Field::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name) } inline void Field::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name) } inline std::string* Field::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Field::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Field.name) @@ -1788,7 +1785,7 @@ inline void Field::set_allocated_name(std::string* name) { // string type_url = 6; inline void Field::clear_type_url() { - type_url_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + type_url_.ClearToEmpty(); } inline const std::string& Field::type_url() const { // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url) @@ -1807,31 +1804,30 @@ inline const std::string& Field::_internal_type_url() const { } inline void Field::_internal_set_type_url(const std::string& value) { - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Field::set_type_url(std::string&& value) { type_url_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.type_url) } inline void Field::set_type_url(const char* value) { GOOGLE_DCHECK(value != nullptr); - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url) } inline void Field::set_type_url(const char* value, size_t size) { - type_url_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url) } inline std::string* Field::_internal_mutable_type_url() { - return type_url_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Field::release_type_url() { // @@protoc_insertion_point(field_release:google.protobuf.Field.type_url) @@ -1929,7 +1925,7 @@ Field::options() const { // string json_name = 10; inline void Field::clear_json_name() { - json_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + json_name_.ClearToEmpty(); } inline const std::string& Field::json_name() const { // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name) @@ -1948,31 +1944,30 @@ inline const std::string& Field::_internal_json_name() const { } inline void Field::_internal_set_json_name(const std::string& value) { - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Field::set_json_name(std::string&& value) { json_name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.json_name) } inline void Field::set_json_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Field.json_name) } inline void Field::set_json_name(const char* value, size_t size) { - json_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.json_name) } inline std::string* Field::_internal_mutable_json_name() { - return json_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return json_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Field::release_json_name() { // @@protoc_insertion_point(field_release:google.protobuf.Field.json_name) @@ -1991,7 +1986,7 @@ inline void Field::set_allocated_json_name(std::string* json_name) { // string default_value = 11; inline void Field::clear_default_value() { - default_value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + default_value_.ClearToEmpty(); } inline const std::string& Field::default_value() const { // @@protoc_insertion_point(field_get:google.protobuf.Field.default_value) @@ -2010,31 +2005,30 @@ inline const std::string& Field::_internal_default_value() const { } inline void Field::_internal_set_default_value(const std::string& value) { - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Field::set_default_value(std::string&& value) { default_value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.default_value) } inline void Field::set_default_value(const char* value) { GOOGLE_DCHECK(value != nullptr); - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Field.default_value) } inline void Field::set_default_value(const char* value, size_t size) { - default_value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.default_value) } inline std::string* Field::_internal_mutable_default_value() { - return default_value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return default_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Field::release_default_value() { // @@protoc_insertion_point(field_release:google.protobuf.Field.default_value) @@ -2057,7 +2051,7 @@ inline void Field::set_allocated_default_value(std::string* default_value) { // string name = 1; inline void Enum::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& Enum::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Enum.name) @@ -2076,31 +2070,30 @@ inline const std::string& Enum::_internal_name() const { } inline void Enum::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Enum::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Enum.name) } inline void Enum::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name) } inline void Enum::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name) } inline std::string* Enum::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Enum::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Enum.name) @@ -2298,7 +2291,7 @@ inline void Enum::set_syntax(PROTOBUF_NAMESPACE_ID::Syntax value) { // string name = 1; inline void EnumValue::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& EnumValue::name() const { // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name) @@ -2317,31 +2310,30 @@ inline const std::string& EnumValue::_internal_name() const { } inline void EnumValue::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void EnumValue::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValue.name) } inline void EnumValue::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name) } inline void EnumValue::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name) } inline std::string* EnumValue::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* EnumValue::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.EnumValue.name) @@ -2423,7 +2415,7 @@ EnumValue::options() const { // string name = 1; inline void Option::clear_name() { - name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + name_.ClearToEmpty(); } inline const std::string& Option::name() const { // @@protoc_insertion_point(field_get:google.protobuf.Option.name) @@ -2442,31 +2434,30 @@ inline const std::string& Option::_internal_name() const { } inline void Option::_internal_set_name(const std::string& value) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void Option::set_name(std::string&& value) { name_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Option.name) } inline void Option::set_name(const char* value) { GOOGLE_DCHECK(value != nullptr); - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name) } inline void Option::set_name(const char* value, size_t size) { - name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name) } inline std::string* Option::_internal_mutable_name() { - return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* Option::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.Option.name) diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto index 50bb996002..f774c766e3 100644 --- a/src/google/protobuf/unittest_custom_options.proto +++ b/src/google/protobuf/unittest_custom_options.proto @@ -45,6 +45,7 @@ option py_generic_services = true; // A custom file option (defined below). option (file_opt1) = 9876543210; +import "google/protobuf/any.proto"; import "google/protobuf/descriptor.proto"; // We don't put this in a package within proto2 because we need to make sure @@ -329,6 +330,9 @@ message Aggregate { // An embedded message set optional AggregateMessageSet mset = 5; + + // An any + optional google.protobuf.Any any = 6; } // Allow Aggregate to be used as an option at all possible locations @@ -376,6 +380,12 @@ option (fileopt) = { s: 'EmbeddedMessageSetElement' } } + + any { + [type.googleapis.com/protobuf_unittest.AggregateMessageSetElement] { + s: 'EmbeddedMessageSetElement' + } + } }; message AggregateMessage { diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc index 451209c797..f40a577cb2 100644 --- a/src/google/protobuf/unknown_field_set.cc +++ b/src/google/protobuf/unknown_field_set.cc @@ -108,8 +108,7 @@ size_t UnknownFieldSet::SpaceUsedExcludingSelfLong() const { size_t total_size = sizeof(fields_) + sizeof(UnknownField) * fields_.size(); - for (int i = 0; i < fields_.size(); i++) { - const UnknownField& field = (fields_)[i]; + for (const UnknownField& field : fields_) { switch (field.type()) { case UnknownField::TYPE_LENGTH_DELIMITED: total_size += sizeof(*field.data_.length_delimited_.string_value) + diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc index e76268a9d5..4246956f55 100644 --- a/src/google/protobuf/util/internal/datapiece.cc +++ b/src/google/protobuf/util/internal/datapiece.cc @@ -47,7 +47,6 @@ namespace util { namespace converter { using util::Status; -using util::StatusOr; using util::error::Code; namespace { @@ -57,7 +56,7 @@ inline Status InvalidArgument(StringPiece value_str) { } template -StatusOr ValidateNumberConversion(To after, From before) { +util::StatusOr ValidateNumberConversion(To after, From before) { if (after == before && MathUtil::Sign(before) == MathUtil::Sign(after)) { return after; @@ -74,7 +73,7 @@ StatusOr ValidateNumberConversion(To after, From before) { // int32, int64, uint32, uint64, double and float // except conversion between double and float. template -StatusOr NumberConvertAndCheck(From before) { +util::StatusOr NumberConvertAndCheck(From before) { if (std::is_same::value) return before; To after = static_cast(before); @@ -84,7 +83,7 @@ StatusOr NumberConvertAndCheck(From before) { // For conversion to integer types (int32, int64, uint32, uint64) from floating // point types (double, float) only. template -StatusOr FloatingPointToIntConvertAndCheck(From before) { +util::StatusOr FloatingPointToIntConvertAndCheck(From before) { if (std::is_same::value) return before; To after = static_cast(before); @@ -92,13 +91,13 @@ StatusOr FloatingPointToIntConvertAndCheck(From before) { } // For conversion between double and float only. -StatusOr FloatToDouble(float before) { +util::StatusOr FloatToDouble(float before) { // Casting float to double should just work as double has more precision // than float. return static_cast(before); } -StatusOr DoubleToFloat(double before) { +util::StatusOr DoubleToFloat(double before) { if (std::isnan(before)) { return std::numeric_limits::quiet_NaN(); } else if (!std::isfinite(before)) { @@ -115,7 +114,7 @@ StatusOr DoubleToFloat(double before) { } // namespace -StatusOr DataPiece::ToInt32() const { +util::StatusOr DataPiece::ToInt32() const { if (type_ == TYPE_STRING) return StringToNumber(safe_strto32); if (type_ == TYPE_DOUBLE) @@ -127,7 +126,7 @@ StatusOr DataPiece::ToInt32() const { return GenericConvert(); } -StatusOr DataPiece::ToUint32() const { +util::StatusOr DataPiece::ToUint32() const { if (type_ == TYPE_STRING) return StringToNumber(safe_strtou32); @@ -140,7 +139,7 @@ StatusOr DataPiece::ToUint32() const { return GenericConvert(); } -StatusOr DataPiece::ToInt64() const { +util::StatusOr DataPiece::ToInt64() const { if (type_ == TYPE_STRING) return StringToNumber(safe_strto64); if (type_ == TYPE_DOUBLE) @@ -152,7 +151,7 @@ StatusOr DataPiece::ToInt64() const { return GenericConvert(); } -StatusOr DataPiece::ToUint64() const { +util::StatusOr DataPiece::ToUint64() const { if (type_ == TYPE_STRING) return StringToNumber(safe_strtou64); @@ -165,7 +164,7 @@ StatusOr DataPiece::ToUint64() const { return GenericConvert(); } -StatusOr DataPiece::ToDouble() const { +util::StatusOr DataPiece::ToDouble() const { if (type_ == TYPE_FLOAT) { return FloatToDouble(float_); } @@ -173,7 +172,7 @@ StatusOr DataPiece::ToDouble() const { if (str_ == "Infinity") return std::numeric_limits::infinity(); if (str_ == "-Infinity") return -std::numeric_limits::infinity(); if (str_ == "NaN") return std::numeric_limits::quiet_NaN(); - StatusOr value = StringToNumber(safe_strtod); + util::StatusOr value = StringToNumber(safe_strtod); if (value.ok() && !std::isfinite(value.value())) { // safe_strtod converts out-of-range values to +inf/-inf, but we want // to report them as errors. @@ -185,7 +184,7 @@ StatusOr DataPiece::ToDouble() const { return GenericConvert(); } -StatusOr DataPiece::ToFloat() const { +util::StatusOr DataPiece::ToFloat() const { if (type_ == TYPE_DOUBLE) { return DoubleToFloat(double_); } @@ -200,7 +199,7 @@ StatusOr DataPiece::ToFloat() const { return GenericConvert(); } -StatusOr DataPiece::ToBool() const { +util::StatusOr DataPiece::ToBool() const { switch (type_) { case TYPE_BOOL: return bool_; @@ -212,7 +211,7 @@ StatusOr DataPiece::ToBool() const { } } -StatusOr DataPiece::ToString() const { +util::StatusOr DataPiece::ToString() const { switch (type_) { case TYPE_STRING: return std::string(str_); @@ -258,7 +257,7 @@ std::string DataPiece::ValueAsStringOrDefault( } } -StatusOr DataPiece::ToBytes() const { +util::StatusOr DataPiece::ToBytes() const { if (type_ == TYPE_BYTES) return str_.ToString(); if (type_ == TYPE_STRING) { std::string decoded; @@ -272,11 +271,11 @@ StatusOr DataPiece::ToBytes() const { } } -StatusOr DataPiece::ToEnum(const google::protobuf::Enum* enum_type, - bool use_lower_camel_for_enums, - bool case_insensitive_enum_parsing, - bool ignore_unknown_enum_values, - bool* is_unknown_enum_value) const { +util::StatusOr DataPiece::ToEnum(const google::protobuf::Enum* enum_type, + bool use_lower_camel_for_enums, + bool case_insensitive_enum_parsing, + bool ignore_unknown_enum_values, + bool* is_unknown_enum_value) const { if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE; if (type_ == TYPE_STRING) { @@ -287,7 +286,7 @@ StatusOr DataPiece::ToEnum(const google::protobuf::Enum* enum_type, if (value != nullptr) return value->number(); // Check if int version of enum is sent as string. - StatusOr int_value = ToInt32(); + util::StatusOr int_value = ToInt32(); if (int_value.ok()) { if (const google::protobuf::EnumValue* enum_value = FindEnumValueByNumberOrNull(enum_type, int_value.value())) { @@ -332,7 +331,7 @@ StatusOr DataPiece::ToEnum(const google::protobuf::Enum* enum_type, } template -StatusOr DataPiece::GenericConvert() const { +util::StatusOr DataPiece::GenericConvert() const { switch (type_) { case TYPE_INT32: return NumberConvertAndCheck(i32_); @@ -354,8 +353,8 @@ StatusOr DataPiece::GenericConvert() const { } template -StatusOr DataPiece::StringToNumber(bool (*func)(StringPiece, - To*)) const { +util::StatusOr DataPiece::StringToNumber(bool (*func)(StringPiece, + To*)) const { if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) { return InvalidArgument(StrCat("\"", str_, "\"")); } diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h index 1b0ccfa244..38ced17277 100644 --- a/src/google/protobuf/util/internal/datapiece.h +++ b/src/google/protobuf/util/internal/datapiece.h @@ -167,10 +167,10 @@ class PROTOBUF_EXPORT DataPiece { // Same as the ToEnum() method above but with additional flag to ignore // unknown enum values. util::StatusOr ToEnum(const google::protobuf::Enum* enum_type, - bool use_lower_camel_for_enums, - bool case_insensitive_enum_parsing, - bool ignore_unknown_enum_values, - bool* is_unknown_enum_value) const; + bool use_lower_camel_for_enums, + bool case_insensitive_enum_parsing, + bool ignore_unknown_enum_values, + bool* is_unknown_enum_value) const; // For numeric conversion between // int32, int64, uint32, uint64, double, float and bool @@ -180,8 +180,7 @@ class PROTOBUF_EXPORT DataPiece { // For conversion from string to // int32, int64, uint32, uint64, double, float and bool template - util::StatusOr StringToNumber(bool (*func)(StringPiece, - To*)) const; + util::StatusOr StringToNumber(bool (*func)(StringPiece, To*)) const; // Decodes a base64 string. Returns true on success. bool DecodeBase64(StringPiece src, std::string* dest) const; diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index a78a862eb0..60a44dbe52 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -40,7 +40,6 @@ namespace google { namespace protobuf { namespace util { using util::Status; -using util::StatusOr; namespace converter { namespace { @@ -49,9 +48,10 @@ namespace { // If value is empty or if conversion fails, the default_value is returned. template T ConvertTo(StringPiece value, - StatusOr (DataPiece::*converter_fn)() const, T default_value) { + util::StatusOr (DataPiece::*converter_fn)() const, + T default_value) { if (value.empty()) return default_value; - StatusOr result = (DataPiece(value, true).*converter_fn)(); + util::StatusOr result = (DataPiece(value, true).*converter_fn)(); return result.ok() ? result.value() : default_value; } } // namespace diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc index 8cb22c79a8..0a321386a1 100644 --- a/src/google/protobuf/util/internal/json_stream_parser.cc +++ b/src/google/protobuf/util/internal/json_stream_parser.cc @@ -853,7 +853,7 @@ util::Status JsonStreamParser::ReportUnknown(StringPiece message) { util::Status JsonStreamParser::IncrementRecursionDepth( StringPiece key) const { if (++recursion_depth_ > max_recursion_depth_) { - return Status( + return util::Status( util::error::INVALID_ARGUMENT, StrCat("Message too deep. Max recursion depth reached for key '", key, "'")); diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc index de93085efa..24a71425ca 100644 --- a/src/google/protobuf/util/internal/proto_writer.cc +++ b/src/google/protobuf/util/internal/proto_writer.cc @@ -55,7 +55,6 @@ namespace converter { using io::CodedOutputStream; using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using util::Status; -using util::StatusOr; using util::error::INVALID_ARGUMENT; @@ -70,6 +69,7 @@ ProtoWriter::ProtoWriter(TypeResolver* type_resolver, ignore_unknown_enum_values_(false), use_lower_camel_for_enums_(false), case_insensitive_enum_parsing_(true), + use_json_name_in_missing_fields_(false), element_(nullptr), size_insert_(), output_(output), @@ -91,6 +91,7 @@ ProtoWriter::ProtoWriter(const TypeInfo* typeinfo, ignore_unknown_enum_values_(false), use_lower_camel_for_enums_(false), case_insensitive_enum_parsing_(true), + use_json_name_in_missing_fields_(false), element_(nullptr), size_insert_(), output_(output), @@ -120,9 +121,9 @@ ProtoWriter::~ProtoWriter() { namespace { // Writes an INT32 field, including tag to the stream. -inline Status WriteInt32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr i32 = data.ToInt32(); +inline util::Status WriteInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr i32 = data.ToInt32(); if (i32.ok()) { WireFormatLite::WriteInt32(field_number, i32.value(), stream); } @@ -130,9 +131,9 @@ inline Status WriteInt32(int field_number, const DataPiece& data, } // writes an SFIXED32 field, including tag, to the stream. -inline Status WriteSFixed32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr i32 = data.ToInt32(); +inline util::Status WriteSFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr i32 = data.ToInt32(); if (i32.ok()) { WireFormatLite::WriteSFixed32(field_number, i32.value(), stream); } @@ -140,9 +141,9 @@ inline Status WriteSFixed32(int field_number, const DataPiece& data, } // Writes an SINT32 field, including tag, to the stream. -inline Status WriteSInt32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr i32 = data.ToInt32(); +inline util::Status WriteSInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr i32 = data.ToInt32(); if (i32.ok()) { WireFormatLite::WriteSInt32(field_number, i32.value(), stream); } @@ -150,9 +151,9 @@ inline Status WriteSInt32(int field_number, const DataPiece& data, } // Writes a FIXED32 field, including tag, to the stream. -inline Status WriteFixed32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr u32 = data.ToUint32(); +inline util::Status WriteFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr u32 = data.ToUint32(); if (u32.ok()) { WireFormatLite::WriteFixed32(field_number, u32.value(), stream); } @@ -160,9 +161,9 @@ inline Status WriteFixed32(int field_number, const DataPiece& data, } // Writes a UINT32 field, including tag, to the stream. -inline Status WriteUInt32(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr u32 = data.ToUint32(); +inline util::Status WriteUInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr u32 = data.ToUint32(); if (u32.ok()) { WireFormatLite::WriteUInt32(field_number, u32.value(), stream); } @@ -170,9 +171,9 @@ inline Status WriteUInt32(int field_number, const DataPiece& data, } // Writes an INT64 field, including tag, to the stream. -inline Status WriteInt64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr i64 = data.ToInt64(); +inline util::Status WriteInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr i64 = data.ToInt64(); if (i64.ok()) { WireFormatLite::WriteInt64(field_number, i64.value(), stream); } @@ -180,9 +181,9 @@ inline Status WriteInt64(int field_number, const DataPiece& data, } // Writes an SFIXED64 field, including tag, to the stream. -inline Status WriteSFixed64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr i64 = data.ToInt64(); +inline util::Status WriteSFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr i64 = data.ToInt64(); if (i64.ok()) { WireFormatLite::WriteSFixed64(field_number, i64.value(), stream); } @@ -190,9 +191,9 @@ inline Status WriteSFixed64(int field_number, const DataPiece& data, } // Writes an SINT64 field, including tag, to the stream. -inline Status WriteSInt64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr i64 = data.ToInt64(); +inline util::Status WriteSInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr i64 = data.ToInt64(); if (i64.ok()) { WireFormatLite::WriteSInt64(field_number, i64.value(), stream); } @@ -200,9 +201,9 @@ inline Status WriteSInt64(int field_number, const DataPiece& data, } // Writes a FIXED64 field, including tag, to the stream. -inline Status WriteFixed64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr u64 = data.ToUint64(); +inline util::Status WriteFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr u64 = data.ToUint64(); if (u64.ok()) { WireFormatLite::WriteFixed64(field_number, u64.value(), stream); } @@ -210,9 +211,9 @@ inline Status WriteFixed64(int field_number, const DataPiece& data, } // Writes a UINT64 field, including tag, to the stream. -inline Status WriteUInt64(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr u64 = data.ToUint64(); +inline util::Status WriteUInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr u64 = data.ToUint64(); if (u64.ok()) { WireFormatLite::WriteUInt64(field_number, u64.value(), stream); } @@ -220,9 +221,9 @@ inline Status WriteUInt64(int field_number, const DataPiece& data, } // Writes a DOUBLE field, including tag, to the stream. -inline Status WriteDouble(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr d = data.ToDouble(); +inline util::Status WriteDouble(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr d = data.ToDouble(); if (d.ok()) { WireFormatLite::WriteDouble(field_number, d.value(), stream); } @@ -230,9 +231,9 @@ inline Status WriteDouble(int field_number, const DataPiece& data, } // Writes a FLOAT field, including tag, to the stream. -inline Status WriteFloat(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr f = data.ToFloat(); +inline util::Status WriteFloat(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr f = data.ToFloat(); if (f.ok()) { WireFormatLite::WriteFloat(field_number, f.value(), stream); } @@ -240,9 +241,9 @@ inline Status WriteFloat(int field_number, const DataPiece& data, } // Writes a BOOL field, including tag, to the stream. -inline Status WriteBool(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr b = data.ToBool(); +inline util::Status WriteBool(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr b = data.ToBool(); if (b.ok()) { WireFormatLite::WriteBool(field_number, b.value(), stream); } @@ -250,9 +251,9 @@ inline Status WriteBool(int field_number, const DataPiece& data, } // Writes a BYTES field, including tag, to the stream. -inline Status WriteBytes(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr c = data.ToBytes(); +inline util::Status WriteBytes(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr c = data.ToBytes(); if (c.ok()) { WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream); } @@ -260,9 +261,9 @@ inline Status WriteBytes(int field_number, const DataPiece& data, } // Writes a STRING field, including tag, to the stream. -inline Status WriteString(int field_number, const DataPiece& data, - CodedOutputStream* stream) { - StatusOr s = data.ToString(); +inline util::Status WriteString(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + util::StatusOr s = data.ToString(); if (s.ok()) { WireFormatLite::WriteString(field_number, s.value(), stream); } @@ -350,7 +351,9 @@ ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() { for (std::set::iterator it = required_fields_.begin(); it != required_fields_.end(); ++it) { - ow_->MissingField((*it)->name()); + ow_->MissingField(ow_->use_json_name_in_missing_fields_ + ? (*it)->json_name() + : (*it)->name()); } } // Computes the total number of proto bytes used by a message, also adjusts @@ -539,7 +542,7 @@ ProtoWriter* ProtoWriter::EndList() { ProtoWriter* ProtoWriter::RenderDataPiece( StringPiece name, const DataPiece& data) { - Status status; + util::Status status; if (invalid_depth_ > 0) return this; const google::protobuf::Field* field = Lookup(name); @@ -593,16 +596,16 @@ ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field, return this; } -Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data, - const google::protobuf::Enum* enum_type, - CodedOutputStream* stream, - bool use_lower_camel_for_enums, - bool case_insensitive_enum_parsing, - bool ignore_unknown_values) { +util::Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data, + const google::protobuf::Enum* enum_type, + CodedOutputStream* stream, + bool use_lower_camel_for_enums, + bool case_insensitive_enum_parsing, + bool ignore_unknown_values) { bool is_unknown_enum_value = false; - StatusOr e = data.ToEnum(enum_type, use_lower_camel_for_enums, - case_insensitive_enum_parsing, - ignore_unknown_values, &is_unknown_enum_value); + util::StatusOr e = data.ToEnum( + enum_type, use_lower_camel_for_enums, case_insensitive_enum_parsing, + ignore_unknown_values, &is_unknown_enum_value); if (e.ok() && !is_unknown_enum_value) { WireFormatLite::WriteEnum(field_number, e.value(), stream); } @@ -612,31 +615,17 @@ Status ProtoWriter::WriteEnum(int field_number, const DataPiece& data, ProtoWriter* ProtoWriter::RenderPrimitiveField( const google::protobuf::Field& field, const google::protobuf::Type& type, const DataPiece& data) { - Status status; + util::Status status; // Pushing a ProtoElement and then pop it off at the end for 2 purposes: // error location reporting and required field accounting. // - // For proto3, since there is no required field tracking, we only need to push - // ProtoElement for error cases. + // For proto3, since there is no required field tracking, we only need to + // push ProtoElement for error cases. if (!element_->proto3()) { element_.reset(new ProtoElement(element_.release(), &field, type, false)); } - if (field.kind() == google::protobuf::Field::TYPE_UNKNOWN || - field.kind() == google::protobuf::Field::TYPE_MESSAGE) { - // Push a ProtoElement for location reporting purposes. - if (element_->proto3()) { - element_.reset(new ProtoElement(element_.release(), &field, type, false)); - } - InvalidValue(field.type_url().empty() - ? google::protobuf::Field_Kind_Name(field.kind()) - : field.type_url(), - data.ValueAsStringOrDefault("")); - element_.reset(element()->pop()); - return this; - } - switch (field.kind()) { case google::protobuf::Field::TYPE_INT32: { status = WriteInt32(field.number(), data, stream_.get()); @@ -705,9 +694,9 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( case_insensitive_enum_parsing_, ignore_unknown_enum_values_); break; } - default: // TYPE_GROUP or TYPE_MESSAGE - status = - Status(util::error::INVALID_ARGUMENT, data.ToString().value()); + default: // TYPE_GROUP, TYPE_MESSAGE, TYPE_UNKNOWN. + status = util::Status(util::error::INVALID_ARGUMENT, + data.ValueAsStringOrDefault("")); } if (!status.ok()) { @@ -715,7 +704,9 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( if (element_->proto3()) { element_.reset(new ProtoElement(element_.release(), &field, type, false)); } - InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), + InvalidValue(field.type_url().empty() + ? google::protobuf::Field_Kind_Name(field.kind()) + : field.type_url(), status.message()); element_.reset(element()->pop()); return this; diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h index 7e79ce31e8..8149ed3624 100644 --- a/src/google/protobuf/util/internal/proto_writer.h +++ b/src/google/protobuf/util/internal/proto_writer.h @@ -159,6 +159,11 @@ class PROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { case_insensitive_enum_parsing_ = case_insensitive_enum_parsing; } + void set_use_json_name_in_missing_fields( + bool use_json_name_in_missing_fields) { + use_json_name_in_missing_fields_ = use_json_name_in_missing_fields; + } + protected: class PROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface { @@ -339,6 +344,9 @@ class PROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // If true, check if enum name in UPPER_CASE matches the field name. bool case_insensitive_enum_parsing_; + // If true, use the json name in missing fields errors. + bool use_json_name_in_missing_fields_; + // Variable for internal state processing: // element_ : the current element. // size_insert_: sizes of nested messages. diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc index 1a9cc9bf41..a941aa0988 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -59,7 +60,6 @@ namespace google { namespace protobuf { namespace util { using util::Status; -using util::StatusOr; namespace error { using util::error::Code; using util::error::INTERNAL; @@ -68,7 +68,6 @@ namespace converter { using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat; using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using util::Status; -using util::StatusOr; namespace { @@ -88,7 +87,7 @@ const google::protobuf::EnumValue* FindEnumValueByNumber( // Utility function to format nanos. const std::string FormatNanos(uint32 nanos, bool with_trailing_zeros); -StatusOr MapKeyDefaultValueAsString( +util::StatusOr MapKeyDefaultValueAsString( const google::protobuf::Field& field) { switch (field.kind()) { case google::protobuf::Field::TYPE_BOOL: @@ -107,7 +106,7 @@ StatusOr MapKeyDefaultValueAsString( case google::protobuf::Field::TYPE_STRING: return std::string(); default: - return Status(util::error::INTERNAL, "Invalid map key type."); + return util::Status(util::error::INTERNAL, "Invalid map key type."); } } } // namespace @@ -159,8 +158,8 @@ ProtoStreamObjectSource::~ProtoStreamObjectSource() { } } -Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, - ObjectWriter* ow) const { +util::Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, + ObjectWriter* ow) const { return WriteMessage(type_, name, 0, true, ow); } @@ -184,11 +183,9 @@ const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( return field; } -Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, - StringPiece name, - const uint32 end_tag, - bool include_start_and_end, - ObjectWriter* ow) const { +util::Status ProtoStreamObjectSource::WriteMessage( + const google::protobuf::Type& type, StringPiece name, + const uint32 end_tag, bool include_start_and_end, ObjectWriter* ow) const { const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); if (type_renderer != nullptr) { @@ -251,7 +248,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, return util::Status(); } -StatusOr ProtoStreamObjectSource::RenderList( +util::StatusOr ProtoStreamObjectSource::RenderList( const google::protobuf::Field* field, StringPiece name, uint32 list_tag, ObjectWriter* ow) const { uint32 tag_to_return = 0; @@ -273,7 +270,7 @@ StatusOr ProtoStreamObjectSource::RenderList( return tag_to_return; } -StatusOr ProtoStreamObjectSource::RenderMap( +util::StatusOr ProtoStreamObjectSource::RenderMap( const google::protobuf::Field* field, StringPiece name, uint32 list_tag, ObjectWriter* ow) const { const google::protobuf::Type* field_type = @@ -303,7 +300,8 @@ StatusOr ProtoStreamObjectSource::RenderMap( if (key_field == nullptr) { // The Type info for this map entry is incorrect. It should always // have a field named "key" and with field number 1. - return Status(util::error::INTERNAL, "Invalid map entry."); + return util::Status(util::error::INTERNAL, + "Invalid map entry."); } ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field)); } @@ -311,7 +309,7 @@ StatusOr ProtoStreamObjectSource::RenderMap( } else { // The Type info for this map entry is incorrect. It should contain // exactly two fields with field number 1 and 2. - return Status(util::error::INTERNAL, "Invalid map entry."); + return util::Status(util::error::INTERNAL, "Invalid map entry."); } } stream_->PopLimit(old_limit); @@ -319,7 +317,7 @@ StatusOr ProtoStreamObjectSource::RenderMap( return tag_to_return; } -Status ProtoStreamObjectSource::RenderPacked( +util::Status ProtoStreamObjectSource::RenderPacked( const google::protobuf::Field* field, ObjectWriter* ow) const { uint32 length; stream_->ReadVarint32(&length); @@ -331,20 +329,21 @@ Status ProtoStreamObjectSource::RenderPacked( return util::Status(); } -Status ProtoStreamObjectSource::RenderTimestamp( +util::Status ProtoStreamObjectSource::RenderTimestamp( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { std::pair p = os->ReadSecondsAndNanos(type); int64 seconds = p.first; int32 nanos = p.second; if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) { - return Status(util::error::INTERNAL, - StrCat("Timestamp seconds exceeds limit for field: ", - field_name)); + return util::Status( + util::error::INTERNAL, + StrCat("Timestamp seconds exceeds limit for field: ", + field_name)); } if (nanos < 0 || nanos >= kNanosPerSecond) { - return Status( + return util::Status( util::error::INTERNAL, StrCat("Timestamp nanos exceeds limit for field: ", field_name)); } @@ -355,20 +354,20 @@ Status ProtoStreamObjectSource::RenderTimestamp( return util::Status(); } -Status ProtoStreamObjectSource::RenderDuration( +util::Status ProtoStreamObjectSource::RenderDuration( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { std::pair p = os->ReadSecondsAndNanos(type); int64 seconds = p.first; int32 nanos = p.second; if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) { - return Status( + return util::Status( util::error::INTERNAL, StrCat("Duration seconds exceeds limit for field: ", field_name)); } if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { - return Status( + return util::Status( util::error::INTERNAL, StrCat("Duration nanos exceeds limit for field: ", field_name)); } @@ -376,7 +375,7 @@ Status ProtoStreamObjectSource::RenderDuration( std::string sign = ""; if (seconds < 0) { if (nanos > 0) { - return Status( + return util::Status( util::error::INTERNAL, StrCat("Duration nanos is non-negative, but seconds is " "negative for field: ", @@ -397,10 +396,9 @@ Status ProtoStreamObjectSource::RenderDuration( return util::Status(); } -Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderDouble( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint64 buffer64 = 0; // default value of Double wrapper value if (tag != 0) { @@ -411,10 +409,9 @@ Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderFloat( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint32 buffer32 = 0; // default value of Float wrapper value if (tag != 0) { @@ -425,10 +422,9 @@ Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderInt64( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint64 buffer64 = 0; // default value of Int64 wrapper value if (tag != 0) { @@ -439,10 +435,9 @@ Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderUInt64( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint64 buffer64 = 0; // default value of UInt64 wrapper value if (tag != 0) { @@ -453,10 +448,9 @@ Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderInt32( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint32 buffer32 = 0; // default value of Int32 wrapper value if (tag != 0) { @@ -467,10 +461,9 @@ Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderUInt32( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint32 buffer32 = 0; // default value of UInt32 wrapper value if (tag != 0) { @@ -481,10 +474,9 @@ Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderBool( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint64 buffer64 = 0; // results in 'false' value as default, which is the // default value of Bool wrapper @@ -496,10 +488,9 @@ Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderString( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint32 buffer32; std::string str; // default value of empty for String wrapper @@ -512,10 +503,9 @@ Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderBytes( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); uint32 buffer32; std::string str; @@ -528,10 +518,9 @@ Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderStruct( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { const google::protobuf::Field* field = nullptr; uint32 tag = os->stream_->ReadTag(); ow->StartObject(field_name); @@ -552,7 +541,7 @@ Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os, return util::Status(); } -Status ProtoStreamObjectSource::RenderStructValue( +util::Status ProtoStreamObjectSource::RenderStructValue( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { const google::protobuf::Field* field = nullptr; @@ -569,7 +558,7 @@ Status ProtoStreamObjectSource::RenderStructValue( } // TODO(skarvaje): Avoid code duplication of for loops and SkipField logic. -Status ProtoStreamObjectSource::RenderStructListValue( +util::Status ProtoStreamObjectSource::RenderStructListValue( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { uint32 tag = os->stream_->ReadTag(); @@ -593,10 +582,9 @@ Status ProtoStreamObjectSource::RenderStructListValue( return util::Status(); } -Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, - const google::protobuf::Type& type, - StringPiece field_name, - ObjectWriter* ow) { +util::Status ProtoStreamObjectSource::RenderAny( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { // An Any is of the form { string type_url = 1; bytes value = 2; } uint32 tag; std::string type_url; @@ -676,7 +664,7 @@ Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, return result; } -Status ProtoStreamObjectSource::RenderFieldMask( +util::Status ProtoStreamObjectSource::RenderFieldMask( const ProtoStreamObjectSource* os, const google::protobuf::Type& type, StringPiece field_name, ObjectWriter* ow) { std::string combined; @@ -709,7 +697,7 @@ Status ProtoStreamObjectSource::RenderFieldMask( std::unordered_map* - ProtoStreamObjectSource::renderers_ = NULL; + ProtoStreamObjectSource::renderers_ = nullptr; PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_; @@ -752,7 +740,7 @@ void ProtoStreamObjectSource::InitRendererMap() { void ProtoStreamObjectSource::DeleteRendererMap() { delete ProtoStreamObjectSource::renderers_; - renderers_ = NULL; + renderers_ = nullptr; } // static @@ -763,7 +751,7 @@ ProtoStreamObjectSource::FindTypeRenderer(const std::string& type_url) { return FindOrNull(*renderers_, type_url); } -Status ProtoStreamObjectSource::RenderField( +util::Status ProtoStreamObjectSource::RenderField( const google::protobuf::Field* field, StringPiece field_name, ObjectWriter* ow) const { // Short-circuit message types as it tends to call WriteMessage recursively @@ -777,7 +765,7 @@ Status ProtoStreamObjectSource::RenderField( const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(field->type_url()); if (type == nullptr) { - return Status( + return util::Status( util::error::INTERNAL, StrCat("Invalid configuration. Could not find the type: ", field->type_url())); @@ -795,8 +783,9 @@ Status ProtoStreamObjectSource::RenderField( --recursion_depth_; if (!stream_->ConsumedEntireMessage()) { - return Status(util::error::INVALID_ARGUMENT, - "Nested protocol message not parsed in its entirety."); + return util::Status( + util::error::INVALID_ARGUMENT, + "Nested protocol message not parsed in its entirety."); } stream_->PopLimit(old_limit); } else { @@ -806,7 +795,7 @@ Status ProtoStreamObjectSource::RenderField( return util::Status(); } -Status ProtoStreamObjectSource::RenderNonMessageField( +util::Status ProtoStreamObjectSource::RenderNonMessageField( const google::protobuf::Field* field, StringPiece field_name, ObjectWriter* ow) const { // Temporary buffers of different types. @@ -1091,10 +1080,10 @@ std::pair ProtoStreamObjectSource::ReadSecondsAndNanos( return std::pair(signed_seconds, signed_nanos); } -Status ProtoStreamObjectSource::IncrementRecursionDepth( +util::Status ProtoStreamObjectSource::IncrementRecursionDepth( StringPiece type_name, StringPiece field_name) const { if (++recursion_depth_ > max_recursion_depth_) { - return Status( + return util::Status( util::error::INVALID_ARGUMENT, StrCat("Message too deep. Max recursion depth reached for type '", type_name, "', field '", field_name, "'")); diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h index 1343d9b3e6..9dce1187e0 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource.h +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -179,8 +179,8 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { // Returns the next tag after reading all map entries. The caller should use // this tag before reading more tags from the stream. util::StatusOr RenderMap(const google::protobuf::Field* field, - StringPiece name, uint32 list_tag, - ObjectWriter* ow) const; + StringPiece name, uint32 list_tag, + ObjectWriter* ow) const; // Renders a packed repeating field. A packed field is stored as: // {tag length item1 item2 item3} instead of the less efficient diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc index ab27349191..4c0caed356 100644 --- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -106,11 +106,11 @@ class ProtostreamObjectSourceTest virtual ~ProtostreamObjectSourceTest() {} void DoTest(const Message& msg, const Descriptor* descriptor) { - Status status = ExecuteTest(msg, descriptor); + util::Status status = ExecuteTest(msg, descriptor); EXPECT_EQ(util::Status(), status); } - Status ExecuteTest(const Message& msg, const Descriptor* descriptor) { + util::Status ExecuteTest(const Message& msg, const Descriptor* descriptor) { std::ostringstream oss; msg.SerializePartialToOstream(&oss); std::string proto = oss.str(); @@ -596,7 +596,7 @@ TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) { current = next; } - Status status = ExecuteTest(cyclic, Cyclic::descriptor()); + util::Status status = ExecuteTest(cyclic, Cyclic::descriptor()); EXPECT_EQ(util::error::INVALID_ARGUMENT, status.code()); } @@ -942,7 +942,7 @@ TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) { // We start the "AnyOut" part and then fail when we hit the Any object. ow_.StartObject(""); - Status status = ExecuteTest(out, AnyOut::descriptor()); + util::Status status = ExecuteTest(out, AnyOut::descriptor()); EXPECT_EQ(util::error::INTERNAL, status.code()); } @@ -958,7 +958,7 @@ TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) { // We start the "AnyOut" part and then fail when we hit the Any object. ow_.StartObject(""); - Status status = ExecuteTest(out, AnyOut::descriptor()); + util::Status status = ExecuteTest(out, AnyOut::descriptor()); EXPECT_EQ(util::error::INTERNAL, status.code()); } @@ -974,7 +974,7 @@ TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) { // We start the "AnyOut" part and then fail when we hit the Any object. ow_.StartObject(""); - Status status = ExecuteTest(out, AnyOut::descriptor()); + util::Status status = ExecuteTest(out, AnyOut::descriptor()); EXPECT_EQ(util::error::INTERNAL, status.code()); } @@ -1107,7 +1107,7 @@ TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) { ts->set_seconds(kTimestampMinSeconds - 1); ow_.StartObject(""); - Status status = ExecuteTest(out, TimestampDuration::descriptor()); + util::Status status = ExecuteTest(out, TimestampDuration::descriptor()); EXPECT_EQ(util::error::INTERNAL, status.code()); } @@ -1118,7 +1118,7 @@ TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) { ts->set_seconds(kTimestampMaxSeconds + 1); ow_.StartObject(""); - Status status = ExecuteTest(out, TimestampDuration::descriptor()); + util::Status status = ExecuteTest(out, TimestampDuration::descriptor()); EXPECT_EQ(util::error::INTERNAL, status.code()); } @@ -1129,7 +1129,7 @@ TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) { dur->set_seconds(kDurationMinSeconds - 1); ow_.StartObject(""); - Status status = ExecuteTest(out, TimestampDuration::descriptor()); + util::Status status = ExecuteTest(out, TimestampDuration::descriptor()); EXPECT_EQ(util::error::INTERNAL, status.code()); } @@ -1140,7 +1140,7 @@ TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) { dur->set_seconds(kDurationMaxSeconds + 1); ow_.StartObject(""); - Status status = ExecuteTest(out, TimestampDuration::descriptor()); + util::Status status = ExecuteTest(out, TimestampDuration::descriptor()); EXPECT_EQ(util::error::INTERNAL, status.code()); } diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 817109b02d..ace209ab27 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -58,7 +58,6 @@ namespace converter { using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite; using std::placeholders::_1; using util::Status; -using util::StatusOr; using util::error::INVALID_ARGUMENT; @@ -74,6 +73,7 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter( set_ignore_unknown_enum_values(options_.ignore_unknown_enum_values); set_use_lower_camel_for_enums(options_.use_lower_camel_for_enums); set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing); + set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields); } ProtoStreamObjectWriter::ProtoStreamObjectWriter( @@ -87,6 +87,7 @@ ProtoStreamObjectWriter::ProtoStreamObjectWriter( set_ignore_unknown_fields(options_.ignore_unknown_fields); set_use_lower_camel_for_enums(options.use_lower_camel_for_enums); set_case_insensitive_enum_parsing(options_.case_insensitive_enum_parsing); + set_use_json_name_in_missing_fields(options.use_json_name_in_missing_fields); } ProtoStreamObjectWriter::ProtoStreamObjectWriter( @@ -329,7 +330,7 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { if (value.type() == DataPiece::TYPE_STRING) { type_url_ = std::string(value.str()); } else { - StatusOr s = value.ToString(); + util::StatusOr s = value.ToString(); if (!s.ok()) { parent_->InvalidValue("String", s.status().message()); invalid_ = true; @@ -338,7 +339,7 @@ void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { type_url_ = s.value(); } // Resolve the type url, and report an error if we failed to resolve it. - StatusOr resolved_type = + util::StatusOr resolved_type = parent_->typeinfo()->ResolveTypeUrl(type_url_); if (!resolved_type.ok()) { parent_->InvalidValue("Any", resolved_type.status().message()); @@ -643,6 +644,16 @@ ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( return this; } + if (field->kind() != google::protobuf::Field::TYPE_GROUP && + field->kind() != google::protobuf::Field::TYPE_MESSAGE) { + IncrementInvalidDepth(); + if (!options_.suppress_object_to_scalar_error) { + InvalidValue(field->name(), "Starting an object on a scalar field"); + } + + return this; + } + // A regular message type. Pass it directly to ProtoWriter. // Render // "": { @@ -910,7 +921,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, switch (data.type()) { case DataPiece::TYPE_INT32: { if (ow->options_.struct_integers_as_strings) { - StatusOr int_value = data.ToInt32(); + util::StatusOr int_value = data.ToInt32(); if (int_value.ok()) { ow->ProtoWriter::RenderDataPiece( "string_value", @@ -923,7 +934,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, } case DataPiece::TYPE_UINT32: { if (ow->options_.struct_integers_as_strings) { - StatusOr int_value = data.ToUint32(); + util::StatusOr int_value = data.ToUint32(); if (int_value.ok()) { ow->ProtoWriter::RenderDataPiece( "string_value", @@ -938,7 +949,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, // If the option to treat integers as strings is set, then render them as // strings. Otherwise, fallback to rendering them as double. if (ow->options_.struct_integers_as_strings) { - StatusOr int_value = data.ToInt64(); + util::StatusOr int_value = data.ToInt64(); if (int_value.ok()) { ow->ProtoWriter::RenderDataPiece( "string_value", DataPiece(StrCat(int_value.value()), true)); @@ -952,7 +963,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, // If the option to treat integers as strings is set, then render them as // strings. Otherwise, fallback to rendering them as double. if (ow->options_.struct_integers_as_strings) { - StatusOr int_value = data.ToUint64(); + util::StatusOr int_value = data.ToUint64(); if (int_value.ok()) { ow->ProtoWriter::RenderDataPiece( "string_value", DataPiece(StrCat(int_value.value()), true)); @@ -964,7 +975,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, } case DataPiece::TYPE_FLOAT: { if (ow->options_.struct_integers_as_strings) { - StatusOr float_value = data.ToFloat(); + util::StatusOr float_value = data.ToFloat(); if (float_value.ok()) { ow->ProtoWriter::RenderDataPiece( "string_value", @@ -977,7 +988,7 @@ Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, } case DataPiece::TYPE_DOUBLE: { if (ow->options_.struct_integers_as_strings) { - StatusOr double_value = data.ToDouble(); + util::StatusOr double_value = data.ToDouble(); if (double_value.ok()) { ow->ProtoWriter::RenderDataPiece( "string_value", @@ -1035,7 +1046,7 @@ Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, } static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow, - StringPiece path) { + StringPiece path) { ow->ProtoWriter::RenderDataPiece( "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true)); return Status(); diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h index cc68c6b1b4..a5bea409d1 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.h +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -107,6 +107,13 @@ class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { // is disabled. bool suppress_implicit_message_list_error; + // If true, suppress the error of rendering scalar field if the source is an + // object. + bool suppress_object_to_scalar_error; + + // If true, use the json name in missing fields errors. + bool use_json_name_in_missing_fields; + Options() : struct_integers_as_strings(false), ignore_unknown_fields(false), @@ -116,7 +123,9 @@ class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter { ignore_null_value_map_entry(false), use_legacy_json_map_format(false), disable_implicit_message_list(false), - suppress_implicit_message_list_error(false) {} + suppress_implicit_message_list_error(false), + suppress_object_to_scalar_error(false), + use_json_name_in_missing_fields(false) {} // Default instance of Options with all options set to defaults. static const Options& Defaults() { diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc index 564050f4f6..211b7bcbf8 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -1000,7 +1000,10 @@ TEST_P(ProtoStreamObjectWriterTest, Proto3Message expected; EXPECT_CALL( listener_, - InvalidValue(_, StringPiece("TYPE_ENUM"), + InvalidValue(_, + StringPiece( + "type.googleapis.com/" + "proto_util_converter.testing.Proto3Message.NestedEnum"), StringPiece("\"someunknownvalueyouwillneverknow\""))) .With(Args<0>(HasObjectLocation("enum_value"))); ow_->StartObject("") diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h index bccea718c4..01cbb9e1ac 100644 --- a/src/google/protobuf/util/internal/structured_objectwriter.h +++ b/src/google/protobuf/util/internal/structured_objectwriter.h @@ -69,7 +69,8 @@ class PROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { public: // Takes ownership of the parent Element. explicit BaseElement(BaseElement* parent) - : parent_(parent), level_(parent == NULL ? 0 : parent->level() + 1) {} + : parent_(parent), + level_(parent == nullptr ? 0 : parent->level() + 1) {} virtual ~BaseElement() {} // Releases ownership of the parent and returns a pointer to it. 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 cc2dcd73cb..ccf6fbd836 100644 --- a/src/google/protobuf/util/internal/type_info_test_helper.cc +++ b/src/google/protobuf/util/internal/type_info_test_helper.cc @@ -95,7 +95,7 @@ ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource( } } GOOGLE_LOG(FATAL) << "Can not reach here."; - return NULL; + return nullptr; } ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter( @@ -109,7 +109,7 @@ ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter( } } GOOGLE_LOG(FATAL) << "Can not reach here."; - return NULL; + return nullptr; } DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter( @@ -121,7 +121,7 @@ DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter( } } GOOGLE_LOG(FATAL) << "Can not reach here."; - return NULL; + return nullptr; } } // namespace testing diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc index 84682fa4d5..1816b6843f 100644 --- a/src/google/protobuf/util/internal/utility.cc +++ b/src/google/protobuf/util/internal/utility.cc @@ -330,7 +330,7 @@ std::string ToSnakeCase(StringPiece input) { return result; } -std::set* well_known_types_ = NULL; +std::set* well_known_types_ = nullptr; PROTOBUF_NAMESPACE_ID::internal::once_flag well_known_types_init_; const char* well_known_types_name_array_[] = { "google.protobuf.Timestamp", "google.protobuf.Duration", diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index 9bfe0dd67e..12cbf945ef 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -112,8 +112,8 @@ class MessageDifferencer::MultipleFieldsMapKeyComparator : message_differencer_(message_differencer), key_field_paths_(key_field_paths) { GOOGLE_CHECK(!key_field_paths_.empty()); - for (int i = 0; i < key_field_paths_.size(); ++i) { - GOOGLE_CHECK(!key_field_paths_[i].empty()); + for (const auto& path : key_field_paths_) { + GOOGLE_CHECK(!path.empty()); } } MultipleFieldsMapKeyComparator(MessageDifferencer* message_differencer, @@ -125,9 +125,8 @@ class MessageDifferencer::MultipleFieldsMapKeyComparator } bool IsMatch(const Message& message1, const Message& message2, const std::vector& parent_fields) const override { - for (int i = 0; i < key_field_paths_.size(); ++i) { - if (!IsMatchInternal(message1, message2, parent_fields, - key_field_paths_[i], 0)) { + for (const auto& path : key_field_paths_) { + if (!IsMatchInternal(message1, message2, parent_fields, path, 0)) { return false; } } @@ -276,11 +275,11 @@ MessageDifferencer::MessageDifferencer() MatchIndicesPostProcessorForSmartList) {} MessageDifferencer::~MessageDifferencer() { - for (int i = 0; i < owned_key_comparators_.size(); ++i) { - delete owned_key_comparators_[i]; + for (MapKeyComparator* comparator : owned_key_comparators_) { + delete comparator; } - for (int i = 0; i < ignore_criteria_.size(); ++i) { - delete ignore_criteria_[i]; + for (IgnoreCriteria* criteria : ignore_criteria_) { + delete criteria; } } @@ -380,9 +379,9 @@ void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey( const FieldDescriptor* field, const std::vector& key_fields) { std::vector > key_field_paths; - for (int i = 0; i < key_fields.size(); ++i) { + for (const FieldDescriptor* key_filed : key_fields) { std::vector key_field_path; - key_field_path.push_back(key_fields[i]); + key_field_path.push_back(key_filed); key_field_paths.push_back(key_field_path); } TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths); @@ -395,9 +394,7 @@ void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey( << "Field must be repeated: " << field->full_name(); GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) << "Field has to be message type. Field name is: " << field->full_name(); - for (int i = 0; i < key_field_paths.size(); ++i) { - const std::vector& key_field_path = - key_field_paths[i]; + for (const auto& key_field_path : key_field_paths) { for (int j = 0; j < key_field_path.size(); ++j) { const FieldDescriptor* parent_field = j == 0 ? field : key_field_path[j - 1]; @@ -919,7 +916,8 @@ bool MessageDifferencer::IsMatch( bool MessageDifferencer::CompareMapFieldByMapReflection( const Message& message1, const Message& message2, - const FieldDescriptor* map_field) { + const FieldDescriptor* map_field, std::vector* parent_fields, + DefaultFieldComparator* comparator) { const Reflection* reflection1 = message1.GetReflection(); const Reflection* reflection2 = message2.GetReflection(); const int count1 = reflection1->MapSize(message1, map_field); @@ -945,9 +943,9 @@ bool MessageDifferencer::CompareMapFieldByMapReflection( } \ MapValueConstRef value2; \ reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \ - if (!default_field_comparator_.Compare##COMPAREMETHOD( \ - *val_des, it.GetValueRef().Get##METHOD(), \ - value2.Get##METHOD())) { \ + if (!comparator->Compare##COMPAREMETHOD(*val_des, \ + it.GetValueRef().Get##METHOD(), \ + value2.Get##METHOD())) { \ return false; \ } \ } \ @@ -972,10 +970,17 @@ bool MessageDifferencer::CompareMapFieldByMapReflection( if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) { return false; } + bool compare_result; MapValueConstRef value2; reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); - if (!Compare(it.GetValueRef().GetMessageValue(), - value2.GetMessageValue())) { + // Append currently compared field to the end of parent_fields. + SpecificField specific_value_field; + specific_value_field.field = val_des; + parent_fields->push_back(specific_value_field); + compare_result = Compare(it.GetValueRef().GetMessageValue(), + value2.GetMessageValue(), parent_fields); + parent_fields->pop_back(); + if (!compare_result) { return false; } } @@ -996,18 +1001,42 @@ bool MessageDifferencer::CompareRepeatedField( // When both map fields are on map, do not sync to repeated field. // TODO(jieluo): Add support for reporter if (repeated_field->is_map() && reporter_ == nullptr && - field_comparator_ == nullptr) { - const FieldDescriptor* key_des = repeated_field->message_type()->map_key(); - const FieldDescriptor* val_des = - repeated_field->message_type()->map_value(); - const internal::MapFieldBase* map_field1 = - reflection1->GetMapData(message1, repeated_field); - const internal::MapFieldBase* map_field2 = - reflection2->GetMapData(message2, repeated_field); - if (map_field1->IsMapValid() && map_field2->IsMapValid() && - ignored_fields_.find(key_des) == ignored_fields_.end() && - ignored_fields_.find(val_des) == ignored_fields_.end()) { - return CompareMapFieldByMapReflection(message1, message2, repeated_field); + // Users didn't set custom map field key comparator + map_field_key_comparator_.find(repeated_field) == + map_field_key_comparator_.end() && + // Users didn't set repeated field comparison + repeated_field_comparison_ == AS_LIST) { + DefaultFieldComparator* map_field_comparator = + field_comparator_ ? nullptr : &default_field_comparator_; +#if PROTOBUF_RTTI + // Inherit class from DefaultFieldComparator can not get the benefit + // because DefaultFieldComparator::Compare() method might be overwrote. + if (field_comparator_ && + typeid(*field_comparator_) == typeid(default_field_comparator_)) { + map_field_comparator = + static_cast(field_comparator_); + } +#endif + if (map_field_comparator) { + const FieldDescriptor* key_des = + repeated_field->message_type()->map_key(); + const FieldDescriptor* val_des = + repeated_field->message_type()->map_value(); + const internal::MapFieldBase* map_field1 = + reflection1->GetMapData(message1, repeated_field); + const internal::MapFieldBase* map_field2 = + reflection2->GetMapData(message2, repeated_field); + std::vector current_parent_fields(*parent_fields); + SpecificField specific_field; + specific_field.field = repeated_field; + current_parent_fields.push_back(specific_field); + if (map_field1->IsMapValid() && map_field2->IsMapValid() && + !IsIgnored(message1, message2, key_des, current_parent_fields) && + !IsIgnored(message1, message2, val_des, current_parent_fields)) { + return CompareMapFieldByMapReflection( + message1, message2, repeated_field, ¤t_parent_fields, + map_field_comparator); + } } } @@ -1204,10 +1233,11 @@ bool MessageDifferencer::CompareFieldValueUsingParentFields( bool MessageDifferencer::CheckPathChanged( const std::vector& field_path) { - for (int i = 0; i < field_path.size(); ++i) { + for (const SpecificField& specific_field : field_path) { // Don't check indexes for map entries -- maps are unordered. - if (field_path[i].field != NULL && field_path[i].field->is_map()) continue; - if (field_path[i].index != field_path[i].new_index) return true; + if (specific_field.field != nullptr && specific_field.field->is_map()) + continue; + if (specific_field.index != specific_field.new_index) return true; } return false; } @@ -1254,9 +1284,8 @@ bool MessageDifferencer::IsIgnored( if (ignored_fields_.find(field) != ignored_fields_.end()) { return true; } - for (int i = 0; i < ignore_criteria_.size(); ++i) { - if (ignore_criteria_[i]->IsIgnored(message1, message2, field, - parent_fields)) { + for (IgnoreCriteria* criteria : ignore_criteria_) { + if (criteria->IsIgnored(message1, message2, field, parent_fields)) { return true; } } @@ -1267,9 +1296,9 @@ bool MessageDifferencer::IsUnknownFieldIgnored( const Message& message1, const Message& message2, const SpecificField& field, const std::vector& parent_fields) { - for (int i = 0; i < ignore_criteria_.size(); ++i) { - if (ignore_criteria_[i]->IsUnknownFieldIgnored(message1, message2, field, - parent_fields)) { + for (IgnoreCriteria* criteria : ignore_criteria_) { + if (criteria->IsUnknownFieldIgnored(message1, message2, field, + parent_fields)) { return true; } } diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h index 943fadf145..2384e51d39 100644 --- a/src/google/protobuf/util/message_differencer.h +++ b/src/google/protobuf/util/message_differencer.h @@ -760,7 +760,9 @@ class PROTOBUF_EXPORT MessageDifferencer { // Compare the map fields using map reflection instead of sync to repeated. bool CompareMapFieldByMapReflection(const Message& message1, const Message& message2, - const FieldDescriptor* field); + const FieldDescriptor* field, + std::vector* parent_fields, + DefaultFieldComparator* comparator); // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields. bool CompareFieldValue(const Message& message1, const Message& message2, diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index 2f40d21eca..2f5908ee1f 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -1462,8 +1462,8 @@ size_t WireFormat::ByteSize(const Message& message) { message_reflection->ListFields(message, &fields); } - for (int i = 0; i < fields.size(); i++) { - our_size += FieldByteSize(fields[i], message); + for (const FieldDescriptor* field : fields) { + our_size += FieldByteSize(field, message); } if (descriptor->options().message_set_wire_format()) { diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index fd5b2edf03..32d9b359e3 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -1661,7 +1661,7 @@ StringValue::StringValue(const StringValue& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_value().empty()) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_value(), + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(), GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.StringValue) @@ -1704,7 +1704,7 @@ void StringValue::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + value_.ClearToEmpty(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } @@ -1867,7 +1867,7 @@ BytesValue::BytesValue(const BytesValue& from) _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); if (!from._internal_value().empty()) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_value(), + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_value(), GetArena()); } // @@protoc_insertion_point(copy_constructor:google.protobuf.BytesValue) @@ -1910,7 +1910,7 @@ void BytesValue::Clear() { // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; - value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + value_.ClearToEmpty(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h index 5a092cd2e8..356e60e8fa 100644 --- a/src/google/protobuf/wrappers.pb.h +++ b/src/google/protobuf/wrappers.pb.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -1515,7 +1514,7 @@ inline void BoolValue::set_value(bool value) { // string value = 1; inline void StringValue::clear_value() { - value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + value_.ClearToEmpty(); } inline const std::string& StringValue::value() const { // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value) @@ -1534,31 +1533,30 @@ inline const std::string& StringValue::_internal_value() const { } inline void StringValue::_internal_set_value(const std::string& value) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void StringValue::set_value(std::string&& value) { value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.StringValue.value) } inline void StringValue::set_value(const char* value) { GOOGLE_DCHECK(value != nullptr); - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.StringValue.value) } inline void StringValue::set_value(const char* value, size_t size) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.StringValue.value) } inline std::string* StringValue::_internal_mutable_value() { - return value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* StringValue::release_value() { // @@protoc_insertion_point(field_release:google.protobuf.StringValue.value) @@ -1581,7 +1579,7 @@ inline void StringValue::set_allocated_value(std::string* value) { // bytes value = 1; inline void BytesValue::clear_value() { - value_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + value_.ClearToEmpty(); } inline const std::string& BytesValue::value() const { // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value) @@ -1600,31 +1598,30 @@ inline const std::string& BytesValue::_internal_value() const { } inline void BytesValue::_internal_set_value(const std::string& value) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena()); } inline void BytesValue::set_value(std::string&& value) { value_.Set( - &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena()); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.BytesValue.value) } inline void BytesValue::set_value(const char* value) { GOOGLE_DCHECK(value != nullptr); - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), - GetArena()); + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena()); // @@protoc_insertion_point(field_set_char:google.protobuf.BytesValue.value) } inline void BytesValue::set_value(const void* value, size_t size) { - value_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string( reinterpret_cast(value), size), GetArena()); // @@protoc_insertion_point(field_set_pointer:google.protobuf.BytesValue.value) } inline std::string* BytesValue::_internal_mutable_value() { - return value_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena()); } inline std::string* BytesValue::release_value() { // @@protoc_insertion_point(field_release:google.protobuf.BytesValue.value)