1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdarg.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wchar.h> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wctype.h> 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/utf_string_conversion_utils.h" 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/icu/icu_utf.h" 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "build/build_config.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Remove when this entire file is in the base namespace. 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using base::char16; 31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using base::string16; 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Force the singleton used by EmptyString[16] to be a unique type. This 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prevents other code that might accidentally use Singleton<string> from 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// getting our internal one. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct EmptyStrings { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EmptyStrings() {} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string s; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16 s16; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static EmptyStrings* GetInstance() { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Singleton<EmptyStrings>::get(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used by ReplaceStringPlaceholders to track the position in the string of 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// replaced parameters. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ReplacementOffset { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplacementOffset(uintptr_t parameter, size_t offset) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : parameter(parameter), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset(offset) {} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Index of the parameter. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t parameter; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starting position in the string. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t offset; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool CompareParameter(const ReplacementOffset& elem1, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ReplacementOffset& elem2) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return elem1.parameter < elem2.parameter; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsWprintfFormatPortable(const wchar_t* format) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const wchar_t* position = format; *position != '\0'; ++position) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*position == '%') { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool in_specification = true; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool modifier_l = false; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (in_specification) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Eat up characters until reaching a known specifier. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*++position == '\0') { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The format string ended in the middle of a specification. Call 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it portable because no unportable specifications were found. The 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // string is equally broken on all platforms. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*position == 'l') { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'l' is the only thing that can save the 's' and 'c' specifiers. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) modifier_l = true; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (((*position == 's' || *position == 'c') && !modifier_l) || 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *position == 'S' || *position == 'C' || *position == 'F' || 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *position == 'D' || *position == 'O' || *position == 'U') { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not portable. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wcschr(L"diouxXeEfgGaAcspn%", *position)) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Portable, keep scanning the rest of the format string. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_specification = false; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& EmptyString() { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EmptyStrings::GetInstance()->s; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const string16& EmptyString16() { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EmptyStrings::GetInstance()->s16; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename STR> 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReplaceCharsT(const STR& input, 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const STR& replace_chars, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const STR& replace_with, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STR* output) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool removed = false; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t replace_length = replace_with.length(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output = input; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t found = output->find_first_of(replace_chars); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (found != STR::npos) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) removed = true; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->replace(found, 1, replace_with); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = output->find_first_of(replace_chars, found + replace_length); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return removed; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReplaceChars(const string16& input, 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::StringPiece16& replace_chars, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& replace_with, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16* output) { 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReplaceChars(const std::string& input, 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::StringPiece& replace_chars, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& replace_with, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ReplaceCharsT(input, replace_chars.as_string(), replace_with, output); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RemoveChars(const string16& input, 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::StringPiece16& remove_chars, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16* output) { 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ReplaceChars(input, remove_chars.as_string(), string16(), output); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RemoveChars(const std::string& input, 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::StringPiece& remove_chars, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return ReplaceChars(input, remove_chars.as_string(), std::string(), output); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename STR> 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TrimPositions TrimStringT(const STR& input, 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const STR& trim_chars, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimPositions positions, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STR* output) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the edges of leading/trailing whitespace as desired. 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t last_char = input.length() - 1; 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t first_good_char = (positions & TRIM_LEADING) ? 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input.find_first_not_of(trim_chars) : 0; 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t last_good_char = (positions & TRIM_TRAILING) ? 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input.find_last_not_of(trim_chars) : last_char; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the string was all whitespace, report that we stripped off whitespace 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from whichever position the caller was interested in. For empty input, we 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stripped no whitespace, but we still need to clear |output|. 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (input.empty() || 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (first_good_char == STR::npos) || (last_good_char == STR::npos)) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool input_was_empty = input.empty(); // in case output == &input 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->clear(); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return input_was_empty ? TRIM_NONE : positions; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Trim the whitespace. 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output = 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input.substr(first_good_char, last_good_char - first_good_char + 1); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return where we trimmed from. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<TrimPositions>( 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrimString(const string16& input, 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::StringPiece16& trim_chars, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16* output) { 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRIM_NONE; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TrimString(const std::string& input, 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const base::StringPiece& trim_chars, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return TrimStringT(input, trim_chars.as_string(), TRIM_ALL, output) != 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TRIM_NONE; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TruncateUTF8ToByteSize(const std::string& input, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t byte_size, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(output); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (byte_size > input.length()) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output = input; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(byte_size, static_cast<uint32>(kint32max)); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: This cast is necessary because CBU8_NEXT uses int32s. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 truncation_length = static_cast<int32>(byte_size); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 char_index = truncation_length - 1; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data = input.data(); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using CBU8, we will move backwards from the truncation point 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the beginning of the string looking for a valid UTF8 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // character. Once a full UTF8 character is found, we will 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // truncate the string to the end of that character. 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (char_index >= 0) { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 prev = char_index; 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base_icu::UChar32 code_point = 0; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CBU8_NEXT(data, char_index, truncation_length, code_point); 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!IsValidCharacter(code_point) || 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !IsValidCodepoint(code_point)) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char_index = prev - 1; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (char_index >= 0 ) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *output = input.substr(0, char_index); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->clear(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TrimPositions TrimWhitespace(const string16& input, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimPositions positions, 244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) string16* output) { 245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return TrimStringT(input, base::string16(kWhitespaceUTF16), positions, 246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) output); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TrimPositions TrimWhitespaceASCII(const std::string& input, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimPositions positions, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return TrimStringT(input, std::string(kWhitespaceASCII), positions, output); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function is only for backward-compatibility. 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To be removed when all callers are updated. 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TrimPositions TrimWhitespace(const std::string& input, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimPositions positions, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* output) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TrimWhitespaceASCII(input, positions, output); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename STR> 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)STR CollapseWhitespaceT(const STR& text, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool trim_sequences_with_line_breaks) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STR result; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.resize(text.size()); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set flags to pretend we're already in a trimmed whitespace sequence, so we 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will trim any leading whitespace. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool in_whitespace = true; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool already_trimmed = true; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int chars_written = 0; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (typename STR::const_iterator i(text.begin()); i != text.end(); ++i) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsWhitespace(*i)) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!in_whitespace) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reduce all whitespace sequences to a single space. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_whitespace = true; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result[chars_written++] = L' '; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trim_sequences_with_line_breaks && !already_trimmed && 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((*i == '\n') || (*i == '\r'))) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whitespace sequences containing CR or LF are eliminated entirely. 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) already_trimmed = true; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --chars_written; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-whitespace chracters are copied straight across. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_whitespace = false; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) already_trimmed = false; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result[chars_written++] = *i; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in_whitespace && !already_trimmed) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any trailing whitespace is eliminated. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --chars_written; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.resize(chars_written); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 CollapseWhitespace(const string16& text, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool trim_sequences_with_line_breaks) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CollapseWhitespaceASCII(const std::string& text, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool trim_sequences_with_line_breaks) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ContainsOnlyChars(const StringPiece& input, 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const StringPiece& characters) { 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return input.find_first_not_of(characters) == StringPiece::npos; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ContainsOnlyChars(const StringPiece16& input, 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const StringPiece16& characters) { 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return input.find_first_not_of(characters) == StringPiece16::npos; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class STR> 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool DoIsStringASCII(const STR& str) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < str.length(); i++) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename ToUnsigned<typename STR::value_type>::Unsigned c = str[i]; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c > 0x7F) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool IsStringASCII(const StringPiece& str) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoIsStringASCII(str); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 339010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool IsStringASCII(const string16& str) { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoIsStringASCII(str); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsStringUTF8(const std::string& str) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *src = str.data(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 src_len = static_cast<int32>(str.length()); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 char_index = 0; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (char_index < src_len) { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 code_point; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CBU8_NEXT(src, char_index, src_len, code_point); 351010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!IsValidCharacter(code_point)) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 357010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace base 358010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename Iter> 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline bool DoLowerCaseEqualsASCII(Iter a_begin, 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Iter a_end, 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* b) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (Iter it = a_begin; it != a_end; ++it, ++b) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!*b || base::ToLowerASCII(*it) != *b) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *b == 0; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Front-ends for LowerCaseEqualsASCII. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LowerCaseEqualsASCII(const std::string& a, const char* b) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LowerCaseEqualsASCII(const string16& a, const char* b) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LowerCaseEqualsASCII(std::string::const_iterator a_begin, 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string::const_iterator a_end, 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* b) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoLowerCaseEqualsASCII(a_begin, a_end, b); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LowerCaseEqualsASCII(string16::const_iterator a_begin, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16::const_iterator a_end, 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* b) { 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoLowerCaseEqualsASCII(a_begin, a_end, b); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(port): Resolve wchar_t/iterator issues that require OS_ANDROID here. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_ANDROID) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LowerCaseEqualsASCII(const char* a_begin, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* a_end, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* b) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoLowerCaseEqualsASCII(a_begin, a_end, b); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LowerCaseEqualsASCII(const char16* a_begin, 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char16* a_end, 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* b) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoLowerCaseEqualsASCII(a_begin, a_end, b); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(OS_ANDROID) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EqualsASCII(const string16& a, const base::StringPiece& b) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (a.length() != b.length()) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::equal(b.begin(), b.end(), a.begin()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StartsWithASCII(const std::string& str, 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& search, 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool case_sensitive) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (case_sensitive) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return str.compare(0, search.length(), search) == 0; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::strncasecmp(str.c_str(), search.c_str(), search.length()) == 0; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename STR> 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StartsWithT(const STR& str, const STR& search, bool case_sensitive) { 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (case_sensitive) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return str.compare(0, search.length(), search) == 0; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (search.size() > str.size()) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::equal(search.begin(), search.end(), str.begin(), 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CaseInsensitiveCompare<typename STR::value_type>()); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool StartsWith(const string16& str, const string16& search, 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool case_sensitive) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return StartsWithT(str, search, case_sensitive); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename STR> 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EndsWithT(const STR& str, const STR& search, bool case_sensitive) { 441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t str_length = str.length(); 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t search_length = search.length(); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (search_length > str_length) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (case_sensitive) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return str.compare(str_length - search_length, search_length, search) == 0; 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return std::equal(search.begin(), search.end(), 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) str.begin() + (str_length - search_length), 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CaseInsensitiveCompare<typename STR::value_type>()); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EndsWith(const std::string& str, const std::string& search, 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool case_sensitive) { 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EndsWithT(str, search, case_sensitive); 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool EndsWith(const string16& str, const string16& search, 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool case_sensitive) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return EndsWithT(str, search, case_sensitive); 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* const kByteStringsUnlocalized[] = { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " B", 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " kB", 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " MB", 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " GB", 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " TB", 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " PB" 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 FormatBytesUnlocalized(int64 bytes) { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double unit_amount = static_cast<double>(bytes); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t dimension = 0; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kKilo = 1024; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (unit_amount >= kKilo && 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dimension < arraysize(kByteStringsUnlocalized) - 1) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unit_amount /= kKilo; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dimension++; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[64]; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes != 0 && dimension > 0 && unit_amount < 100) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::snprintf(buf, arraysize(buf), "%.1lf%s", unit_amount, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kByteStringsUnlocalized[dimension]); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::snprintf(buf, arraysize(buf), "%.0lf%s", unit_amount, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kByteStringsUnlocalized[dimension]); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::ASCIIToUTF16(buf); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class StringType> 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DoReplaceSubstringsAfterOffset(StringType* str, 495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t start_offset, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StringType& find_this, 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const StringType& replace_with, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool replace_all) { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((start_offset == StringType::npos) || (start_offset >= str->length())) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!find_this.empty()); 503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (size_t offs(str->find(find_this, start_offset)); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offs != StringType::npos; offs = str->find(find_this, offs)) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str->replace(offs, find_this.length(), replace_with); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offs += replace_with.length(); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!replace_all) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReplaceFirstSubstringAfterOffset(string16* str, 514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t start_offset, 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& find_this, 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& replace_with) { 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); // replace first instance 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReplaceFirstSubstringAfterOffset(std::string* str, 522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t start_offset, 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& find_this, 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& replace_with) { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false); // replace first instance 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReplaceSubstringsAfterOffset(string16* str, 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t start_offset, 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& find_this, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& replace_with) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); // replace all instances 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReplaceSubstringsAfterOffset(std::string* str, 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t start_offset, 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& find_this, 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& replace_with) { 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); // replace all instances 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename STR> 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static size_t TokenizeT(const STR& str, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const STR& delimiters, 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<STR>* tokens) { 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tokens->clear(); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t start = str.find_first_not_of(delimiters); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (start != STR::npos) { 554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t end = str.find_first_of(delimiters, start + 1); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (end == STR::npos) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tokens->push_back(str.substr(start)); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tokens->push_back(str.substr(start, end - start)); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = str.find_first_not_of(delimiters, end + 1); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tokens->size(); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Tokenize(const string16& str, 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& delimiters, 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<string16>* tokens) { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TokenizeT(str, delimiters, tokens); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Tokenize(const std::string& str, 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& delimiters, 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string>* tokens) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TokenizeT(str, delimiters, tokens); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t Tokenize(const base::StringPiece& str, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& delimiters, 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<base::StringPiece>* tokens) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TokenizeT(str, delimiters, tokens); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename STR> 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static STR JoinStringT(const std::vector<STR>& parts, const STR& sep) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parts.empty()) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return STR(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STR result(parts[0]); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename std::vector<STR>::const_iterator iter = parts.begin(); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter; 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; iter != parts.end(); ++iter) { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += sep; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result += *iter; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string JoinString(const std::vector<std::string>& parts, char sep) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return JoinStringT(parts, std::string(1, sep)); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 JoinString(const std::vector<string16>& parts, char16 sep) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return JoinStringT(parts, string16(1, sep)); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string JoinString(const std::vector<std::string>& parts, 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& separator) { 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return JoinStringT(parts, separator); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 JoinString(const std::vector<string16>& parts, 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& separator) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return JoinStringT(parts, separator); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class FormatStringType, class OutStringType> 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string, 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<OutStringType>& subst, std::vector<size_t>* offsets) { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t substitutions = subst.size(); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t sub_length = 0; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (typename std::vector<OutStringType>::const_iterator iter = subst.begin(); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != subst.end(); ++iter) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sub_length += iter->length(); 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OutStringType formatted; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formatted.reserve(format_string.length() + sub_length); 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ReplacementOffset> r_offsets; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (typename FormatStringType::const_iterator i = format_string.begin(); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != format_string.end(); ++i) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ('$' == *i) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i + 1 != format_string.end()) { 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ('$' == *i) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (i != format_string.end() && '$' == *i) { 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formatted.push_back('$'); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --i; 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t index = 0; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (i != format_string.end() && '0' <= *i && *i <= '9') { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index *= 10; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index += *i - '0'; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --i; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index -= 1; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (offsets) { 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplacementOffset r_offset(index, 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(formatted.size())); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r_offsets.insert(std::lower_bound(r_offsets.begin(), 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r_offsets.end(), 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r_offset, 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &CompareParameter), 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r_offset); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < substitutions) 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formatted.append(subst.at(index)); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) formatted.push_back(*i); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (offsets) { 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<ReplacementOffset>::const_iterator i = r_offsets.begin(); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != r_offsets.end(); ++i) { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offsets->push_back(i->offset); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return formatted; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 ReplaceStringPlaceholders(const string16& format_string, 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<string16>& subst, 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t>* offsets) { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoReplaceStringPlaceholders(format_string, subst, offsets); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ReplaceStringPlaceholders(const base::StringPiece& format_string, 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<std::string>& subst, 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t>* offsets) { 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return DoReplaceStringPlaceholders(format_string, subst, offsets); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 ReplaceStringPlaceholders(const string16& format_string, 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& a, 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* offset) { 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<size_t> offsets; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<string16> subst; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subst.push_back(a); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 result = ReplaceStringPlaceholders(format_string, subst, &offsets); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_EQ(1U, offsets.size()); 703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (offset) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *offset = offsets[0]; 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsWildcard(base_icu::UChar32 character) { 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return character == '*' || character == '?'; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Move the strings pointers to the point where they start to differ. 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename CHAR, typename NEXT> 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void EatSameChars(const CHAR** pattern, const CHAR* pattern_end, 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CHAR** string, const CHAR* string_end, 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEXT next) { 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CHAR* escape = NULL; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*pattern != pattern_end && *string != string_end) { 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!escape && IsWildcard(**pattern)) { 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to match wildcard here, except if it's escaped. 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the escapement char is found. If so, skip it and move to the 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // next character. 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!escape && **pattern == '\\') { 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) escape = *pattern; 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next(pattern, pattern_end); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if the chars match, if so, increment the ptrs. 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CHAR* pattern_next = *pattern; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CHAR* string_next = *string; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_icu::UChar32 pattern_char = next(&pattern_next, pattern_end); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pattern_char == next(&string_next, string_end) && 737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pattern_char != CBU_SENTINEL) { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pattern = pattern_next; 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *string = string_next; 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 741116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Uh oh, it did not match, we are done. If the last char was an 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // escapement, that means that it was an error to advance the ptr here, 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // let's put it back where it was. This also mean that the MatchPattern 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function will return false because if we can't match an escape char 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // here, then no one will. 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (escape) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pattern = escape; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) escape = NULL; 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename CHAR, typename NEXT> 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void EatWildcard(const CHAR** pattern, const CHAR* end, NEXT next) { 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*pattern != end) { 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsWildcard(**pattern)) 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next(pattern, end); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename CHAR, typename NEXT> 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool MatchPatternT(const CHAR* eval, const CHAR* eval_end, 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CHAR* pattern, const CHAR* pattern_end, 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int depth, 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NEXT next) { 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMaxDepth = 16; 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (depth > kMaxDepth) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Eat all the matching chars. 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EatSameChars(&pattern, pattern_end, &eval, eval_end, next); 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the string is empty, then the pattern must be empty too, or contains 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only wildcards. 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (eval == eval_end) { 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EatWildcard(&pattern, pattern_end, next); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return pattern == pattern_end; 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pattern is empty but not string, this is not a match. 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pattern == pattern_end) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is a question mark, then we need to compare the rest with 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the current string or the string with one character eaten. 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CHAR* next_pattern = pattern; 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next(&next_pattern, pattern_end); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pattern[0] == '?') { 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth + 1, next)) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CHAR* next_eval = eval; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next(&next_eval, eval_end); 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MatchPatternT(next_eval, eval_end, next_pattern, pattern_end, 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth + 1, next)) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is a *, try to match all the possible substrings with the remainder 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the pattern. 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pattern[0] == '*') { 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Collapse duplicate wild cards (********** into *) so that the 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // method does not recurse unnecessarily. http://crbug.com/52839 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EatWildcard(&next_pattern, pattern_end, next); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (eval != eval_end) { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth + 1, next)) 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eval++; 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We reached the end of the string, let see if the pattern contains only 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wildcards. 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (eval == eval_end) { 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EatWildcard(&pattern, pattern_end, next); 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pattern != pattern_end) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct NextCharUTF8 { 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_icu::UChar32 operator()(const char** p, const char* end) { 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_icu::UChar32 c; 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset = 0; 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CBU8_NEXT(*p, offset, end - *p, c); 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p += offset; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return c; 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct NextCharUTF16 { 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_icu::UChar32 operator()(const char16** p, const char16* end) { 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_icu::UChar32 c; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset = 0; 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CBU16_NEXT(*p, offset, end - *p, c); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p += offset; 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return c; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MatchPattern(const base::StringPiece& eval, 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& pattern) { 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MatchPatternT(eval.data(), eval.data() + eval.size(), 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pattern.data(), pattern.data() + pattern.size(), 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, NextCharUTF8()); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MatchPattern(const string16& eval, const string16& pattern) { 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MatchPatternT(eval.c_str(), eval.c_str() + eval.size(), 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pattern.c_str(), pattern.c_str() + pattern.size(), 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, NextCharUTF16()); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following code is compatible with the OpenBSD lcpy interface. See: 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://www.gratisoft.us/todd/papers/strlcpy.html 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename CHAR> 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < dst_size; ++i) { 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We were left off at dst_size. We over copied 1 byte. Null terminate. 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dst_size != 0) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst[dst_size - 1] = 0; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Count the rest of the |src|, and return it's length in characters. 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (src[dst_size]) ++dst_size; 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dst_size; 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t base::strlcpy(char* dst, const char* src, size_t dst_size) { 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lcpyT<char>(dst, src, dst_size); 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return lcpyT<wchar_t>(dst, src, dst_size); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 893