aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/cpp
diff options
context:
space:
mode:
authorGravatar Chris Kennelly <ckennelly@google.com>2016-12-15 16:17:17 -0800
committerGravatar Chris Kennelly <ckennelly@google.com>2016-12-16 13:50:14 -0800
commit183d31cbdb5197b1a014893a91198e970379f656 (patch)
tree1dcb6e66e200a91724895185b4561aec8dc9552b /src/google/protobuf/compiler/cpp
parenta95e38ce8dec20d327692f4f5c2b0d37d6776696 (diff)
Add rvalue setters for non-arena strings on C++11.
Diffstat (limited to 'src/google/protobuf/compiler/cpp')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc32
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc46
2 files changed, 77 insertions, 1 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index a9505e3d..2874de7d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -141,7 +141,16 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
printer->Print(variables_,
"$deprecated_attr$const ::std::string& $name$() const;\n"
- "$deprecated_attr$void set_$name$(const ::std::string& value);\n"
+ "$deprecated_attr$void set_$name$(const ::std::string& value);\n");
+
+ if (!SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "#if LANG_CXX11\n"
+ "$deprecated_attr$void set_$name$(::std::string&& value);\n"
+ "#endif\n");
+ }
+
+ printer->Print(variables_,
"$deprecated_attr$void set_$name$(const char* value);\n"
"$deprecated_attr$void set_$name$(const $pointer_type$* value, size_t size)"
";\n"
@@ -249,6 +258,14 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
+ "#if LANG_CXX11\n"
+ "$inline$void $classname$::set_$name$(::std::string&& value) {\n"
+ " $set_hasbit$\n"
+ " $name$_.SetNoArena(\n"
+ " $default_variable$, ::std::move(value));\n"
+ " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+ "}\n"
+ "#endif\n"
"$inline$void $classname$::set_$name$(const char* value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
@@ -633,6 +650,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
+ "#if LANG_CXX11\n"
+ "$inline$void $classname$::set_$name$(::std::string&& value) {\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.SetNoArena(\n"
+ " $default_variable$, ::std::move(value));\n"
+ " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+ "}\n"
+ "#endif\n"
"$inline$void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 8eaddb87..686c70a9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -53,6 +53,7 @@
#include <vector>
#include <google/protobuf/unittest.pb.h>
+#include <google/protobuf/unittest_no_arena.pb.h>
#include <google/protobuf/unittest_optimize_for.pb.h>
#include <google/protobuf/unittest_embed_optimize_for.pb.h>
#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
@@ -420,6 +421,51 @@ TEST(GeneratedMessageTest, StringCharStarLength) {
EXPECT_EQ("wx", message.repeated_string(0));
}
+#if LANG_CXX11
+TEST(GeneratedMessageTest, StringMove) {
+ // Verify that we trigger the move behavior on a scalar setter.
+ protobuf_unittest_no_arena::TestAllTypes message;
+ {
+ string tmp(32, 'a');
+
+ const char* old_data = tmp.data();
+ message.set_optional_string(std::move(tmp));
+ const char* new_data = message.optional_string().data();
+
+ EXPECT_EQ(old_data, new_data);
+ EXPECT_EQ(string(32, 'a'), message.optional_string());
+
+ string tmp2(32, 'b');
+ old_data = tmp2.data();
+ message.set_optional_string(std::move(tmp2));
+ new_data = message.optional_string().data();
+
+ EXPECT_EQ(old_data, new_data);
+ EXPECT_EQ(string(32, 'b'), message.optional_string());
+ }
+
+ // Verify that we trigger the move behavior on a oneof setter.
+ {
+ string tmp(32, 'a');
+
+ const char* old_data = tmp.data();
+ message.set_oneof_string(std::move(tmp));
+ const char* new_data = message.oneof_string().data();
+
+ EXPECT_EQ(old_data, new_data);
+ EXPECT_EQ(string(32, 'a'), message.oneof_string());
+
+ string tmp2(32, 'b');
+ old_data = tmp2.data();
+ message.set_oneof_string(std::move(tmp2));
+ new_data = message.oneof_string().data();
+
+ EXPECT_EQ(old_data, new_data);
+ EXPECT_EQ(string(32, 'b'), message.oneof_string());
+ }
+}
+#endif
+
TEST(GeneratedMessageTest, CopyFrom) {
unittest::TestAllTypes message1, message2;