| 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> |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 const std::string& EmptyString() { | 106 const std::string& EmptyString() { |
| 107 return EmptyStrings::GetInstance()->s; | 107 return EmptyStrings::GetInstance()->s; |
| 108 } | 108 } |
| 109 | 109 |
| 110 const string16& EmptyString16() { | 110 const string16& EmptyString16() { |
| 111 return EmptyStrings::GetInstance()->s16; | 111 return EmptyStrings::GetInstance()->s16; |
| 112 } | 112 } |
| 113 | 113 |
| 114 template<typename STR> | 114 template<typename STR> |
| 115 bool ReplaceCharsT(const STR& input, | 115 bool ReplaceCharsT(const STR& input, |
| 116 const typename STR::value_type replace_chars[], | 116 const STR& replace_chars, |
| 117 const STR& replace_with, | 117 const STR& replace_with, |
| 118 STR* output) { | 118 STR* output) { |
| 119 bool removed = false; | 119 bool removed = false; |
| 120 size_t replace_length = replace_with.length(); | 120 size_t replace_length = replace_with.length(); |
| 121 | 121 |
| 122 *output = input; | 122 *output = input; |
| 123 | 123 |
| 124 size_t found = output->find_first_of(replace_chars); | 124 size_t found = output->find_first_of(replace_chars); |
| 125 while (found != STR::npos) { | 125 while (found != STR::npos) { |
| 126 removed = true; | 126 removed = true; |
| 127 output->replace(found, 1, replace_with); | 127 output->replace(found, 1, replace_with); |
| 128 found = output->find_first_of(replace_chars, found + replace_length); | 128 found = output->find_first_of(replace_chars, found + replace_length); |
| 129 } | 129 } |
| 130 | 130 |
| 131 return removed; | 131 return removed; |
| 132 } | 132 } |
| 133 | 133 |
| 134 bool ReplaceChars(const string16& input, | 134 bool ReplaceChars(const string16& input, |
| 135 const char16 replace_chars[], | 135 const base::StringPiece16& replace_chars, |
| 136 const string16& replace_with, | 136 const string16& replace_with, |
| 137 string16* output) { | 137 string16* output) { |
| 138 return ReplaceCharsT(input, replace_chars, replace_with, output); | 138 return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); |
| 139 } | 139 } |
| 140 | 140 |
| 141 bool ReplaceChars(const std::string& input, | 141 bool ReplaceChars(const std::string& input, |
| 142 const char replace_chars[], | 142 const base::StringPiece& replace_chars, |
| 143 const std::string& replace_with, | 143 const std::string& replace_with, |
| 144 std::string* output) { | 144 std::string* output) { |
| 145 return ReplaceCharsT(input, replace_chars, replace_with, output); | 145 return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); |
| 146 } | 146 } |
| 147 | 147 |
| 148 bool RemoveChars(const string16& input, | 148 bool RemoveChars(const string16& input, |
| 149 const char16 remove_chars[], | 149 const base::StringPiece16& remove_chars, |
| 150 string16* output) { | 150 string16* output) { |
| 151 return ReplaceChars(input, remove_chars, string16(), output); | 151 return ReplaceChars(input, remove_chars.as_string(), string16(), output); |
| 152 } | 152 } |
| 153 | 153 |
| 154 bool RemoveChars(const std::string& input, | 154 bool RemoveChars(const std::string& input, |
| 155 const char remove_chars[], | 155 const base::StringPiece& remove_chars, |
| 156 std::string* output) { | 156 std::string* output) { |
| 157 return ReplaceChars(input, remove_chars, std::string(), output); | 157 return ReplaceChars(input, remove_chars.as_string(), std::string(), output); |
| 158 } | 158 } |
| 159 | 159 |
| 160 template<typename STR> | 160 template<typename STR> |
| 161 TrimPositions TrimStringT(const STR& input, | 161 TrimPositions TrimStringT(const STR& input, |
| 162 const typename STR::value_type trim_chars[], | 162 const STR& trim_chars, |
| 163 TrimPositions positions, | 163 TrimPositions positions, |
| 164 STR* output) { | 164 STR* output) { |
| 165 // Find the edges of leading/trailing whitespace as desired. | 165 // Find the edges of leading/trailing whitespace as desired. |
| 166 const typename STR::size_type last_char = input.length() - 1; | 166 const size_t last_char = input.length() - 1; |
| 167 const typename STR::size_type first_good_char = (positions & TRIM_LEADING) ? | 167 const size_t first_good_char = (positions & TRIM_LEADING) ? |
| 168 input.find_first_not_of(trim_chars) : 0; | 168 input.find_first_not_of(trim_chars) : 0; |
| 169 const typename STR::size_type last_good_char = (positions & TRIM_TRAILING) ? | 169 const size_t last_good_char = (positions & TRIM_TRAILING) ? |
| 170 input.find_last_not_of(trim_chars) : last_char; | 170 input.find_last_not_of(trim_chars) : last_char; |
| 171 | 171 |
| 172 // When the string was all whitespace, report that we stripped off whitespace | 172 // When the string was all whitespace, report that we stripped off whitespace |
| 173 // from whichever position the caller was interested in. For empty input, we | 173 // from whichever position the caller was interested in. For empty input, we |
| 174 // stripped no whitespace, but we still need to clear |output|. | 174 // stripped no whitespace, but we still need to clear |output|. |
| 175 if (input.empty() || | 175 if (input.empty() || |
| 176 (first_good_char == STR::npos) || (last_good_char == STR::npos)) { | 176 (first_good_char == STR::npos) || (last_good_char == STR::npos)) { |
| 177 bool input_was_empty = input.empty(); // in case output == &input | 177 bool input_was_empty = input.empty(); // in case output == &input |
| 178 output->clear(); | 178 output->clear(); |
| 179 return input_was_empty ? TRIM_NONE : positions; | 179 return input_was_empty ? TRIM_NONE : positions; |
| 180 } | 180 } |
| 181 | 181 |
| 182 // Trim the whitespace. | 182 // Trim the whitespace. |
| 183 *output = | 183 *output = |
| 184 input.substr(first_good_char, last_good_char - first_good_char + 1); | 184 input.substr(first_good_char, last_good_char - first_good_char + 1); |
| 185 | 185 |
| 186 // Return where we trimmed from. | 186 // Return where we trimmed from. |
| 187 return static_cast<TrimPositions>( | 187 return static_cast<TrimPositions>( |
| 188 ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | | 188 ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | |
| 189 ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); | 189 ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); |
| 190 } | 190 } |
| 191 | 191 |
| 192 bool TrimString(const string16& input, | 192 bool TrimString(const string16& input, |
| 193 const char16 trim_chars[], | 193 const base::StringPiece16& trim_chars, |
| 194 string16* output) { | 194 string16* output) { |
| 195 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; | 195 return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != |
| 196 TRIM_NONE; |
| 196 } | 197 } |
| 197 | 198 |
| 198 bool TrimString(const std::string& input, | 199 bool TrimString(const std::string& input, |
| 199 const char trim_chars[], | 200 const base::StringPiece& trim_chars, |
| 200 std::string* output) { | 201 std::string* output) { |
| 201 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; | 202 return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != |
| 203 TRIM_NONE; |
| 202 } | 204 } |
| 203 | 205 |
| 204 void TruncateUTF8ToByteSize(const std::string& input, | 206 void TruncateUTF8ToByteSize(const std::string& input, |
| 205 const size_t byte_size, | 207 const size_t byte_size, |
| 206 std::string* output) { | 208 std::string* output) { |
| 207 DCHECK(output); | 209 DCHECK(output); |
| 208 if (byte_size > input.length()) { | 210 if (byte_size > input.length()) { |
| 209 *output = input; | 211 *output = input; |
| 210 return; | 212 return; |
| 211 } | 213 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 233 | 235 |
| 234 if (char_index >= 0 ) | 236 if (char_index >= 0 ) |
| 235 *output = input.substr(0, char_index); | 237 *output = input.substr(0, char_index); |
| 236 else | 238 else |
| 237 output->clear(); | 239 output->clear(); |
| 238 } | 240 } |
| 239 | 241 |
| 240 TrimPositions TrimWhitespace(const string16& input, | 242 TrimPositions TrimWhitespace(const string16& input, |
| 241 TrimPositions positions, | 243 TrimPositions positions, |
| 242 string16* output) { | 244 string16* output) { |
| 243 return TrimStringT(input, kWhitespaceUTF16, positions, output); | 245 return TrimStringT(input, base::string16(kWhitespaceUTF16), positions, |
| 246 output); |
| 244 } | 247 } |
| 245 | 248 |
| 246 TrimPositions TrimWhitespaceASCII(const std::string& input, | 249 TrimPositions TrimWhitespaceASCII(const std::string& input, |
| 247 TrimPositions positions, | 250 TrimPositions positions, |
| 248 std::string* output) { | 251 std::string* output) { |
| 249 return TrimStringT(input, kWhitespaceASCII, positions, output); | 252 return TrimStringT(input, std::string(kWhitespaceASCII), positions, output); |
| 250 } | 253 } |
| 251 | 254 |
| 252 // This function is only for backward-compatibility. | 255 // This function is only for backward-compatibility. |
| 253 // To be removed when all callers are updated. | 256 // To be removed when all callers are updated. |
| 254 TrimPositions TrimWhitespace(const std::string& input, | 257 TrimPositions TrimWhitespace(const std::string& input, |
| 255 TrimPositions positions, | 258 TrimPositions positions, |
| 256 std::string* output) { | 259 std::string* output) { |
| 257 return TrimWhitespaceASCII(input, positions, output); | 260 return TrimWhitespaceASCII(input, positions, output); |
| 258 } | 261 } |
| 259 | 262 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 } | 431 } |
| 429 } | 432 } |
| 430 | 433 |
| 431 bool StartsWith(const string16& str, const string16& search, | 434 bool StartsWith(const string16& str, const string16& search, |
| 432 bool case_sensitive) { | 435 bool case_sensitive) { |
| 433 return StartsWithT(str, search, case_sensitive); | 436 return StartsWithT(str, search, case_sensitive); |
| 434 } | 437 } |
| 435 | 438 |
| 436 template <typename STR> | 439 template <typename STR> |
| 437 bool EndsWithT(const STR& str, const STR& search, bool case_sensitive) { | 440 bool EndsWithT(const STR& str, const STR& search, bool case_sensitive) { |
| 438 typename STR::size_type str_length = str.length(); | 441 size_t str_length = str.length(); |
| 439 typename STR::size_type search_length = search.length(); | 442 size_t search_length = search.length(); |
| 440 if (search_length > str_length) | 443 if (search_length > str_length) |
| 441 return false; | 444 return false; |
| 442 if (case_sensitive) { | 445 if (case_sensitive) |
| 443 return str.compare(str_length - search_length, search_length, search) == 0; | 446 return str.compare(str_length - search_length, search_length, search) == 0; |
| 444 } else { | 447 return std::equal(search.begin(), search.end(), |
| 445 return std::equal(search.begin(), search.end(), | 448 str.begin() + (str_length - search_length), |
| 446 str.begin() + (str_length - search_length), | 449 base::CaseInsensitiveCompare<typename STR::value_type>()); |
| 447 base::CaseInsensitiveCompare<typename STR::value_type>()); | |
| 448 } | |
| 449 } | 450 } |
| 450 | 451 |
| 451 bool EndsWith(const std::string& str, const std::string& search, | 452 bool EndsWith(const std::string& str, const std::string& search, |
| 452 bool case_sensitive) { | 453 bool case_sensitive) { |
| 453 return EndsWithT(str, search, case_sensitive); | 454 return EndsWithT(str, search, case_sensitive); |
| 454 } | 455 } |
| 455 | 456 |
| 456 bool EndsWith(const string16& str, const string16& search, | 457 bool EndsWith(const string16& str, const string16& search, |
| 457 bool case_sensitive) { | 458 bool case_sensitive) { |
| 458 return EndsWithT(str, search, case_sensitive); | 459 return EndsWithT(str, search, case_sensitive); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 484 } else { | 485 } else { |
| 485 base::snprintf(buf, arraysize(buf), "%.0lf%s", unit_amount, | 486 base::snprintf(buf, arraysize(buf), "%.0lf%s", unit_amount, |
| 486 kByteStringsUnlocalized[dimension]); | 487 kByteStringsUnlocalized[dimension]); |
| 487 } | 488 } |
| 488 | 489 |
| 489 return base::ASCIIToUTF16(buf); | 490 return base::ASCIIToUTF16(buf); |
| 490 } | 491 } |
| 491 | 492 |
| 492 template<class StringType> | 493 template<class StringType> |
| 493 void DoReplaceSubstringsAfterOffset(StringType* str, | 494 void DoReplaceSubstringsAfterOffset(StringType* str, |
| 494 typename StringType::size_type start_offset, | 495 size_t start_offset, |
| 495 const StringType& find_this, | 496 const StringType& find_this, |
| 496 const StringType& replace_with, | 497 const StringType& replace_with, |
| 497 bool replace_all) { | 498 bool replace_all) { |
| 498 if ((start_offset == StringType::npos) || (start_offset >= str->length())) | 499 if ((start_offset == StringType::npos) || (start_offset >= str->length())) |
| 499 return; | 500 return; |
| 500 | 501 |
| 501 DCHECK(!find_this.empty()); | 502 DCHECK(!find_this.empty()); |
| 502 for (typename StringType::size_type offs(str->find(find_this, start_offset)); | 503 for (size_t offs(str->find(find_this, start_offset)); |
| 503 offs != StringType::npos; offs = str->find(find_this, offs)) { | 504 offs != StringType::npos; offs = str->find(find_this, offs)) { |
| 504 str->replace(offs, find_this.length(), replace_with); | 505 str->replace(offs, find_this.length(), replace_with); |
| 505 offs += replace_with.length(); | 506 offs += replace_with.length(); |
| 506 | 507 |
| 507 if (!replace_all) | 508 if (!replace_all) |
| 508 break; | 509 break; |
| 509 } | 510 } |
| 510 } | 511 } |
| 511 | 512 |
| 512 void ReplaceFirstSubstringAfterOffset(string16* str, | 513 void ReplaceFirstSubstringAfterOffset(string16* str, |
| 513 string16::size_type start_offset, | 514 size_t start_offset, |
| 514 const string16& find_this, | 515 const string16& find_this, |
| 515 const string16& replace_with) { | 516 const string16& replace_with) { |
| 516 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, | 517 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, |
| 517 false); // replace first instance | 518 false); // replace first instance |
| 518 } | 519 } |
| 519 | 520 |
| 520 void ReplaceFirstSubstringAfterOffset(std::string* str, | 521 void ReplaceFirstSubstringAfterOffset(std::string* str, |
| 521 std::string::size_type start_offset, | 522 size_t start_offset, |
| 522 const std::string& find_this, | 523 const std::string& find_this, |
| 523 const std::string& replace_with) { | 524 const std::string& replace_with) { |
| 524 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, | 525 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, |
| 525 false); // replace first instance | 526 false); // replace first instance |
| 526 } | 527 } |
| 527 | 528 |
| 528 void ReplaceSubstringsAfterOffset(string16* str, | 529 void ReplaceSubstringsAfterOffset(string16* str, |
| 529 string16::size_type start_offset, | 530 size_t start_offset, |
| 530 const string16& find_this, | 531 const string16& find_this, |
| 531 const string16& replace_with) { | 532 const string16& replace_with) { |
| 532 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, | 533 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, |
| 533 true); // replace all instances | 534 true); // replace all instances |
| 534 } | 535 } |
| 535 | 536 |
| 536 void ReplaceSubstringsAfterOffset(std::string* str, | 537 void ReplaceSubstringsAfterOffset(std::string* str, |
| 537 std::string::size_type start_offset, | 538 size_t start_offset, |
| 538 const std::string& find_this, | 539 const std::string& find_this, |
| 539 const std::string& replace_with) { | 540 const std::string& replace_with) { |
| 540 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, | 541 DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, |
| 541 true); // replace all instances | 542 true); // replace all instances |
| 542 } | 543 } |
| 543 | 544 |
| 544 | 545 |
| 545 template<typename STR> | 546 template<typename STR> |
| 546 static size_t TokenizeT(const STR& str, | 547 static size_t TokenizeT(const STR& str, |
| 547 const STR& delimiters, | 548 const STR& delimiters, |
| 548 std::vector<STR>* tokens) { | 549 std::vector<STR>* tokens) { |
| 549 tokens->clear(); | 550 tokens->clear(); |
| 550 | 551 |
| 551 typename STR::size_type start = str.find_first_not_of(delimiters); | 552 size_t start = str.find_first_not_of(delimiters); |
| 552 while (start != STR::npos) { | 553 while (start != STR::npos) { |
| 553 typename STR::size_type end = str.find_first_of(delimiters, start + 1); | 554 size_t end = str.find_first_of(delimiters, start + 1); |
| 554 if (end == STR::npos) { | 555 if (end == STR::npos) { |
| 555 tokens->push_back(str.substr(start)); | 556 tokens->push_back(str.substr(start)); |
| 556 break; | 557 break; |
| 557 } else { | 558 } else { |
| 558 tokens->push_back(str.substr(start, end - start)); | 559 tokens->push_back(str.substr(start, end - start)); |
| 559 start = str.find_first_not_of(delimiters, end + 1); | 560 start = str.find_first_not_of(delimiters, end + 1); |
| 560 } | 561 } |
| 561 } | 562 } |
| 562 | 563 |
| 563 return tokens->size(); | 564 return tokens->size(); |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 } | 883 } |
| 883 | 884 |
| 884 } // namespace | 885 } // namespace |
| 885 | 886 |
| 886 size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { | 887 size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { |
| 887 return lcpyT<char>(dst, src, dst_size); | 888 return lcpyT<char>(dst, src, dst_size); |
| 888 } | 889 } |
| 889 size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { | 890 size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { |
| 890 return lcpyT<wchar_t>(dst, src, dst_size); | 891 return lcpyT<wchar_t>(dst, src, dst_size); |
| 891 } | 892 } |
| OLD | NEW |