Chromium Code Reviews| 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/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
| 10 #include "base/third_party/icu/icu_utf.h" | 10 #include "base/third_party/icu/icu_utf.h" |
| 11 | 11 |
| 12 namespace base { | 12 namespace base { |
| 13 | 13 |
| 14 template<typename STR> | 14 namespace { |
| 15 static void SplitStringT(const STR& str, | 15 |
| 16 const typename STR::value_type s, | 16 template <typename STR> |
| 17 bool trim_whitespace, | 17 void SplitStringT(const STR& str, |
| 18 std::vector<STR>* r) { | 18 const typename STR::value_type s, |
| 19 bool trim_whitespace, | |
| 20 std::vector<STR>* r) { | |
| 19 r->clear(); | 21 r->clear(); |
| 20 size_t last = 0; | 22 size_t last = 0; |
| 21 size_t c = str.size(); | 23 size_t c = str.size(); |
| 22 for (size_t i = 0; i <= c; ++i) { | 24 for (size_t i = 0; i <= c; ++i) { |
| 23 if (i == c || str[i] == s) { | 25 if (i == c || str[i] == s) { |
| 24 STR tmp(str, last, i - last); | 26 STR tmp(str, last, i - last); |
| 25 if (trim_whitespace) | 27 if (trim_whitespace) |
| 26 TrimWhitespace(tmp, TRIM_ALL, &tmp); | 28 TrimWhitespace(tmp, TRIM_ALL, &tmp); |
| 27 // Avoid converting an empty or all-whitespace source string into a vector | 29 // Avoid converting an empty or all-whitespace source string into a vector |
| 28 // of one empty string. | 30 // of one empty string. |
| 29 if (i != c || !r->empty() || !tmp.empty()) | 31 if (i != c || !r->empty() || !tmp.empty()) |
| 30 r->push_back(tmp); | 32 r->push_back(tmp); |
| 31 last = i + 1; | 33 last = i + 1; |
| 32 } | 34 } |
| 33 } | 35 } |
| 34 } | 36 } |
| 35 | 37 |
| 38 bool SplitStringIntoKeyValue(const std::string& line, | |
| 39 char key_value_delimiter, | |
| 40 std::string* key, | |
| 41 std::string* value) { | |
| 42 key->clear(); | |
| 43 value->clear(); | |
| 44 | |
| 45 // Find the delimiter. | |
| 46 size_t end_key_pos = line.find_first_of(key_value_delimiter); | |
| 47 if (end_key_pos == std::string::npos) { | |
| 48 DVLOG(1) << "cannot find delimiter in: " << line; | |
| 49 return false; // no delimiter | |
| 50 } | |
| 51 key->assign(line, 0, end_key_pos); | |
| 52 | |
| 53 // Find the value string. | |
| 54 std::string remains(line, end_key_pos, line.size() - end_key_pos); | |
| 55 size_t begin_value_pos = remains.find_first_not_of(key_value_delimiter); | |
| 56 if (begin_value_pos == std::string::npos) { | |
| 57 DVLOG(1) << "cannot parse value from line: " << line; | |
| 58 return false; // no value | |
| 59 } | |
| 60 value->assign(remains, begin_value_pos, remains.size() - begin_value_pos); | |
| 61 return true; | |
| 62 } | |
| 63 | |
| 64 } // namespace | |
| 65 | |
| 36 void SplitString(const string16& str, | 66 void SplitString(const string16& str, |
| 37 char16 c, | 67 char16 c, |
| 38 std::vector<string16>* r) { | 68 std::vector<string16>* r) { |
| 39 DCHECK(CBU16_IS_SINGLE(c)); | 69 DCHECK(CBU16_IS_SINGLE(c)); |
| 40 SplitStringT(str, c, true, r); | 70 SplitStringT(str, c, true, r); |
| 41 } | 71 } |
| 42 | 72 |
| 43 void SplitString(const std::string& str, | 73 void SplitString(const std::string& str, |
| 44 char c, | 74 char c, |
| 45 std::vector<std::string>* r) { | 75 std::vector<std::string>* r) { |
| 46 #if CHAR_MIN < 0 | 76 #if CHAR_MIN < 0 |
| 47 DCHECK(c >= 0); | 77 DCHECK(c >= 0); |
| 48 #endif | 78 #endif |
| 49 DCHECK(c < 0x7F); | 79 DCHECK(c < 0x7F); |
| 50 SplitStringT(str, c, true, r); | 80 SplitStringT(str, c, true, r); |
| 51 } | 81 } |
| 52 | 82 |
| 53 bool SplitStringIntoKeyValues( | |
| 54 const std::string& line, | |
| 55 char key_value_delimiter, | |
| 56 std::string* key, std::vector<std::string>* values) { | |
| 57 key->clear(); | |
| 58 values->clear(); | |
| 59 | |
| 60 // Find the key string. | |
| 61 size_t end_key_pos = line.find_first_of(key_value_delimiter); | |
| 62 if (end_key_pos == std::string::npos) { | |
| 63 DVLOG(1) << "cannot parse key from line: " << line; | |
| 64 return false; // no key | |
| 65 } | |
| 66 key->assign(line, 0, end_key_pos); | |
| 67 | |
| 68 // Find the values string. | |
| 69 std::string remains(line, end_key_pos, line.size() - end_key_pos); | |
| 70 size_t begin_values_pos = remains.find_first_not_of(key_value_delimiter); | |
| 71 if (begin_values_pos == std::string::npos) { | |
| 72 DVLOG(1) << "cannot parse value from line: " << line; | |
| 73 return false; // no value | |
| 74 } | |
| 75 std::string values_string(remains, begin_values_pos, | |
| 76 remains.size() - begin_values_pos); | |
| 77 | |
| 78 // Construct the values vector. | |
| 79 values->push_back(values_string); | |
| 80 return true; | |
| 81 } | |
| 82 | |
| 83 bool SplitStringIntoKeyValuePairs(const std::string& line, | 83 bool SplitStringIntoKeyValuePairs(const std::string& line, |
| 84 char key_value_delimiter, | 84 char key_value_delimiter, |
| 85 char key_value_pair_delimiter, | 85 char key_value_pair_delimiter, |
| 86 StringPairs* key_value_pairs) { | 86 StringPairs* key_value_pairs) { |
| 87 key_value_pairs->clear(); | 87 key_value_pairs->clear(); |
| 88 | 88 |
| 89 std::vector<std::string> pairs; | 89 std::vector<std::string> pairs; |
| 90 SplitString(line, key_value_pair_delimiter, &pairs); | 90 SplitString(line, key_value_pair_delimiter, &pairs); |
| 91 | 91 |
| 92 bool success = true; | 92 bool success = true; |
| 93 for (size_t i = 0; i < pairs.size(); ++i) { | 93 for (size_t i = 0; i < pairs.size(); ++i) { |
| 94 // Empty pair. SplitStringIntoKeyValues is more strict about an empty pair | 94 // Don't add empty pairs into the result. |
|
Mark Mentovai
2014/03/06 17:55:51
This is empty pairs after whitespace trimming. Des
| |
| 95 // line, so continue with the next pair. | |
| 96 if (pairs[i].empty()) | 95 if (pairs[i].empty()) |
| 97 continue; | 96 continue; |
| 98 | 97 |
| 99 std::string key; | 98 std::string key; |
| 100 std::vector<std::string> value; | 99 std::string value; |
| 101 if (!SplitStringIntoKeyValues(pairs[i], | 100 if (!SplitStringIntoKeyValue(pairs[i], key_value_delimiter, &key, &value)) { |
|
Mark Mentovai
2014/03/06 17:55:51
This whole thing would be better with StringPieces
| |
| 102 key_value_delimiter, | 101 // Don't return here, to allow for pairs without associated |
| 103 &key, &value)) { | 102 // value or key; just record that our split failed. |
|
Mark Mentovai
2014/03/06 17:55:51
our split -> the split
See the test CL. I’m not s
pneubeck (no reviews)
2014/03/07 17:12:11
Done.
| |
| 104 // Don't return here, to allow for keys without associated | |
| 105 // values; just record that our split failed. | |
| 106 success = false; | 103 success = false; |
| 107 } | 104 } |
| 108 DCHECK_LE(value.size(), 1U); | 105 DCHECK_LE(value.size(), 1U); |
|
Mark Mentovai
2014/03/06 17:55:51
?
pneubeck (no reviews)
2014/03/07 17:12:11
Ouch. yes that has to be removed.
Done.
| |
| 109 key_value_pairs->push_back( | 106 key_value_pairs->push_back(make_pair(key, value)); |
| 110 make_pair(key, value.empty() ? std::string() : value[0])); | |
| 111 } | 107 } |
| 112 return success; | 108 return success; |
| 113 } | 109 } |
| 114 | 110 |
| 115 template <typename STR> | 111 template <typename STR> |
| 116 static void SplitStringUsingSubstrT(const STR& str, | 112 static void SplitStringUsingSubstrT(const STR& str, |
| 117 const STR& s, | 113 const STR& s, |
| 118 std::vector<STR>* r) { | 114 std::vector<STR>* r) { |
| 119 r->clear(); | 115 r->clear(); |
| 120 typename STR::size_type begin_index = 0; | 116 typename STR::size_type begin_index = 0; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 std::vector<string16>* result) { | 206 std::vector<string16>* result) { |
| 211 SplitStringAlongWhitespaceT(str, result); | 207 SplitStringAlongWhitespaceT(str, result); |
| 212 } | 208 } |
| 213 | 209 |
| 214 void SplitStringAlongWhitespace(const std::string& str, | 210 void SplitStringAlongWhitespace(const std::string& str, |
| 215 std::vector<std::string>* result) { | 211 std::vector<std::string>* result) { |
| 216 SplitStringAlongWhitespaceT(str, result); | 212 SplitStringAlongWhitespaceT(str, result); |
| 217 } | 213 } |
| 218 | 214 |
| 219 } // namespace base | 215 } // namespace base |
| OLD | NEW |