From 928ebb6b55a23972573328e0ca9500d9730249af Mon Sep 17 00:00:00 2001 From: temporal Date: Wed, 16 Jul 2008 02:00:27 +0000 Subject: Fix bytes type setter to work with byte sequences with embedded NULLs. Patch from Alkis Evlogimenos . --- .../protobuf/compiler/cpp/cpp_string_field.cc | 77 +++++++++++++++++----- src/google/protobuf/compiler/cpp/cpp_unittest.cc | 13 ++++ src/google/protobuf/descriptor.pb.h | 8 +-- 3 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index de59ac87..e74eb432 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -96,8 +96,14 @@ GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, "inline const ::std::string& $name$() const;\n" - "inline void set_$name$(const ::std::string& value);\n" - "inline void set_$name$(const char* value);\n"); + "inline void set_$name$(const ::std::string& value);\n"); + if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) { + printer->Print(variables_, + "inline void set_$name$(const char* value, size_t size);\n"); + } else { + printer->Print(variables_, + "inline void set_$name$(const char* value);\n"); + } printer->Print(variables_, "inline ::std::string* mutable_$name$();\n"); @@ -121,14 +127,28 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" - "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n" - " $name$_ = new ::std::string;\n" - " }\n" - " $name$_->assign(value);\n" "}\n"); + + if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) { + printer->Print(variables_, + "inline void $classname$::set_$name$(const char* value, size_t size) {\n" + " _set_bit($index$);\n" + " if ($name$_ == &_default_$name$_) {\n" + " $name$_ = new ::std::string;\n" + " }\n" + " $name$_->assign(value, size);\n" + "}\n"); + } else { + printer->Print(variables_, + "inline void $classname$::set_$name$(const char* value) {\n" + " _set_bit($index$);\n" + " if ($name$_ == &_default_$name$_) {\n" + " $name$_ = new ::std::string;\n" + " }\n" + " $name$_->assign(value);\n" + "}\n"); + } + printer->Print(variables_, "inline ::std::string* $classname$::mutable_$name$() {\n" " _set_bit($index$);\n" @@ -245,10 +265,18 @@ GenerateAccessorDeclarations(io::Printer* printer) const { "inline const ::std::string& $name$(int index) const;\n" "inline ::std::string* mutable_$name$(int index);\n" "inline void set_$name$(int index, const ::std::string& value);\n" - "inline void set_$name$(int index, const char* value);\n" "inline ::std::string* add_$name$();\n" - "inline void add_$name$(const ::std::string& value);\n" - "inline void add_$name$(const char* value);\n"); + "inline void add_$name$(const ::std::string& value);\n"); + + if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) { + printer->Print(variables_, + "inline void set_$name$(int index, const char* value, size_t size);\n" + "inline void add_$name$(const char* value, size_t size);\n"); + } else { + printer->Print(variables_, + "inline void set_$name$(int index, const char* value);\n" + "inline void add_$name$(const char* value);\n"); + } if (descriptor_->options().has_ctype()) { printer->Outdent(); @@ -277,18 +305,31 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" " $name$_.Mutable(index)->assign(value);\n" "}\n" - "inline void $classname$::set_$name$(int index, const char* value) {\n" - " $name$_.Mutable(index)->assign(value);\n" - "}\n" "inline ::std::string* $classname$::add_$name$() {\n" " return $name$_.Add();\n" "}\n" "inline void $classname$::add_$name$(const ::std::string& value) {\n" " $name$_.Add()->assign(value);\n" - "}\n" - "inline void $classname$::add_$name$(const char* value) {\n" - " $name$_.Add()->assign(value);\n" "}\n"); + + if (descriptor_->type() == FieldDescriptor::TYPE_BYTES) { + printer->Print(variables_, + "inline void " + "$classname$::set_$name$(int index, const char* value, size_t size) {\n" + " $name$_.Mutable(index)->assign(value, size);\n" + "}\n" + "inline void $classname$::add_$name$(const char* value, size_t size) {\n" + " $name$_.Add()->assign(value, size);\n" + "}\n"); + } else { + printer->Print(variables_, + "inline void $classname$::set_$name$(int index, const char* value) {\n" + " $name$_.Mutable(index)->assign(value);\n" + "}\n" + "inline void $classname$::add_$name$(const char* value) {\n" + " $name$_.Add()->assign(value);\n" + "}\n"); + } } void RepeatedStringFieldGenerator:: diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 8253242b..561a5ad1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -172,6 +172,19 @@ TEST(GeneratedMessageTest, Clear) { &message.optional_import_message()); } +TEST(GeneratedMessageTest, EmbeddedNullsInBytesCharStar) { + unittest::TestAllTypes message; + + const char* value = "\0lalala\0\0"; + message.set_optional_bytes(value, 9); + ASSERT_EQ(9, message.optional_bytes().size()); + EXPECT_EQ(0, memcmp(value, message.optional_bytes().data(), 9)); + + message.add_repeated_bytes(value, 9); + ASSERT_EQ(9, message.repeated_bytes(0).size()); + EXPECT_EQ(0, memcmp(value, message.repeated_bytes(0).data(), 9)); +} + TEST(GeneratedMessageTest, ClearOneField) { // Set every field to a unique value, then clear one value and insure that // only that one value is cleared. diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 892f92d0..27994dda 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -174,9 +174,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag inline const ::std::string& dependency(int index) const; inline ::std::string* mutable_dependency(int index); inline void set_dependency(int index, const ::std::string& value); - inline void set_dependency(int index, const char* value); inline ::std::string* add_dependency(); inline void add_dependency(const ::std::string& value); + inline void set_dependency(int index, const char* value); inline void add_dependency(const char* value); // repeated .google.protobuf.DescriptorProto message_type = 4; @@ -1835,15 +1835,15 @@ inline ::std::string* FileDescriptorProto::mutable_dependency(int index) { inline void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { dependency_.Mutable(index)->assign(value); } -inline void FileDescriptorProto::set_dependency(int index, const char* value) { - dependency_.Mutable(index)->assign(value); -} inline ::std::string* FileDescriptorProto::add_dependency() { return dependency_.Add(); } inline void FileDescriptorProto::add_dependency(const ::std::string& value) { dependency_.Add()->assign(value); } +inline void FileDescriptorProto::set_dependency(int index, const char* value) { + dependency_.Mutable(index)->assign(value); +} inline void FileDescriptorProto::add_dependency(const char* value) { dependency_.Add()->assign(value); } -- cgit v1.2.3