Index: base/strings/string_split.cc |
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc |
index b01ca66dea7476ff331a0a111e86d18617e0e5ee..4253e2f8f86b7ed393dfdf66193b91b489176bf8 100644 |
--- a/base/strings/string_split.cc |
+++ b/base/strings/string_split.cc |
@@ -99,52 +99,57 @@ static std::vector<OutputStringType> SplitStringT( |
return result; |
} |
-bool SplitStringIntoKeyValue(const std::string& line, |
- char key_value_delimiter, |
- std::string* key, |
- std::string* value) { |
- key->clear(); |
- value->clear(); |
+bool AppendStringKeyValue(StringPiece input, |
+ char delimiter, |
+ StringPairs* result) { |
+ // Always append a new item regardless of success (it might be empty). The |
+ // below code will copy the strings directly into the result pair. |
+ result->resize(result->size() + 1); |
+ auto& result_pair = result->back(); |
// Find the delimiter. |
- size_t end_key_pos = line.find_first_of(key_value_delimiter); |
+ size_t end_key_pos = input.find_first_of(delimiter); |
if (end_key_pos == std::string::npos) { |
- DVLOG(1) << "cannot find delimiter in: " << line; |
- return false; // no delimiter |
+ DVLOG(1) << "cannot find delimiter in: " << input; |
+ return false; // No delimiter. |
} |
- key->assign(line, 0, end_key_pos); |
+ input.substr(0, end_key_pos).CopyToString(&result_pair.first); |
// Find the value string. |
- std::string remains(line, end_key_pos, line.size() - end_key_pos); |
- size_t begin_value_pos = remains.find_first_not_of(key_value_delimiter); |
- if (begin_value_pos == std::string::npos) { |
- DVLOG(1) << "cannot parse value from line: " << line; |
- return false; // no value |
+ StringPiece remains = input.substr(end_key_pos, input.size() - end_key_pos); |
+ size_t begin_value_pos = remains.find_first_not_of(delimiter); |
+ if (begin_value_pos == StringPiece::npos) { |
+ DVLOG(1) << "cannot parse value from input: " << input; |
+ return false; // No value. |
} |
- value->assign(remains, begin_value_pos, remains.size() - begin_value_pos); |
+ remains.substr(begin_value_pos, remains.size() - begin_value_pos) |
+ .CopyToString(&result_pair.second); |
+ |
return true; |
} |
-template <typename STR> |
-void SplitStringUsingSubstrT(const STR& str, |
- const STR& s, |
- std::vector<STR>* r) { |
- r->clear(); |
- typename STR::size_type begin_index = 0; |
+template <typename Str> |
+void SplitStringUsingSubstrT(BasicStringPiece<Str> input, |
+ BasicStringPiece<Str> delimiter, |
+ std::vector<Str>* result) { |
+ using Piece = BasicStringPiece<Str>; |
+ using size_type = typename Piece::size_type; |
+ |
+ result->clear(); |
+ size_type begin_index = 0; |
while (true) { |
- const typename STR::size_type end_index = str.find(s, begin_index); |
- if (end_index == STR::npos) { |
- const STR term = str.substr(begin_index); |
- STR tmp; |
- TrimWhitespace(term, TRIM_ALL, &tmp); |
- r->push_back(tmp); |
+ size_type end_index = input.find(delimiter, begin_index); |
+ if (end_index == Piece::npos) { |
+ // No delimiter, use the rest of the string. |
+ Piece term = TrimString(input.substr(begin_index), |
+ WhitespaceForType<Str>(), TRIM_ALL); |
+ result->push_back(term.as_string()); |
return; |
} |
- const STR term = str.substr(begin_index, end_index - begin_index); |
- STR tmp; |
- TrimWhitespace(term, TRIM_ALL, &tmp); |
- r->push_back(tmp); |
- begin_index = end_index + s.size(); |
+ Piece term = TrimString(input.substr(begin_index, end_index - begin_index), |
+ WhitespaceForType<Str>(), TRIM_ALL); |
+ result->push_back(term.as_string()); |
+ begin_index = end_index + delimiter.size(); |
} |
} |
@@ -198,77 +203,38 @@ std::vector<StringPiece16> SplitStringPiece(StringPiece16 input, |
input, separators, whitespace, result_type); |
} |
-void SplitString(const string16& str, |
- char16 c, |
- std::vector<string16>* result) { |
- DCHECK(CBU16_IS_SINGLE(c)); |
- *result = SplitStringT<string16, string16, char16>( |
- str, c, TRIM_WHITESPACE, SPLIT_WANT_ALL); |
- |
- // Backward-compat hack: The old SplitString implementation would keep |
- // empty substrings, for example: |
- // "a,,b" -> ["a", "", "b"] |
- // "a, ,b" -> ["a", "", "b"] |
- // which the current code also does. But the old one would discard them when |
- // the only result was that empty string: |
- // " " -> [] |
- // In the latter case, our new code will give [""] |
- if (result->size() == 1 && (*result)[0].empty()) |
- result->clear(); |
-} |
- |
-void SplitString(const std::string& str, |
- char c, |
- std::vector<std::string>* result) { |
-#if CHAR_MIN < 0 |
- DCHECK_GE(c, 0); |
-#endif |
- DCHECK_LT(c, 0x7F); |
- *result = SplitStringT<std::string, std::string, char>( |
- str, c, TRIM_WHITESPACE, SPLIT_WANT_ALL); |
- |
- // Backward-compat hack, see above. |
- if (result->size() == 1 && (*result)[0].empty()) |
- result->clear(); |
-} |
- |
-bool SplitStringIntoKeyValuePairs(const std::string& line, |
+bool SplitStringIntoKeyValuePairs(StringPiece input, |
char key_value_delimiter, |
char key_value_pair_delimiter, |
StringPairs* key_value_pairs) { |
key_value_pairs->clear(); |
- std::vector<std::string> pairs; |
- SplitString(line, key_value_pair_delimiter, &pairs); |
+ std::vector<StringPiece> pairs = SplitStringPiece( |
+ input, std::string(1, key_value_pair_delimiter), |
+ TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); |
+ key_value_pairs->reserve(pairs.size()); |
bool success = true; |
- for (size_t i = 0; i < pairs.size(); ++i) { |
- // Don't add empty pairs into the result. |
- if (pairs[i].empty()) |
- continue; |
- |
- std::string key; |
- std::string value; |
- if (!SplitStringIntoKeyValue(pairs[i], key_value_delimiter, &key, &value)) { |
+ for (const StringPiece& pair : pairs) { |
+ if (!AppendStringKeyValue(pair, key_value_delimiter, key_value_pairs)) { |
// Don't return here, to allow for pairs without associated |
// value or key; just record that the split failed. |
success = false; |
} |
- key_value_pairs->push_back(make_pair(key, value)); |
} |
return success; |
} |
-void SplitStringUsingSubstr(const string16& str, |
- const string16& s, |
- std::vector<string16>* r) { |
- SplitStringUsingSubstrT(str, s, r); |
+void SplitStringUsingSubstr(StringPiece16 input, |
+ StringPiece16 delimiter, |
+ std::vector<string16>* result) { |
+ SplitStringUsingSubstrT(input, delimiter, result); |
} |
-void SplitStringUsingSubstr(const std::string& str, |
- const std::string& s, |
- std::vector<std::string>* r) { |
- SplitStringUsingSubstrT(str, s, r); |
+void SplitStringUsingSubstr(StringPiece input, |
+ StringPiece delimiter, |
+ std::vector<std::string>* result) { |
+ SplitStringUsingSubstrT(input, delimiter, result); |
} |
} // namespace base |