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 |