| 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
|
|
|