| 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 |