libweave: Port base/ changes from Chromium project

Now this makes the state of base/ match libchrome's implementation
on Brillo and Chrome OS.

Change-Id: I1c1eb30d2669aeb58a77f332f8c69f130d00878c
Reviewed-on: https://weave-review.googlesource.com/3065
Reviewed-by: Robert Ginda <rginda@google.com>
diff --git a/third_party/chromium/base/strings/string_number_conversions.cc b/third_party/chromium/base/strings/string_number_conversions.cc
index ac0fd46..529e913 100644
--- a/third_party/chromium/base/strings/string_number_conversions.cc
+++ b/third_party/chromium/base/strings/string_number_conversions.cc
@@ -136,6 +136,7 @@
 
     if (begin != end && *begin == '-') {
       if (!std::numeric_limits<value_type>::is_signed) {
+        *output = 0;
         valid = false;
       } else if (!Negative::Invoke(begin + 1, end, output)) {
         valid = false;
diff --git a/third_party/chromium/base/strings/string_number_conversions_unittest.cc b/third_party/chromium/base/strings/string_number_conversions_unittest.cc
index 1cfb2c8..d570c08 100644
--- a/third_party/chromium/base/strings/string_number_conversions_unittest.cc
+++ b/third_party/chromium/base/strings/string_number_conversions_unittest.cc
@@ -133,7 +133,7 @@
   };
 
   for (size_t i = 0; i < arraysize(cases); ++i) {
-    int output = 0;
+    int output = cases[i].output ^ 1;  // Ensure StringToInt wrote something.
     EXPECT_EQ(cases[i].success, StringToInt(cases[i].input, &output));
     EXPECT_EQ(cases[i].output, output);
   }
@@ -182,7 +182,8 @@
   };
 
   for (size_t i = 0; i < arraysize(cases); ++i) {
-    unsigned output = 0;
+    unsigned output =
+        cases[i].output ^ 1;  // Ensure StringToUint wrote something.
     EXPECT_EQ(cases[i].success, StringToUint(cases[i].input, &output));
     EXPECT_EQ(cases[i].output, output);
   }
diff --git a/third_party/chromium/base/strings/string_piece.h b/third_party/chromium/base/strings/string_piece.h
index c79d9fa..b68b1f2 100644
--- a/third_party/chromium/base/strings/string_piece.h
+++ b/third_party/chromium/base/strings/string_piece.h
@@ -143,6 +143,8 @@
   }
 
   value_type operator[](size_type i) const { return ptr_[i]; }
+  value_type front() const { return ptr_[0]; }
+  value_type back() const { return ptr_[length_ - 1]; }
 
   void remove_prefix(size_type n) {
     ptr_ += n;
diff --git a/third_party/chromium/base/strings/string_util.cc b/third_party/chromium/base/strings/string_util.cc
index eb0c546..50f7a23 100644
--- a/third_party/chromium/base/strings/string_util.cc
+++ b/third_party/chromium/base/strings/string_util.cc
@@ -242,4 +242,17 @@
   return true;
 }
 
+
+template <class string_type>
+inline typename string_type::value_type* WriteIntoT(string_type* str,
+                                                    size_t length_with_null) {
+  DCHECK_GT(length_with_null, 1u);
+  str->reserve(length_with_null);
+  str->resize(length_with_null - 1);
+  return &((*str)[0]);
+}
+
+char* WriteInto(std::string* str, size_t length_with_null) {
+  return WriteIntoT(str, length_with_null);
+}
 }  // namespace base
diff --git a/third_party/chromium/base/strings/string_util.h b/third_party/chromium/base/strings/string_util.h
index d6b6e10..f505bb6 100644
--- a/third_party/chromium/base/strings/string_util.h
+++ b/third_party/chromium/base/strings/string_util.h
@@ -173,6 +173,28 @@
 bool IsStringUTF8(const StringPiece& str);
 bool IsStringASCII(const StringPiece& str);
 
+// Reserves enough memory in |str| to accommodate |length_with_null| characters,
+// sets the size of |str| to |length_with_null - 1| characters, and returns a
+// pointer to the underlying contiguous array of characters.  This is typically
+// used when calling a function that writes results into a character array, but
+// the caller wants the data to be managed by a string-like object.  It is
+// convenient in that is can be used inline in the call, and fast in that it
+// avoids copying the results of the call from a char* into a string.
+//
+// |length_with_null| must be at least 2, since otherwise the underlying string
+// would have size 0, and trying to access &((*str)[0]) in that case can result
+// in a number of problems.
+//
+// Internally, this takes linear time because the resize() call 0-fills the
+// underlying array for potentially all
+// (|length_with_null - 1| * sizeof(string_type::value_type)) bytes.  Ideally we
+// could avoid this aspect of the resize() call, as we expect the caller to
+// immediately write over this memory, but there is no other way to set the size
+// of the string, and not doing that will mean people who access |str| rather
+// than str.c_str() will get back a string of whatever size |str| had on entry
+// to this function (probably 0).
+char* WriteInto(std::string* str, size_t length_with_null);
+
 }  // namespace base
 
 #if defined(OS_WIN)
diff --git a/third_party/chromium/base/strings/string_util_unittest.cc b/third_party/chromium/base/strings/string_util_unittest.cc
index 451fbd8..8d77d36 100644
--- a/third_party/chromium/base/strings/string_util_unittest.cc
+++ b/third_party/chromium/base/strings/string_util_unittest.cc
@@ -147,4 +147,39 @@
   }
 }
 
+class WriteIntoTest : public testing::Test {
+ protected:
+  static void WritesCorrectly(size_t num_chars) {
+    std::string buffer;
+    char kOriginal[] = "supercali";
+    strncpy(WriteInto(&buffer, num_chars + 1), kOriginal, num_chars);
+    // Using std::string(buffer.c_str()) instead of |buffer| truncates the
+    // string at the first \0.
+    EXPECT_EQ(std::string(kOriginal,
+                          std::min(num_chars, arraysize(kOriginal) - 1)),
+              std::string(buffer.c_str()));
+    EXPECT_EQ(num_chars, buffer.size());
+  }
+};
+
+TEST_F(WriteIntoTest, WriteInto) {
+  // Validate that WriteInto reserves enough space and
+  // sizes a string correctly.
+  WritesCorrectly(1);
+  WritesCorrectly(2);
+  WritesCorrectly(5000);
+
+  // Validate that WriteInto doesn't modify other strings
+  // when using a Copy-on-Write implementation.
+  const char kLive[] = "live";
+  const char kDead[] = "dead";
+  const std::string live = kLive;
+  std::string dead = live;
+  strncpy(WriteInto(&dead, 5), kDead, 4);
+  EXPECT_EQ(kDead, dead);
+  EXPECT_EQ(4u, dead.size());
+  EXPECT_EQ(kLive, live);
+  EXPECT_EQ(4u, live.size());
+}
+
 }  // namespace base