Index: base/strings/string_util.cc |
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc |
index cb668ed7fff4f60f76291a0a19d478fb9faaacd5..49ae9435e934febcd1383437616287af2d22ede5 100644 |
--- a/base/strings/string_util.cc |
+++ b/base/strings/string_util.cc |
@@ -64,6 +64,21 @@ static bool CompareParameter(const ReplacementOffset& elem1, |
return elem1.parameter < elem2.parameter; |
} |
+// Overloaded function to append one string onto the end of another. Having a |
+// separate overload for |source| as both string and StringPiece allows for more |
+// efficient usage from functions templated to work with either type (avoiding a |
+// redundant call to the BasicStringPiece constructor in both cases). |
+template <typename string_type> |
+inline void AppendToString(string_type* target, const string_type& source) { |
+ target->append(source); |
+} |
+ |
+template <typename string_type> |
+inline void AppendToString(string_type* target, |
+ const BasicStringPiece<string_type>& source) { |
+ source.AppendToString(target); |
+} |
+ |
// Assuming that a pointer is the size of a "machine word", then |
// uintptr_t is an integer type that is also a machine word. |
typedef uintptr_t MachineWord; |
@@ -853,19 +868,28 @@ char16* WriteInto(string16* str, size_t length_with_null) { |
return WriteIntoT(str, length_with_null); |
} |
-template<typename STR> |
-static STR JoinStringT(const std::vector<STR>& parts, |
- BasicStringPiece<STR> sep) { |
- if (parts.empty()) |
- return STR(); |
- |
- STR result(parts[0]); |
+// Generic version for all JoinString overloads. |list_type| must be a sequence |
+// (std::vector or std::initializer_list) of strings/StringPieces (std::string, |
+// string16, StringPiece or StringPiece16). |string_type| is either std::string |
+// or string16. |
+template <typename list_type, typename string_type> |
+static string_type JoinStringT(const list_type& parts, |
+ BasicStringPiece<string_type> sep) { |
auto iter = parts.begin(); |
+ // Early-exit to avoid bad access to the first element. |
+ if (iter == parts.end()) |
+ return string_type(); |
+ |
+ // Begin constructing the result from the first element. |
+ string_type result(iter->data(), iter->size()); |
++iter; |
for (; iter != parts.end(); ++iter) { |
sep.AppendToString(&result); |
- result += *iter; |
+ // Using the overloaded AppendToString allows this template function to work |
+ // on both strings and StringPieces without creating an intermediate |
+ // StringPiece object. |
+ AppendToString(&result, *iter); |
} |
return result; |
@@ -881,6 +905,26 @@ string16 JoinString(const std::vector<string16>& parts, |
return JoinStringT(parts, separator); |
} |
+std::string JoinString(const std::vector<StringPiece>& parts, |
+ StringPiece separator) { |
+ return JoinStringT(parts, separator); |
+} |
+ |
+string16 JoinString(const std::vector<StringPiece16>& parts, |
+ StringPiece16 separator) { |
+ return JoinStringT(parts, separator); |
+} |
+ |
+std::string JoinString(std::initializer_list<StringPiece> parts, |
+ StringPiece separator) { |
+ return JoinStringT(parts, separator); |
+} |
+ |
+string16 JoinString(std::initializer_list<StringPiece16> parts, |
+ StringPiece16 separator) { |
+ return JoinStringT(parts, separator); |
+} |
+ |
template<class FormatStringType, class OutStringType> |
OutStringType DoReplaceStringPlaceholders( |
const FormatStringType& format_string, |