OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_util.h" | 5 #include "base/strings/string_util.h" |
6 | 6 |
7 #include <ctype.h> | 7 #include <ctype.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <math.h> | 9 #include <math.h> |
10 #include <stdarg.h> | 10 #include <stdarg.h> |
11 #include <stdio.h> | 11 #include <stdio.h> |
12 #include <stdlib.h> | 12 #include <stdlib.h> |
13 #include <string.h> | 13 #include <string.h> |
14 #include <time.h> | 14 #include <time.h> |
15 #include <wchar.h> | 15 #include <wchar.h> |
16 #include <wctype.h> | 16 #include <wctype.h> |
17 | 17 |
18 #include <algorithm> | 18 #include <algorithm> |
19 #include <vector> | 19 #include <vector> |
20 | 20 |
21 #include "base/basictypes.h" | 21 #include "base/basictypes.h" |
22 #include "base/logging.h" | 22 #include "base/logging.h" |
23 #include "base/memory/singleton.h" | 23 #include "base/memory/singleton.h" |
| 24 #include "base/strings/string_split.h" |
24 #include "base/strings/utf_string_conversion_utils.h" | 25 #include "base/strings/utf_string_conversion_utils.h" |
25 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
26 #include "base/third_party/icu/icu_utf.h" | 27 #include "base/third_party/icu/icu_utf.h" |
27 #include "build/build_config.h" | 28 #include "build/build_config.h" |
28 | 29 |
29 // Remove when this entire file is in the base namespace. | 30 // Remove when this entire file is in the base namespace. |
30 using base::char16; | 31 using base::char16; |
31 using base::string16; | 32 using base::string16; |
32 | 33 |
33 namespace { | 34 namespace { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 string16* output) { | 187 string16* output) { |
187 return ReplaceChars(input, remove_chars.as_string(), string16(), output); | 188 return ReplaceChars(input, remove_chars.as_string(), string16(), output); |
188 } | 189 } |
189 | 190 |
190 bool RemoveChars(const std::string& input, | 191 bool RemoveChars(const std::string& input, |
191 const base::StringPiece& remove_chars, | 192 const base::StringPiece& remove_chars, |
192 std::string* output) { | 193 std::string* output) { |
193 return ReplaceChars(input, remove_chars.as_string(), std::string(), output); | 194 return ReplaceChars(input, remove_chars.as_string(), std::string(), output); |
194 } | 195 } |
195 | 196 |
196 template<typename STR> | 197 template<typename Str> |
197 TrimPositions TrimStringT(const STR& input, | 198 TrimPositions TrimStringT(const Str& input, |
198 const STR& trim_chars, | 199 BasicStringPiece<Str> trim_chars, |
199 TrimPositions positions, | 200 TrimPositions positions, |
200 STR* output) { | 201 Str* output) { |
201 // Find the edges of leading/trailing whitespace as desired. | 202 // Find the edges of leading/trailing whitespace as desired. Need to use |
| 203 // a StringPiece version of input to be able to call find* on it with the |
| 204 // StringPiece version of trim_chars (normally the trim_chars will be a |
| 205 // constant so avoid making a copy). |
| 206 BasicStringPiece<Str> input_piece(input); |
202 const size_t last_char = input.length() - 1; | 207 const size_t last_char = input.length() - 1; |
203 const size_t first_good_char = (positions & TRIM_LEADING) ? | 208 const size_t first_good_char = (positions & TRIM_LEADING) ? |
204 input.find_first_not_of(trim_chars) : 0; | 209 input_piece.find_first_not_of(trim_chars) : 0; |
205 const size_t last_good_char = (positions & TRIM_TRAILING) ? | 210 const size_t last_good_char = (positions & TRIM_TRAILING) ? |
206 input.find_last_not_of(trim_chars) : last_char; | 211 input_piece.find_last_not_of(trim_chars) : last_char; |
207 | 212 |
208 // When the string was all whitespace, report that we stripped off whitespace | 213 // When the string was all trimmed, report that we stripped off characters |
209 // from whichever position the caller was interested in. For empty input, we | 214 // from whichever position the caller was interested in. For empty input, we |
210 // stripped no whitespace, but we still need to clear |output|. | 215 // stripped no characters, but we still need to clear |output|. |
211 if (input.empty() || | 216 if (input.empty() || |
212 (first_good_char == STR::npos) || (last_good_char == STR::npos)) { | 217 (first_good_char == Str::npos) || (last_good_char == Str::npos)) { |
213 bool input_was_empty = input.empty(); // in case output == &input | 218 bool input_was_empty = input.empty(); // in case output == &input |
214 output->clear(); | 219 output->clear(); |
215 return input_was_empty ? TRIM_NONE : positions; | 220 return input_was_empty ? TRIM_NONE : positions; |
216 } | 221 } |
217 | 222 |
218 // Trim the whitespace. | 223 // Trim. |
219 *output = | 224 *output = |
220 input.substr(first_good_char, last_good_char - first_good_char + 1); | 225 input.substr(first_good_char, last_good_char - first_good_char + 1); |
221 | 226 |
222 // Return where we trimmed from. | 227 // Return where we trimmed from. |
223 return static_cast<TrimPositions>( | 228 return static_cast<TrimPositions>( |
224 ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | | 229 ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | |
225 ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); | 230 ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); |
226 } | 231 } |
227 | 232 |
228 bool TrimString(const string16& input, | 233 bool TrimString(const string16& input, |
229 const base::StringPiece16& trim_chars, | 234 base::StringPiece16 trim_chars, |
230 string16* output) { | 235 string16* output) { |
231 return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != | 236 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; |
232 TRIM_NONE; | |
233 } | 237 } |
234 | 238 |
235 bool TrimString(const std::string& input, | 239 bool TrimString(const std::string& input, |
236 const base::StringPiece& trim_chars, | 240 base::StringPiece trim_chars, |
237 std::string* output) { | 241 std::string* output) { |
238 return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != | 242 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; |
239 TRIM_NONE; | 243 } |
| 244 |
| 245 template<typename Str> |
| 246 BasicStringPiece<Str> TrimStringPieceT(BasicStringPiece<Str> input, |
| 247 BasicStringPiece<Str> trim_chars, |
| 248 TrimPositions positions) { |
| 249 size_t begin = (positions & TRIM_LEADING) ? |
| 250 input.find_first_not_of(trim_chars) : 0; |
| 251 size_t end = (positions & TRIM_TRAILING) ? |
| 252 input.find_last_not_of(trim_chars) + 1 : input.size(); |
| 253 return input.substr(begin, end - begin); |
| 254 } |
| 255 |
| 256 StringPiece16 TrimString(StringPiece16 input, |
| 257 const base::StringPiece16& trim_chars, |
| 258 TrimPositions positions) { |
| 259 return TrimStringPieceT(input, trim_chars, positions); |
| 260 } |
| 261 |
| 262 StringPiece TrimString(StringPiece input, |
| 263 const base::StringPiece& trim_chars, |
| 264 TrimPositions positions) { |
| 265 return TrimStringPieceT(input, trim_chars, positions); |
240 } | 266 } |
241 | 267 |
242 void TruncateUTF8ToByteSize(const std::string& input, | 268 void TruncateUTF8ToByteSize(const std::string& input, |
243 const size_t byte_size, | 269 const size_t byte_size, |
244 std::string* output) { | 270 std::string* output) { |
245 DCHECK(output); | 271 DCHECK(output); |
246 if (byte_size > input.length()) { | 272 if (byte_size > input.length()) { |
247 *output = input; | 273 *output = input; |
248 return; | 274 return; |
249 } | 275 } |
(...skipping 21 matching lines...) Expand all Loading... |
271 | 297 |
272 if (char_index >= 0 ) | 298 if (char_index >= 0 ) |
273 *output = input.substr(0, char_index); | 299 *output = input.substr(0, char_index); |
274 else | 300 else |
275 output->clear(); | 301 output->clear(); |
276 } | 302 } |
277 | 303 |
278 TrimPositions TrimWhitespace(const string16& input, | 304 TrimPositions TrimWhitespace(const string16& input, |
279 TrimPositions positions, | 305 TrimPositions positions, |
280 string16* output) { | 306 string16* output) { |
281 return TrimStringT(input, base::string16(kWhitespaceUTF16), positions, | 307 return TrimStringT(input, StringPiece16(kWhitespaceUTF16), positions, output); |
282 output); | |
283 } | 308 } |
284 | 309 |
285 TrimPositions TrimWhitespaceASCII(const std::string& input, | 310 TrimPositions TrimWhitespaceASCII(const std::string& input, |
286 TrimPositions positions, | 311 TrimPositions positions, |
287 std::string* output) { | 312 std::string* output) { |
288 return TrimStringT(input, std::string(kWhitespaceASCII), positions, output); | 313 return TrimStringT(input, StringPiece(kWhitespaceASCII), positions, output); |
289 } | 314 } |
290 | 315 |
291 // This function is only for backward-compatibility. | 316 // This function is only for backward-compatibility. |
292 // To be removed when all callers are updated. | 317 // To be removed when all callers are updated. |
293 TrimPositions TrimWhitespace(const std::string& input, | 318 TrimPositions TrimWhitespace(const std::string& input, |
294 TrimPositions positions, | 319 TrimPositions positions, |
295 std::string* output) { | 320 std::string* output) { |
296 return TrimWhitespaceASCII(input, positions, output); | 321 return TrimWhitespaceASCII(input, positions, output); |
297 } | 322 } |
298 | 323 |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 } | 714 } |
690 | 715 |
691 void ReplaceSubstringsAfterOffset(std::string* str, | 716 void ReplaceSubstringsAfterOffset(std::string* str, |
692 size_t start_offset, | 717 size_t start_offset, |
693 const std::string& find_this, | 718 const std::string& find_this, |
694 const std::string& replace_with) { | 719 const std::string& replace_with) { |
695 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, | 720 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, |
696 true); // replace all instances | 721 true); // replace all instances |
697 } | 722 } |
698 | 723 |
699 | 724 size_t Tokenize(const base::string16& str, |
700 template<typename STR> | 725 const base::string16& delimiters, |
701 static size_t TokenizeT(const STR& str, | 726 std::vector<base::string16>* tokens) { |
702 const STR& delimiters, | 727 *tokens = base::SplitString( |
703 std::vector<STR>* tokens) { | 728 str, delimiters, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
704 tokens->clear(); | |
705 | |
706 size_t start = str.find_first_not_of(delimiters); | |
707 while (start != STR::npos) { | |
708 size_t end = str.find_first_of(delimiters, start + 1); | |
709 if (end == STR::npos) { | |
710 tokens->push_back(str.substr(start)); | |
711 break; | |
712 } else { | |
713 tokens->push_back(str.substr(start, end - start)); | |
714 start = str.find_first_not_of(delimiters, end + 1); | |
715 } | |
716 } | |
717 | |
718 return tokens->size(); | 729 return tokens->size(); |
719 } | 730 } |
720 | 731 |
721 size_t Tokenize(const string16& str, | |
722 const string16& delimiters, | |
723 std::vector<string16>* tokens) { | |
724 return TokenizeT(str, delimiters, tokens); | |
725 } | |
726 | |
727 size_t Tokenize(const std::string& str, | 732 size_t Tokenize(const std::string& str, |
728 const std::string& delimiters, | 733 const std::string& delimiters, |
729 std::vector<std::string>* tokens) { | 734 std::vector<std::string>* tokens) { |
730 return TokenizeT(str, delimiters, tokens); | 735 *tokens = base::SplitString( |
| 736 str, delimiters, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 737 return tokens->size(); |
731 } | 738 } |
732 | 739 |
733 size_t Tokenize(const base::StringPiece& str, | 740 size_t Tokenize(const base::StringPiece& str, |
734 const base::StringPiece& delimiters, | 741 const base::StringPiece& delimiters, |
735 std::vector<base::StringPiece>* tokens) { | 742 std::vector<base::StringPiece>* tokens) { |
736 return TokenizeT(str, delimiters, tokens); | 743 *tokens = base::SplitStringPiece( |
| 744 str, delimiters, base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| 745 return tokens->size(); |
737 } | 746 } |
738 | 747 |
739 template<typename STR> | 748 template<typename STR> |
740 static STR JoinStringT(const std::vector<STR>& parts, const STR& sep) { | 749 static STR JoinStringT(const std::vector<STR>& parts, const STR& sep) { |
741 if (parts.empty()) | 750 if (parts.empty()) |
742 return STR(); | 751 return STR(); |
743 | 752 |
744 STR result(parts[0]); | 753 STR result(parts[0]); |
745 typename std::vector<STR>::const_iterator iter = parts.begin(); | 754 typename std::vector<STR>::const_iterator iter = parts.begin(); |
746 ++iter; | 755 ++iter; |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 } | 1046 } |
1038 | 1047 |
1039 } // namespace | 1048 } // namespace |
1040 | 1049 |
1041 size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { | 1050 size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { |
1042 return lcpyT<char>(dst, src, dst_size); | 1051 return lcpyT<char>(dst, src, dst_size); |
1043 } | 1052 } |
1044 size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { | 1053 size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { |
1045 return lcpyT<wchar_t>(dst, src, dst_size); | 1054 return lcpyT<wchar_t>(dst, src, dst_size); |
1046 } | 1055 } |
OLD | NEW |