shill: Added move operators to ByteString and IPAddress.

This change address move assignment operator and move constructor to
ByteString and to IPAddress.

ByteStrings can become very large and copying them can become expensive
operations.  IPAddress can similarly benefit.  By providing move
operators to them, they can be efficiently passed.

TEST=unittest
BUG=chromium:863260

Change-Id: I8faf0e06d5cadabd6407bb544ff25e73ee0a9321
Reviewed-on: https://chromium-review.googlesource.com/1170562
Commit-Ready: Alex Dale <sigquit@google.com>
Tested-by: Alex Dale <sigquit@google.com>
Reviewed-by: Stephen Barber <smbarber@chromium.org>
diff --git a/net/byte_string.h b/net/byte_string.h
index 08018d7..b38d92c 100644
--- a/net/byte_string.h
+++ b/net/byte_string.h
@@ -31,6 +31,7 @@
  public:
   ByteString() {}
   ByteString(const ByteString& b);
+  ByteString(ByteString&&) = default;
 
   explicit ByteString(const std::vector<unsigned char>& data) : data_(data) {}
 
@@ -53,6 +54,7 @@
                                                      1 : 0))) {}
 
   ByteString& operator=(const ByteString& b);
+  ByteString& operator=(ByteString&&) = default;
 
   unsigned char* GetData();
   const unsigned char* GetConstData() const;
diff --git a/net/byte_string_unittest.cc b/net/byte_string_unittest.cc
index 219b119..23ad277 100644
--- a/net/byte_string_unittest.cc
+++ b/net/byte_string_unittest.cc
@@ -19,9 +19,10 @@
 #include <arpa/inet.h>
 #include <endian.h>
 
-#include <gtest/gtest.h>
-
 #include <string>
+#include <utility>
+
+#include <gtest/gtest.h>
 
 using testing::Test;
 using std::string;
@@ -332,4 +333,27 @@
   EXPECT_FALSE(bs5 < bs5);
 }
 
+TEST_F(ByteStringTest, MoveConstructor) {
+  const ByteString const_data(kTest1, sizeof(kTest1));
+  ByteString source_data(kTest1, sizeof(kTest1));
+  EXPECT_EQ(const_data, source_data);
+
+  const ByteString dest_data(std::move(source_data));
+  EXPECT_TRUE(source_data.IsEmpty());
+  EXPECT_EQ(const_data, dest_data);
+}
+
+TEST_F(ByteStringTest, MoveAssignmentOperator) {
+  const ByteString const_data(kTest1, sizeof(kTest1));
+  ByteString source_data(kTest1, sizeof(kTest1));
+  ByteString dest_data(kTest2, sizeof(kTest2));
+
+  EXPECT_EQ(const_data, source_data);
+  EXPECT_FALSE(const_data.Equals(dest_data));
+
+  dest_data = std::move(source_data);
+  EXPECT_TRUE(source_data.IsEmpty());
+  EXPECT_EQ(const_data, dest_data);
+}
+
 }  // namespace shill
diff --git a/net/ip_address.h b/net/ip_address.h
index 0dc8568..9062809 100644
--- a/net/ip_address.h
+++ b/net/ip_address.h
@@ -20,6 +20,7 @@
 #include <netinet/in.h>
 
 #include <string>
+#include <utility>
 
 #include "shill/net/byte_string.h"
 #include "shill/net/shill_export.h"
@@ -58,10 +59,28 @@
     : family_(b.family_),
       address_(b.address_),
       prefix_(b.prefix_) {}
+  IPAddress(IPAddress&& b)
+      : family_(b.family_),
+        address_(std::move(b.address_)),
+        prefix_(b.prefix_) {
+    b.family_ = kFamilyUnknown;
+  }
+
   IPAddress& operator=(const IPAddress& b) {
-    family_ = b.family_;
-    address_ = b.address_;
-    prefix_ = b.prefix_;
+    if (this != &b) {
+      family_ = b.family_;
+      address_ = b.address_;
+      prefix_ = b.prefix_;
+    }
+    return *this;
+  }
+  IPAddress& operator=(IPAddress&& b) {
+    if (this != &b) {
+      family_ = b.family_;
+      b.family_ = kFamilyUnknown;
+      address_ = std::move(b.address_);
+      prefix_ = b.prefix_;
+    }
     return *this;
   }
 
diff --git a/net/ip_address_unittest.cc b/net/ip_address_unittest.cc
index 998b6b4..672f83f 100644
--- a/net/ip_address_unittest.cc
+++ b/net/ip_address_unittest.cc
@@ -17,6 +17,7 @@
 #include <arpa/inet.h>
 
 #include <tuple>
+#include <utility>
 #include <vector>
 
 #include <base/macros.h>
@@ -554,4 +555,29 @@
         testing::Range<size_t>(0, arraysize(kIPv4OrderedAddresses) - 1),
         testing::Range<size_t>(0, arraysize(kIPv6OrderedAddresses) - 1)));
 
+TEST(IPAddressMoveTest, MoveConstructor) {
+  const IPAddress const_address(kV4String1);
+  IPAddress source_address(kV4String1);
+  EXPECT_EQ(const_address, source_address);
+
+  const IPAddress dest_address(std::move(source_address));
+  EXPECT_EQ(source_address.GetLength(), 0);
+  EXPECT_FALSE(source_address.IsValid());
+  EXPECT_EQ(const_address, dest_address);
+}
+
+TEST(IPAddressMoveTest, MoveAssignmentOperator) {
+  const IPAddress const_address(kV4String1);
+  IPAddress source_address(kV4String1);
+  IPAddress dest_address(kV4String2);
+
+  EXPECT_EQ(const_address, source_address);
+  EXPECT_FALSE(const_address.Equals(dest_address));
+
+  dest_address = std::move(source_address);
+  EXPECT_EQ(source_address.GetLength(), 0);
+  EXPECT_FALSE(source_address.IsValid());
+  EXPECT_EQ(const_address, dest_address);
+}
+
 }  // namespace shill