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