Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: base/strings/string_split.cc

Issue 184233010: Cleanup SplitStringIntoKeyaluePairs implementation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/strings/string_split.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
36 void SplitString(const string16& str, 38 bool SplitStringIntoKeyValue(const std::string& line,
37 char16 c, 39 char key_value_delimiter,
38 std::vector<string16>* r) { 40 std::string* key,
39 DCHECK(CBU16_IS_SINGLE(c)); 41 std::string* value) {
40 SplitStringT(str, c, true, r); 42 key->clear();
41 } 43 value->clear();
42 44
43 void SplitString(const std::string& str, 45 // Find the delimiter.
44 char c,
45 std::vector<std::string>* r) {
46 #if CHAR_MIN < 0
47 DCHECK(c >= 0);
48 #endif
49 DCHECK(c < 0x7F);
50 SplitStringT(str, c, true, r);
51 }
52
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); 46 size_t end_key_pos = line.find_first_of(key_value_delimiter);
62 if (end_key_pos == std::string::npos) { 47 if (end_key_pos == std::string::npos) {
63 DVLOG(1) << "cannot parse key from line: " << line; 48 DVLOG(1) << "cannot find delimiter in: " << line;
64 return false; // no key 49 return false; // no delimiter
65 } 50 }
66 key->assign(line, 0, end_key_pos); 51 key->assign(line, 0, end_key_pos);
67 52
68 // Find the values string. 53 // Find the value string.
69 std::string remains(line, end_key_pos, line.size() - end_key_pos); 54 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); 55 size_t begin_value_pos = remains.find_first_not_of(key_value_delimiter);
71 if (begin_values_pos == std::string::npos) { 56 if (begin_value_pos == std::string::npos) {
72 DVLOG(1) << "cannot parse value from line: " << line; 57 DVLOG(1) << "cannot parse value from line: " << line;
73 return false; // no value 58 return false; // no value
74 } 59 }
75 std::string values_string(remains, begin_values_pos, 60 value->assign(remains, begin_value_pos, remains.size() - begin_value_pos);
76 remains.size() - begin_values_pos);
77
78 // Construct the values vector.
79 values->push_back(values_string);
80 return true; 61 return true;
81 } 62 }
82 63
83 bool SplitStringIntoKeyValuePairs(const std::string& line,
84 char key_value_delimiter,
85 char key_value_pair_delimiter,
86 StringPairs* key_value_pairs) {
87 key_value_pairs->clear();
88
89 std::vector<std::string> pairs;
90 SplitString(line, key_value_pair_delimiter, &pairs);
91
92 bool success = true;
93 for (size_t i = 0; i < pairs.size(); ++i) {
94 // Empty pair. SplitStringIntoKeyValues is more strict about an empty pair
95 // line, so continue with the next pair.
96 if (pairs[i].empty())
97 continue;
98
99 std::string key;
100 std::vector<std::string> value;
101 if (!SplitStringIntoKeyValues(pairs[i],
102 key_value_delimiter,
103 &key, &value)) {
104 // Don't return here, to allow for keys without associated
105 // values; just record that our split failed.
106 success = false;
107 }
108 DCHECK_LE(value.size(), 1U);
109 key_value_pairs->push_back(
110 make_pair(key, value.empty() ? std::string() : value[0]));
111 }
112 return success;
113 }
114
115 template <typename STR> 64 template <typename STR>
116 static void SplitStringUsingSubstrT(const STR& str, 65 void SplitStringUsingSubstrT(const STR& str,
117 const STR& s, 66 const STR& s,
118 std::vector<STR>* r) { 67 std::vector<STR>* r) {
119 r->clear(); 68 r->clear();
120 typename STR::size_type begin_index = 0; 69 typename STR::size_type begin_index = 0;
121 while (true) { 70 while (true) {
122 const typename STR::size_type end_index = str.find(s, begin_index); 71 const typename STR::size_type end_index = str.find(s, begin_index);
123 if (end_index == STR::npos) { 72 if (end_index == STR::npos) {
124 const STR term = str.substr(begin_index); 73 const STR term = str.substr(begin_index);
125 STR tmp; 74 STR tmp;
126 TrimWhitespace(term, TRIM_ALL, &tmp); 75 TrimWhitespace(term, TRIM_ALL, &tmp);
127 r->push_back(tmp); 76 r->push_back(tmp);
128 return; 77 return;
129 } 78 }
130 const STR term = str.substr(begin_index, end_index - begin_index); 79 const STR term = str.substr(begin_index, end_index - begin_index);
131 STR tmp; 80 STR tmp;
132 TrimWhitespace(term, TRIM_ALL, &tmp); 81 TrimWhitespace(term, TRIM_ALL, &tmp);
133 r->push_back(tmp); 82 r->push_back(tmp);
134 begin_index = end_index + s.size(); 83 begin_index = end_index + s.size();
135 } 84 }
136 } 85 }
137 86
138 void SplitStringUsingSubstr(const string16& str,
139 const string16& s,
140 std::vector<string16>* r) {
141 SplitStringUsingSubstrT(str, s, r);
142 }
143
144 void SplitStringUsingSubstr(const std::string& str,
145 const std::string& s,
146 std::vector<std::string>* r) {
147 SplitStringUsingSubstrT(str, s, r);
148 }
149
150 void SplitStringDontTrim(const string16& str,
151 char16 c,
152 std::vector<string16>* r) {
153 DCHECK(CBU16_IS_SINGLE(c));
154 SplitStringT(str, c, false, r);
155 }
156
157 void SplitStringDontTrim(const std::string& str,
158 char c,
159 std::vector<std::string>* r) {
160 DCHECK(IsStringUTF8(str));
161 #if CHAR_MIN < 0
162 DCHECK(c >= 0);
163 #endif
164 DCHECK(c < 0x7F);
165 SplitStringT(str, c, false, r);
166 }
167
168 template<typename STR> 87 template<typename STR>
169 void SplitStringAlongWhitespaceT(const STR& str, std::vector<STR>* result) { 88 void SplitStringAlongWhitespaceT(const STR& str, std::vector<STR>* result) {
170 result->clear(); 89 result->clear();
171 const size_t length = str.length(); 90 const size_t length = str.length();
172 if (!length) 91 if (!length)
173 return; 92 return;
174 93
175 bool last_was_ws = false; 94 bool last_was_ws = false;
176 size_t last_non_ws_start = 0; 95 size_t last_non_ws_start = 0;
177 for (size_t i = 0; i < length; ++i) { 96 for (size_t i = 0; i < length; ++i) {
(...skipping 21 matching lines...) Expand all
199 } 118 }
200 break; 119 break;
201 } 120 }
202 } 121 }
203 if (!last_was_ws) { 122 if (!last_was_ws) {
204 result->push_back( 123 result->push_back(
205 str.substr(last_non_ws_start, length - last_non_ws_start)); 124 str.substr(last_non_ws_start, length - last_non_ws_start));
206 } 125 }
207 } 126 }
208 127
128 } // namespace
129
130 void SplitString(const string16& str,
131 char16 c,
132 std::vector<string16>* r) {
133 DCHECK(CBU16_IS_SINGLE(c));
134 SplitStringT(str, c, true, r);
135 }
136
137 void SplitString(const std::string& str,
138 char c,
139 std::vector<std::string>* r) {
140 #if CHAR_MIN < 0
141 DCHECK(c >= 0);
142 #endif
143 DCHECK(c < 0x7F);
144 SplitStringT(str, c, true, r);
145 }
146
147 bool SplitStringIntoKeyValuePairs(const std::string& line,
148 char key_value_delimiter,
149 char key_value_pair_delimiter,
150 StringPairs* key_value_pairs) {
151 key_value_pairs->clear();
152
153 std::vector<std::string> pairs;
154 SplitString(line, key_value_pair_delimiter, &pairs);
155
156 bool success = true;
157 for (size_t i = 0; i < pairs.size(); ++i) {
158 // Don't add empty pairs into the result.
159 if (pairs[i].empty())
160 continue;
161
162 std::string key;
163 std::string value;
164 if (!SplitStringIntoKeyValue(pairs[i], key_value_delimiter, &key, &value)) {
165 // Don't return here, to allow for pairs without associated
166 // value or key; just record that the split failed.
167 success = false;
168 }
169 key_value_pairs->push_back(make_pair(key, value));
170 }
171 return success;
172 }
173
174 void SplitStringUsingSubstr(const string16& str,
175 const string16& s,
176 std::vector<string16>* r) {
177 SplitStringUsingSubstrT(str, s, r);
178 }
179
180 void SplitStringUsingSubstr(const std::string& str,
181 const std::string& s,
182 std::vector<std::string>* r) {
183 SplitStringUsingSubstrT(str, s, r);
184 }
185
186 void SplitStringDontTrim(const string16& str,
187 char16 c,
188 std::vector<string16>* r) {
189 DCHECK(CBU16_IS_SINGLE(c));
190 SplitStringT(str, c, false, r);
191 }
192
193 void SplitStringDontTrim(const std::string& str,
194 char c,
195 std::vector<std::string>* r) {
196 DCHECK(IsStringUTF8(str));
197 #if CHAR_MIN < 0
198 DCHECK(c >= 0);
199 #endif
200 DCHECK(c < 0x7F);
201 SplitStringT(str, c, false, r);
202 }
203
209 void SplitStringAlongWhitespace(const string16& str, 204 void SplitStringAlongWhitespace(const string16& str,
210 std::vector<string16>* result) { 205 std::vector<string16>* result) {
211 SplitStringAlongWhitespaceT(str, result); 206 SplitStringAlongWhitespaceT(str, result);
212 } 207 }
213 208
214 void SplitStringAlongWhitespace(const std::string& str, 209 void SplitStringAlongWhitespace(const std::string& str,
215 std::vector<std::string>* result) { 210 std::vector<std::string>* result) {
216 SplitStringAlongWhitespaceT(str, result); 211 SplitStringAlongWhitespaceT(str, result);
217 } 212 }
218 213
219 } // namespace base 214 } // namespace base
OLDNEW
« no previous file with comments | « base/strings/string_split.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698