| 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/string_split.h" |
| 25 #include "base/strings/utf_string_conversion_utils.h" | 25 #include "base/strings/utf_string_conversion_utils.h" |
| 26 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
| 27 #include "base/third_party/icu/icu_utf.h" | 27 #include "base/third_party/icu/icu_utf.h" |
| 28 #include "build/build_config.h" | 28 #include "build/build_config.h" |
| 29 | 29 |
| 30 // Remove when this entire file is in the base namespace. | 30 namespace base { |
| 31 using base::char16; | |
| 32 using base::string16; | |
| 33 | 31 |
| 34 namespace { | 32 namespace { |
| 35 | 33 |
| 36 // Force the singleton used by EmptyString[16] to be a unique type. This | 34 // Force the singleton used by EmptyString[16] to be a unique type. This |
| 37 // prevents other code that might accidentally use Singleton<string> from | 35 // prevents other code that might accidentally use Singleton<string> from |
| 38 // getting our internal one. | 36 // getting our internal one. |
| 39 struct EmptyStrings { | 37 struct EmptyStrings { |
| 40 EmptyStrings() {} | 38 EmptyStrings() {} |
| 41 const std::string s; | 39 const std::string s; |
| 42 const string16 s16; | 40 const string16 s16; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 73 inline bool IsAlignedToMachineWord(const void* pointer) { | 71 inline bool IsAlignedToMachineWord(const void* pointer) { |
| 74 return !(reinterpret_cast<MachineWord>(pointer) & kMachineWordAlignmentMask); | 72 return !(reinterpret_cast<MachineWord>(pointer) & kMachineWordAlignmentMask); |
| 75 } | 73 } |
| 76 | 74 |
| 77 template<typename T> inline T* AlignToMachineWord(T* pointer) { | 75 template<typename T> inline T* AlignToMachineWord(T* pointer) { |
| 78 return reinterpret_cast<T*>(reinterpret_cast<MachineWord>(pointer) & | 76 return reinterpret_cast<T*>(reinterpret_cast<MachineWord>(pointer) & |
| 79 ~kMachineWordAlignmentMask); | 77 ~kMachineWordAlignmentMask); |
| 80 } | 78 } |
| 81 | 79 |
| 82 template<size_t size, typename CharacterType> struct NonASCIIMask; | 80 template<size_t size, typename CharacterType> struct NonASCIIMask; |
| 83 template<> struct NonASCIIMask<4, base::char16> { | 81 template<> struct NonASCIIMask<4, char16> { |
| 84 static inline uint32_t value() { return 0xFF80FF80U; } | 82 static inline uint32_t value() { return 0xFF80FF80U; } |
| 85 }; | 83 }; |
| 86 template<> struct NonASCIIMask<4, char> { | 84 template<> struct NonASCIIMask<4, char> { |
| 87 static inline uint32_t value() { return 0x80808080U; } | 85 static inline uint32_t value() { return 0x80808080U; } |
| 88 }; | 86 }; |
| 89 template<> struct NonASCIIMask<8, base::char16> { | 87 template<> struct NonASCIIMask<8, char16> { |
| 90 static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; } | 88 static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; } |
| 91 }; | 89 }; |
| 92 template<> struct NonASCIIMask<8, char> { | 90 template<> struct NonASCIIMask<8, char> { |
| 93 static inline uint64_t value() { return 0x8080808080808080ULL; } | 91 static inline uint64_t value() { return 0x8080808080808080ULL; } |
| 94 }; | 92 }; |
| 95 #if defined(WCHAR_T_IS_UTF32) | 93 #if defined(WCHAR_T_IS_UTF32) |
| 96 template<> struct NonASCIIMask<4, wchar_t> { | 94 template<> struct NonASCIIMask<4, wchar_t> { |
| 97 static inline uint32_t value() { return 0xFFFFFF80U; } | 95 static inline uint32_t value() { return 0xFFFFFF80U; } |
| 98 }; | 96 }; |
| 99 template<> struct NonASCIIMask<8, wchar_t> { | 97 template<> struct NonASCIIMask<8, wchar_t> { |
| 100 static inline uint64_t value() { return 0xFFFFFF80FFFFFF80ULL; } | 98 static inline uint64_t value() { return 0xFFFFFF80FFFFFF80ULL; } |
| 101 }; | 99 }; |
| 102 #endif // WCHAR_T_IS_UTF32 | 100 #endif // WCHAR_T_IS_UTF32 |
| 103 | 101 |
| 104 // DO NOT USE. http://crbug.com/24917 | 102 // DO NOT USE. http://crbug.com/24917 |
| 105 // | 103 // |
| 106 // tolower() will given incorrect results for non-ASCII characters. Use the | 104 // tolower() will given incorrect results for non-ASCII characters. Use the |
| 107 // ASCII version, base::i18n::ToLower, or base::i18n::FoldCase. This is here | 105 // ASCII version, base::i18n::ToLower, or base::i18n::FoldCase. This is here |
| 108 // for backwards-compat for StartsWith until such calls can be updated. | 106 // for backwards-compat for StartsWith until such calls can be updated. |
| 109 struct CaseInsensitiveCompareDeprecated { | 107 struct CaseInsensitiveCompareDeprecated { |
| 110 public: | 108 public: |
| 111 bool operator()(char16 x, char16 y) const { | 109 bool operator()(char16 x, char16 y) const { |
| 112 return tolower(x) == tolower(y); | 110 return tolower(x) == tolower(y); |
| 113 } | 111 } |
| 114 }; | 112 }; |
| 115 | 113 |
| 116 } // namespace | 114 } // namespace |
| 117 | 115 |
| 118 namespace base { | |
| 119 | |
| 120 bool IsWprintfFormatPortable(const wchar_t* format) { | 116 bool IsWprintfFormatPortable(const wchar_t* format) { |
| 121 for (const wchar_t* position = format; *position != '\0'; ++position) { | 117 for (const wchar_t* position = format; *position != '\0'; ++position) { |
| 122 if (*position == '%') { | 118 if (*position == '%') { |
| 123 bool in_specification = true; | 119 bool in_specification = true; |
| 124 bool modifier_l = false; | 120 bool modifier_l = false; |
| 125 while (in_specification) { | 121 while (in_specification) { |
| 126 // Eat up characters until reaching a known specifier. | 122 // Eat up characters until reaching a known specifier. |
| 127 if (*++position == '\0') { | 123 if (*++position == '\0') { |
| 128 // The format string ended in the middle of a specification. Call | 124 // The format string ended in the middle of a specification. Call |
| 129 // it portable because no unportable specifications were found. The | 125 // it portable because no unportable specifications were found. The |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 // End of one string hit before finding a different character. Expect the | 168 // End of one string hit before finding a different character. Expect the |
| 173 // common case to be "strings equal" at this point so check that first. | 169 // common case to be "strings equal" at this point so check that first. |
| 174 if (a.length() == b.length()) | 170 if (a.length() == b.length()) |
| 175 return 0; | 171 return 0; |
| 176 | 172 |
| 177 if (a.length() < b.length()) | 173 if (a.length() < b.length()) |
| 178 return -1; | 174 return -1; |
| 179 return 1; | 175 return 1; |
| 180 } | 176 } |
| 181 | 177 |
| 182 int CompareCaseInsensitiveASCII(base::StringPiece a, base::StringPiece b) { | 178 int CompareCaseInsensitiveASCII(StringPiece a, StringPiece b) { |
| 183 return CompareCaseInsensitiveASCIIT<std::string>(a, b); | 179 return CompareCaseInsensitiveASCIIT<std::string>(a, b); |
| 184 } | 180 } |
| 185 | 181 |
| 186 int CompareCaseInsensitiveASCII(base::StringPiece16 a, base::StringPiece16 b) { | 182 int CompareCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) { |
| 187 return CompareCaseInsensitiveASCIIT<base::string16>(a, b); | 183 return CompareCaseInsensitiveASCIIT<string16>(a, b); |
| 188 } | 184 } |
| 189 | 185 |
| 190 bool EqualsCaseInsensitiveASCII(base::StringPiece a, base::StringPiece b) { | 186 bool EqualsCaseInsensitiveASCII(StringPiece a, StringPiece b) { |
| 191 if (a.length() != b.length()) | 187 if (a.length() != b.length()) |
| 192 return false; | 188 return false; |
| 193 return CompareCaseInsensitiveASCIIT<std::string>(a, b) == 0; | 189 return CompareCaseInsensitiveASCIIT<std::string>(a, b) == 0; |
| 194 } | 190 } |
| 195 | 191 |
| 196 bool EqualsCaseInsensitiveASCII(base::StringPiece16 a, base::StringPiece16 b) { | 192 bool EqualsCaseInsensitiveASCII(StringPiece16 a, StringPiece16 b) { |
| 197 if (a.length() != b.length()) | 193 if (a.length() != b.length()) |
| 198 return false; | 194 return false; |
| 199 return CompareCaseInsensitiveASCIIT<base::string16>(a, b) == 0; | 195 return CompareCaseInsensitiveASCIIT<string16>(a, b) == 0; |
| 200 } | 196 } |
| 201 | 197 |
| 202 const std::string& EmptyString() { | 198 const std::string& EmptyString() { |
| 203 return EmptyStrings::GetInstance()->s; | 199 return EmptyStrings::GetInstance()->s; |
| 204 } | 200 } |
| 205 | 201 |
| 206 const string16& EmptyString16() { | 202 const string16& EmptyString16() { |
| 207 return EmptyStrings::GetInstance()->s16; | 203 return EmptyStrings::GetInstance()->s16; |
| 208 } | 204 } |
| 209 | 205 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 221 while (found != STR::npos) { | 217 while (found != STR::npos) { |
| 222 removed = true; | 218 removed = true; |
| 223 output->replace(found, 1, replace_with); | 219 output->replace(found, 1, replace_with); |
| 224 found = output->find_first_of(replace_chars, found + replace_length); | 220 found = output->find_first_of(replace_chars, found + replace_length); |
| 225 } | 221 } |
| 226 | 222 |
| 227 return removed; | 223 return removed; |
| 228 } | 224 } |
| 229 | 225 |
| 230 bool ReplaceChars(const string16& input, | 226 bool ReplaceChars(const string16& input, |
| 231 const base::StringPiece16& replace_chars, | 227 const StringPiece16& replace_chars, |
| 232 const string16& replace_with, | 228 const string16& replace_with, |
| 233 string16* output) { | 229 string16* output) { |
| 234 return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); | 230 return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); |
| 235 } | 231 } |
| 236 | 232 |
| 237 bool ReplaceChars(const std::string& input, | 233 bool ReplaceChars(const std::string& input, |
| 238 const base::StringPiece& replace_chars, | 234 const StringPiece& replace_chars, |
| 239 const std::string& replace_with, | 235 const std::string& replace_with, |
| 240 std::string* output) { | 236 std::string* output) { |
| 241 return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); | 237 return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); |
| 242 } | 238 } |
| 243 | 239 |
| 244 bool RemoveChars(const string16& input, | 240 bool RemoveChars(const string16& input, |
| 245 const base::StringPiece16& remove_chars, | 241 const StringPiece16& remove_chars, |
| 246 string16* output) { | 242 string16* output) { |
| 247 return ReplaceChars(input, remove_chars.as_string(), string16(), output); | 243 return ReplaceChars(input, remove_chars.as_string(), string16(), output); |
| 248 } | 244 } |
| 249 | 245 |
| 250 bool RemoveChars(const std::string& input, | 246 bool RemoveChars(const std::string& input, |
| 251 const base::StringPiece& remove_chars, | 247 const StringPiece& remove_chars, |
| 252 std::string* output) { | 248 std::string* output) { |
| 253 return ReplaceChars(input, remove_chars.as_string(), std::string(), output); | 249 return ReplaceChars(input, remove_chars.as_string(), std::string(), output); |
| 254 } | 250 } |
| 255 | 251 |
| 256 template<typename Str> | 252 template<typename Str> |
| 257 TrimPositions TrimStringT(const Str& input, | 253 TrimPositions TrimStringT(const Str& input, |
| 258 BasicStringPiece<Str> trim_chars, | 254 BasicStringPiece<Str> trim_chars, |
| 259 TrimPositions positions, | 255 TrimPositions positions, |
| 260 Str* output) { | 256 Str* output) { |
| 261 // Find the edges of leading/trailing whitespace as desired. Need to use | 257 // Find the edges of leading/trailing whitespace as desired. Need to use |
| (...skipping 21 matching lines...) Expand all Loading... |
| 283 *output = | 279 *output = |
| 284 input.substr(first_good_char, last_good_char - first_good_char + 1); | 280 input.substr(first_good_char, last_good_char - first_good_char + 1); |
| 285 | 281 |
| 286 // Return where we trimmed from. | 282 // Return where we trimmed from. |
| 287 return static_cast<TrimPositions>( | 283 return static_cast<TrimPositions>( |
| 288 ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | | 284 ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | |
| 289 ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); | 285 ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); |
| 290 } | 286 } |
| 291 | 287 |
| 292 bool TrimString(const string16& input, | 288 bool TrimString(const string16& input, |
| 293 base::StringPiece16 trim_chars, | 289 StringPiece16 trim_chars, |
| 294 string16* output) { | 290 string16* output) { |
| 295 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; | 291 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; |
| 296 } | 292 } |
| 297 | 293 |
| 298 bool TrimString(const std::string& input, | 294 bool TrimString(const std::string& input, |
| 299 base::StringPiece trim_chars, | 295 StringPiece trim_chars, |
| 300 std::string* output) { | 296 std::string* output) { |
| 301 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; | 297 return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; |
| 302 } | 298 } |
| 303 | 299 |
| 304 template<typename Str> | 300 template<typename Str> |
| 305 BasicStringPiece<Str> TrimStringPieceT(BasicStringPiece<Str> input, | 301 BasicStringPiece<Str> TrimStringPieceT(BasicStringPiece<Str> input, |
| 306 BasicStringPiece<Str> trim_chars, | 302 BasicStringPiece<Str> trim_chars, |
| 307 TrimPositions positions) { | 303 TrimPositions positions) { |
| 308 size_t begin = (positions & TRIM_LEADING) ? | 304 size_t begin = (positions & TRIM_LEADING) ? |
| 309 input.find_first_not_of(trim_chars) : 0; | 305 input.find_first_not_of(trim_chars) : 0; |
| 310 size_t end = (positions & TRIM_TRAILING) ? | 306 size_t end = (positions & TRIM_TRAILING) ? |
| 311 input.find_last_not_of(trim_chars) + 1 : input.size(); | 307 input.find_last_not_of(trim_chars) + 1 : input.size(); |
| 312 return input.substr(begin, end - begin); | 308 return input.substr(begin, end - begin); |
| 313 } | 309 } |
| 314 | 310 |
| 315 StringPiece16 TrimString(StringPiece16 input, | 311 StringPiece16 TrimString(StringPiece16 input, |
| 316 const base::StringPiece16& trim_chars, | 312 const StringPiece16& trim_chars, |
| 317 TrimPositions positions) { | 313 TrimPositions positions) { |
| 318 return TrimStringPieceT(input, trim_chars, positions); | 314 return TrimStringPieceT(input, trim_chars, positions); |
| 319 } | 315 } |
| 320 | 316 |
| 321 StringPiece TrimString(StringPiece input, | 317 StringPiece TrimString(StringPiece input, |
| 322 const base::StringPiece& trim_chars, | 318 const StringPiece& trim_chars, |
| 323 TrimPositions positions) { | 319 TrimPositions positions) { |
| 324 return TrimStringPieceT(input, trim_chars, positions); | 320 return TrimStringPieceT(input, trim_chars, positions); |
| 325 } | 321 } |
| 326 | 322 |
| 327 void TruncateUTF8ToByteSize(const std::string& input, | 323 void TruncateUTF8ToByteSize(const std::string& input, |
| 328 const size_t byte_size, | 324 const size_t byte_size, |
| 329 std::string* output) { | 325 std::string* output) { |
| 330 DCHECK(output); | 326 DCHECK(output); |
| 331 if (byte_size > input.length()) { | 327 if (byte_size > input.length()) { |
| 332 *output = input; | 328 *output = input; |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 BasicStringPiece<Str> source = str.substr(0, search_for.size()); | 581 BasicStringPiece<Str> source = str.substr(0, search_for.size()); |
| 586 | 582 |
| 587 switch (case_sensitivity) { | 583 switch (case_sensitivity) { |
| 588 case CompareCase::SENSITIVE: | 584 case CompareCase::SENSITIVE: |
| 589 return source == search_for; | 585 return source == search_for; |
| 590 | 586 |
| 591 case CompareCase::INSENSITIVE_ASCII: | 587 case CompareCase::INSENSITIVE_ASCII: |
| 592 return std::equal( | 588 return std::equal( |
| 593 search_for.begin(), search_for.end(), | 589 search_for.begin(), search_for.end(), |
| 594 source.begin(), | 590 source.begin(), |
| 595 base::CaseInsensitiveCompareASCII<typename Str::value_type>()); | 591 CaseInsensitiveCompareASCII<typename Str::value_type>()); |
| 596 | 592 |
| 597 default: | 593 default: |
| 598 NOTREACHED(); | 594 NOTREACHED(); |
| 599 return false; | 595 return false; |
| 600 } | 596 } |
| 601 } | 597 } |
| 602 | 598 |
| 603 bool StartsWith(StringPiece str, | 599 bool StartsWith(StringPiece str, |
| 604 StringPiece search_for, | 600 StringPiece search_for, |
| 605 CompareCase case_sensitivity) { | 601 CompareCase case_sensitivity) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 search_for.size()); | 636 search_for.size()); |
| 641 | 637 |
| 642 switch (case_sensitivity) { | 638 switch (case_sensitivity) { |
| 643 case CompareCase::SENSITIVE: | 639 case CompareCase::SENSITIVE: |
| 644 return source == search_for; | 640 return source == search_for; |
| 645 | 641 |
| 646 case CompareCase::INSENSITIVE_ASCII: | 642 case CompareCase::INSENSITIVE_ASCII: |
| 647 return std::equal( | 643 return std::equal( |
| 648 source.begin(), source.end(), | 644 source.begin(), source.end(), |
| 649 search_for.begin(), | 645 search_for.begin(), |
| 650 base::CaseInsensitiveCompareASCII<typename Str::value_type>()); | 646 CaseInsensitiveCompareASCII<typename Str::value_type>()); |
| 651 | 647 |
| 652 default: | 648 default: |
| 653 NOTREACHED(); | 649 NOTREACHED(); |
| 654 return false; | 650 return false; |
| 655 } | 651 } |
| 656 } | 652 } |
| 657 | 653 |
| 658 bool EndsWith(StringPiece str, | 654 bool EndsWith(StringPiece str, |
| 659 StringPiece search_for, | 655 StringPiece search_for, |
| 660 CompareCase case_sensitivity) { | 656 CompareCase case_sensitivity) { |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 DCHECK_GT(length_with_null, 1u); | 869 DCHECK_GT(length_with_null, 1u); |
| 874 str->reserve(length_with_null); | 870 str->reserve(length_with_null); |
| 875 str->resize(length_with_null - 1); | 871 str->resize(length_with_null - 1); |
| 876 return &((*str)[0]); | 872 return &((*str)[0]); |
| 877 } | 873 } |
| 878 | 874 |
| 879 char* WriteInto(std::string* str, size_t length_with_null) { | 875 char* WriteInto(std::string* str, size_t length_with_null) { |
| 880 return WriteIntoT(str, length_with_null); | 876 return WriteIntoT(str, length_with_null); |
| 881 } | 877 } |
| 882 | 878 |
| 883 char16* WriteInto(base::string16* str, size_t length_with_null) { | 879 char16* WriteInto(string16* str, size_t length_with_null) { |
| 884 return WriteIntoT(str, length_with_null); | 880 return WriteIntoT(str, length_with_null); |
| 885 } | 881 } |
| 886 | 882 |
| 887 template<typename STR> | 883 template<typename STR> |
| 888 static STR JoinStringT(const std::vector<STR>& parts, | 884 static STR JoinStringT(const std::vector<STR>& parts, |
| 889 BasicStringPiece<STR> sep) { | 885 BasicStringPiece<STR> sep) { |
| 890 if (parts.empty()) | 886 if (parts.empty()) |
| 891 return STR(); | 887 return STR(); |
| 892 | 888 |
| 893 STR result(parts[0]); | 889 STR result(parts[0]); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 905 std::string JoinString(const std::vector<std::string>& parts, | 901 std::string JoinString(const std::vector<std::string>& parts, |
| 906 StringPiece separator) { | 902 StringPiece separator) { |
| 907 return JoinStringT(parts, separator); | 903 return JoinStringT(parts, separator); |
| 908 } | 904 } |
| 909 | 905 |
| 910 string16 JoinString(const std::vector<string16>& parts, | 906 string16 JoinString(const std::vector<string16>& parts, |
| 911 StringPiece16 separator) { | 907 StringPiece16 separator) { |
| 912 return JoinStringT(parts, separator); | 908 return JoinStringT(parts, separator); |
| 913 } | 909 } |
| 914 | 910 |
| 915 } // namespace base | |
| 916 | |
| 917 template<class FormatStringType, class OutStringType> | 911 template<class FormatStringType, class OutStringType> |
| 918 OutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string, | 912 OutStringType DoReplaceStringPlaceholders( |
| 919 const std::vector<OutStringType>& subst, std::vector<size_t>* offsets) { | 913 const FormatStringType& format_string, |
| 914 const std::vector<OutStringType>& subst, |
| 915 std::vector<size_t>* offsets) { |
| 920 size_t substitutions = subst.size(); | 916 size_t substitutions = subst.size(); |
| 921 | 917 |
| 922 size_t sub_length = 0; | 918 size_t sub_length = 0; |
| 923 for (typename std::vector<OutStringType>::const_iterator iter = subst.begin(); | 919 for (const auto& cur : subst) |
| 924 iter != subst.end(); ++iter) { | 920 sub_length += cur.length(); |
| 925 sub_length += iter->length(); | |
| 926 } | |
| 927 | 921 |
| 928 OutStringType formatted; | 922 OutStringType formatted; |
| 929 formatted.reserve(format_string.length() + sub_length); | 923 formatted.reserve(format_string.length() + sub_length); |
| 930 | 924 |
| 931 std::vector<ReplacementOffset> r_offsets; | 925 std::vector<ReplacementOffset> r_offsets; |
| 932 for (typename FormatStringType::const_iterator i = format_string.begin(); | 926 for (auto i = format_string.begin(); i != format_string.end(); ++i) { |
| 933 i != format_string.end(); ++i) { | |
| 934 if ('$' == *i) { | 927 if ('$' == *i) { |
| 935 if (i + 1 != format_string.end()) { | 928 if (i + 1 != format_string.end()) { |
| 936 ++i; | 929 ++i; |
| 937 DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i; | 930 DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i; |
| 938 if ('$' == *i) { | 931 if ('$' == *i) { |
| 939 while (i != format_string.end() && '$' == *i) { | 932 while (i != format_string.end() && '$' == *i) { |
| 940 formatted.push_back('$'); | 933 formatted.push_back('$'); |
| 941 ++i; | 934 ++i; |
| 942 } | 935 } |
| 943 --i; | 936 --i; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 961 } | 954 } |
| 962 if (index < substitutions) | 955 if (index < substitutions) |
| 963 formatted.append(subst.at(index)); | 956 formatted.append(subst.at(index)); |
| 964 } | 957 } |
| 965 } | 958 } |
| 966 } else { | 959 } else { |
| 967 formatted.push_back(*i); | 960 formatted.push_back(*i); |
| 968 } | 961 } |
| 969 } | 962 } |
| 970 if (offsets) { | 963 if (offsets) { |
| 971 for (std::vector<ReplacementOffset>::const_iterator i = r_offsets.begin(); | 964 for (const auto& cur : r_offsets) |
| 972 i != r_offsets.end(); ++i) { | 965 offsets->push_back(cur.offset); |
| 973 offsets->push_back(i->offset); | |
| 974 } | |
| 975 } | 966 } |
| 976 return formatted; | 967 return formatted; |
| 977 } | 968 } |
| 978 | 969 |
| 979 string16 ReplaceStringPlaceholders(const string16& format_string, | 970 string16 ReplaceStringPlaceholders(const string16& format_string, |
| 980 const std::vector<string16>& subst, | 971 const std::vector<string16>& subst, |
| 981 std::vector<size_t>* offsets) { | 972 std::vector<size_t>* offsets) { |
| 982 return DoReplaceStringPlaceholders(format_string, subst, offsets); | 973 return DoReplaceStringPlaceholders(format_string, subst, offsets); |
| 983 } | 974 } |
| 984 | 975 |
| 985 std::string ReplaceStringPlaceholders(const base::StringPiece& format_string, | 976 std::string ReplaceStringPlaceholders(const StringPiece& format_string, |
| 986 const std::vector<std::string>& subst, | 977 const std::vector<std::string>& subst, |
| 987 std::vector<size_t>* offsets) { | 978 std::vector<size_t>* offsets) { |
| 988 return DoReplaceStringPlaceholders(format_string, subst, offsets); | 979 return DoReplaceStringPlaceholders(format_string, subst, offsets); |
| 989 } | 980 } |
| 990 | 981 |
| 991 string16 ReplaceStringPlaceholders(const string16& format_string, | 982 string16 ReplaceStringPlaceholders(const string16& format_string, |
| 992 const string16& a, | 983 const string16& a, |
| 993 size_t* offset) { | 984 size_t* offset) { |
| 994 std::vector<size_t> offsets; | 985 std::vector<size_t> offsets; |
| 995 std::vector<string16> subst; | 986 std::vector<string16> subst; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1019 if (dst_size != 0) | 1010 if (dst_size != 0) |
| 1020 dst[dst_size - 1] = 0; | 1011 dst[dst_size - 1] = 0; |
| 1021 | 1012 |
| 1022 // Count the rest of the |src|, and return it's length in characters. | 1013 // Count the rest of the |src|, and return it's length in characters. |
| 1023 while (src[dst_size]) ++dst_size; | 1014 while (src[dst_size]) ++dst_size; |
| 1024 return dst_size; | 1015 return dst_size; |
| 1025 } | 1016 } |
| 1026 | 1017 |
| 1027 } // namespace | 1018 } // namespace |
| 1028 | 1019 |
| 1029 size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { | 1020 size_t strlcpy(char* dst, const char* src, size_t dst_size) { |
| 1030 return lcpyT<char>(dst, src, dst_size); | 1021 return lcpyT<char>(dst, src, dst_size); |
| 1031 } | 1022 } |
| 1032 size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { | 1023 size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { |
| 1033 return lcpyT<wchar_t>(dst, src, dst_size); | 1024 return lcpyT<wchar_t>(dst, src, dst_size); |
| 1034 } | 1025 } |
| 1026 |
| 1027 } // namespace base |
| OLD | NEW |