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