summaryrefslogtreecommitdiff
path: root/base/strings/string_split.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/strings/string_split.cc')
-rw-r--r--base/strings/string_split.cc196
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