| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/strings/string_split.h" | 5 #include "base/strings/string_split.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "base/third_party/icu/icu_utf.h" | 9 #include "base/third_party/icu/icu_utf.h" |
| 10 | 10 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 | 92 |
| 93 if (whitespace == TRIM_WHITESPACE) | 93 if (whitespace == TRIM_WHITESPACE) |
| 94 piece = TrimString(piece, WhitespaceForType<Str>(), TRIM_ALL); | 94 piece = TrimString(piece, WhitespaceForType<Str>(), TRIM_ALL); |
| 95 | 95 |
| 96 if (result_type == SPLIT_WANT_ALL || !piece.empty()) | 96 if (result_type == SPLIT_WANT_ALL || !piece.empty()) |
| 97 result.push_back(PieceToOutputType<Str, OutputStringType>(piece)); | 97 result.push_back(PieceToOutputType<Str, OutputStringType>(piece)); |
| 98 } | 98 } |
| 99 return result; | 99 return result; |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool SplitStringIntoKeyValue(const std::string& line, | 102 bool AppendStringKeyValue(StringPiece input, |
| 103 char key_value_delimiter, | 103 char delimiter, |
| 104 std::string* key, | 104 StringPairs* result) { |
| 105 std::string* value) { | 105 // Always append a new item regardless of success (it might be empty). The |
| 106 key->clear(); | 106 // below code will copy the strings directly into the result pair. |
| 107 value->clear(); | 107 result->resize(result->size() + 1); |
| 108 auto& result_pair = result->back(); |
| 108 | 109 |
| 109 // Find the delimiter. | 110 // Find the delimiter. |
| 110 size_t end_key_pos = line.find_first_of(key_value_delimiter); | 111 size_t end_key_pos = input.find_first_of(delimiter); |
| 111 if (end_key_pos == std::string::npos) { | 112 if (end_key_pos == std::string::npos) { |
| 112 DVLOG(1) << "cannot find delimiter in: " << line; | 113 DVLOG(1) << "cannot find delimiter in: " << input; |
| 113 return false; // no delimiter | 114 return false; // No delimiter. |
| 114 } | 115 } |
| 115 key->assign(line, 0, end_key_pos); | 116 input.substr(0, end_key_pos).CopyToString(&result_pair.first); |
| 116 | 117 |
| 117 // Find the value string. | 118 // Find the value string. |
| 118 std::string remains(line, end_key_pos, line.size() - end_key_pos); | 119 StringPiece remains = input.substr(end_key_pos, input.size() - end_key_pos); |
| 119 size_t begin_value_pos = remains.find_first_not_of(key_value_delimiter); | 120 size_t begin_value_pos = remains.find_first_not_of(delimiter); |
| 120 if (begin_value_pos == std::string::npos) { | 121 if (begin_value_pos == StringPiece::npos) { |
| 121 DVLOG(1) << "cannot parse value from line: " << line; | 122 DVLOG(1) << "cannot parse value from input: " << input; |
| 122 return false; // no value | 123 return false; // No value. |
| 123 } | 124 } |
| 124 value->assign(remains, begin_value_pos, remains.size() - begin_value_pos); | 125 remains.substr(begin_value_pos, remains.size() - begin_value_pos) |
| 126 .CopyToString(&result_pair.second); |
| 127 |
| 125 return true; | 128 return true; |
| 126 } | 129 } |
| 127 | 130 |
| 128 template <typename STR> | 131 template <typename Str> |
| 129 void SplitStringUsingSubstrT(const STR& str, | 132 void SplitStringUsingSubstrT(BasicStringPiece<Str> input, |
| 130 const STR& s, | 133 BasicStringPiece<Str> delimiter, |
| 131 std::vector<STR>* r) { | 134 std::vector<Str>* result) { |
| 132 r->clear(); | 135 using Piece = BasicStringPiece<Str>; |
| 133 typename STR::size_type begin_index = 0; | 136 using size_type = typename Piece::size_type; |
| 137 |
| 138 result->clear(); |
| 139 size_type begin_index = 0; |
| 134 while (true) { | 140 while (true) { |
| 135 const typename STR::size_type end_index = str.find(s, begin_index); | 141 size_type end_index = input.find(delimiter, begin_index); |
| 136 if (end_index == STR::npos) { | 142 if (end_index == Piece::npos) { |
| 137 const STR term = str.substr(begin_index); | 143 // No delimiter, use the rest of the string. |
| 138 STR tmp; | 144 Piece term = TrimString(input.substr(begin_index), |
| 139 TrimWhitespace(term, TRIM_ALL, &tmp); | 145 WhitespaceForType<Str>(), TRIM_ALL); |
| 140 r->push_back(tmp); | 146 result->push_back(term.as_string()); |
| 141 return; | 147 return; |
| 142 } | 148 } |
| 143 const STR term = str.substr(begin_index, end_index - begin_index); | 149 Piece term = TrimString(input.substr(begin_index, end_index - begin_index), |
| 144 STR tmp; | 150 WhitespaceForType<Str>(), TRIM_ALL); |
| 145 TrimWhitespace(term, TRIM_ALL, &tmp); | 151 result->push_back(term.as_string()); |
| 146 r->push_back(tmp); | 152 begin_index = end_index + delimiter.size(); |
| 147 begin_index = end_index + s.size(); | |
| 148 } | 153 } |
| 149 } | 154 } |
| 150 | 155 |
| 151 } // namespace | 156 } // namespace |
| 152 | 157 |
| 153 std::vector<std::string> SplitString(StringPiece input, | 158 std::vector<std::string> SplitString(StringPiece input, |
| 154 StringPiece separators, | 159 StringPiece separators, |
| 155 WhitespaceHandling whitespace, | 160 WhitespaceHandling whitespace, |
| 156 SplitResult result_type) { | 161 SplitResult result_type) { |
| 157 if (separators.size() == 1) { | 162 if (separators.size() == 1) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 WhitespaceHandling whitespace, | 196 WhitespaceHandling whitespace, |
| 192 SplitResult result_type) { | 197 SplitResult result_type) { |
| 193 if (separators.size() == 1) { | 198 if (separators.size() == 1) { |
| 194 return SplitStringT<string16, StringPiece16, char16>( | 199 return SplitStringT<string16, StringPiece16, char16>( |
| 195 input, separators[0], whitespace, result_type); | 200 input, separators[0], whitespace, result_type); |
| 196 } | 201 } |
| 197 return SplitStringT<string16, StringPiece16, StringPiece16>( | 202 return SplitStringT<string16, StringPiece16, StringPiece16>( |
| 198 input, separators, whitespace, result_type); | 203 input, separators, whitespace, result_type); |
| 199 } | 204 } |
| 200 | 205 |
| 201 void SplitString(const string16& str, | 206 bool SplitStringIntoKeyValuePairs(StringPiece input, |
| 202 char16 c, | |
| 203 std::vector<string16>* result) { | |
| 204 DCHECK(CBU16_IS_SINGLE(c)); | |
| 205 *result = SplitStringT<string16, string16, char16>( | |
| 206 str, c, TRIM_WHITESPACE, SPLIT_WANT_ALL); | |
| 207 | |
| 208 // Backward-compat hack: The old SplitString implementation would keep | |
| 209 // empty substrings, for example: | |
| 210 // "a,,b" -> ["a", "", "b"] | |
| 211 // "a, ,b" -> ["a", "", "b"] | |
| 212 // which the current code also does. But the old one would discard them when | |
| 213 // the only result was that empty string: | |
| 214 // " " -> [] | |
| 215 // In the latter case, our new code will give [""] | |
| 216 if (result->size() == 1 && (*result)[0].empty()) | |
| 217 result->clear(); | |
| 218 } | |
| 219 | |
| 220 void SplitString(const std::string& str, | |
| 221 char c, | |
| 222 std::vector<std::string>* result) { | |
| 223 #if CHAR_MIN < 0 | |
| 224 DCHECK_GE(c, 0); | |
| 225 #endif | |
| 226 DCHECK_LT(c, 0x7F); | |
| 227 *result = SplitStringT<std::string, std::string, char>( | |
| 228 str, c, TRIM_WHITESPACE, SPLIT_WANT_ALL); | |
| 229 | |
| 230 // Backward-compat hack, see above. | |
| 231 if (result->size() == 1 && (*result)[0].empty()) | |
| 232 result->clear(); | |
| 233 } | |
| 234 | |
| 235 bool SplitStringIntoKeyValuePairs(const std::string& line, | |
| 236 char key_value_delimiter, | 207 char key_value_delimiter, |
| 237 char key_value_pair_delimiter, | 208 char key_value_pair_delimiter, |
| 238 StringPairs* key_value_pairs) { | 209 StringPairs* key_value_pairs) { |
| 239 key_value_pairs->clear(); | 210 key_value_pairs->clear(); |
| 240 | 211 |
| 241 std::vector<std::string> pairs; | 212 std::vector<StringPiece> pairs = SplitStringPiece( |
| 242 SplitString(line, key_value_pair_delimiter, &pairs); | 213 input, std::string(1, key_value_pair_delimiter), |
| 214 TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); |
| 215 key_value_pairs->reserve(pairs.size()); |
| 243 | 216 |
| 244 bool success = true; | 217 bool success = true; |
| 245 for (size_t i = 0; i < pairs.size(); ++i) { | 218 for (const StringPiece& pair : pairs) { |
| 246 // Don't add empty pairs into the result. | 219 if (!AppendStringKeyValue(pair, key_value_delimiter, key_value_pairs)) { |
| 247 if (pairs[i].empty()) | |
| 248 continue; | |
| 249 | |
| 250 std::string key; | |
| 251 std::string value; | |
| 252 if (!SplitStringIntoKeyValue(pairs[i], key_value_delimiter, &key, &value)) { | |
| 253 // Don't return here, to allow for pairs without associated | 220 // Don't return here, to allow for pairs without associated |
| 254 // value or key; just record that the split failed. | 221 // value or key; just record that the split failed. |
| 255 success = false; | 222 success = false; |
| 256 } | 223 } |
| 257 key_value_pairs->push_back(make_pair(key, value)); | |
| 258 } | 224 } |
| 259 return success; | 225 return success; |
| 260 } | 226 } |
| 261 | 227 |
| 262 void SplitStringUsingSubstr(const string16& str, | 228 void SplitStringUsingSubstr(StringPiece16 input, |
| 263 const string16& s, | 229 StringPiece16 delimiter, |
| 264 std::vector<string16>* r) { | 230 std::vector<string16>* result) { |
| 265 SplitStringUsingSubstrT(str, s, r); | 231 SplitStringUsingSubstrT(input, delimiter, result); |
| 266 } | 232 } |
| 267 | 233 |
| 268 void SplitStringUsingSubstr(const std::string& str, | 234 void SplitStringUsingSubstr(StringPiece input, |
| 269 const std::string& s, | 235 StringPiece delimiter, |
| 270 std::vector<std::string>* r) { | 236 std::vector<std::string>* result) { |
| 271 SplitStringUsingSubstrT(str, s, r); | 237 SplitStringUsingSubstrT(input, delimiter, result); |
| 272 } | 238 } |
| 273 | 239 |
| 274 } // namespace base | 240 } // namespace base |
| OLD | NEW |