diff options
Diffstat (limited to 'base/strings/string_split.cc')
-rw-r--r-- | base/strings/string_split.cc | 196 |
1 files changed, 76 insertions, 120 deletions
diff --git a/base/strings/string_split.cc b/base/strings/string_split.cc index e23ce3fa03..6c949b989a 100644 --- a/base/strings/string_split.cc +++ b/base/strings/string_split.cc @@ -4,6 +4,8 @@ #include "base/strings/string_split.h" +#include <stddef.h> + #include "base/logging.h" #include "base/strings/string_util.h" #include "base/third_party/icu/icu_utf.h" @@ -99,52 +101,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; - 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); - 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(); +template <typename Str, typename OutputStringType> +void SplitStringUsingSubstrT(BasicStringPiece<Str> input, + BasicStringPiece<Str> delimiter, + WhitespaceHandling whitespace, + SplitResult result_type, + std::vector<OutputStringType>* result) { + using Piece = BasicStringPiece<Str>; + using size_type = typename Piece::size_type; + + result->clear(); + for (size_type begin_index = 0, end_index = 0; end_index != Piece::npos; + begin_index = end_index + delimiter.size()) { + end_index = input.find(delimiter, begin_index); + Piece term = end_index == Piece::npos + ? input.substr(begin_index) + : input.substr(begin_index, end_index - begin_index); + + if (whitespace == TRIM_WHITESPACE) + term = TrimString(term, WhitespaceForType<Str>(), TRIM_ALL); + + if (result_type == SPLIT_WANT_ALL || !term.empty()) + result->push_back(PieceToOutputType<Str, OutputStringType>(term)); } } @@ -198,111 +205,60 @@ 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, TRIM_WHITESPACE, SPLIT_WANT_ALL, + 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, TRIM_WHITESPACE, SPLIT_WANT_ALL, + result); } -void SplitStringDontTrim(StringPiece16 str, - char16 c, - std::vector<string16>* result) { - DCHECK(CBU16_IS_SINGLE(c)); - *result = SplitStringT<string16, string16, char16>( - str, c, KEEP_WHITESPACE, SPLIT_WANT_ALL); -} - -void SplitStringDontTrim(StringPiece 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, KEEP_WHITESPACE, SPLIT_WANT_ALL); -} - -void SplitStringAlongWhitespace(const string16& str, - std::vector<string16>* result) { - *result = SplitStringT<string16, string16, StringPiece16>( - str, StringPiece16(kWhitespaceASCIIAs16), - TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); +std::vector<StringPiece16> SplitStringPieceUsingSubstr( + StringPiece16 input, + StringPiece16 delimiter, + WhitespaceHandling whitespace, + SplitResult result_type) { + std::vector<StringPiece16> result; + SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); + return result; } -void SplitStringAlongWhitespace(const std::string& str, - std::vector<std::string>* result) { - *result = SplitStringT<std::string, std::string, StringPiece>( - str, StringPiece(kWhitespaceASCII), - TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); +std::vector<StringPiece> SplitStringPieceUsingSubstr( + StringPiece input, + StringPiece delimiter, + WhitespaceHandling whitespace, + SplitResult result_type) { + std::vector<StringPiece> result; + SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); + return result; } } // namespace base |