1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "build/build_config.h" 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <ctype.h> 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <math.h> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdarg.h> 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdio.h> 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h> 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string.h> 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <time.h> 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <wchar.h> 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <wctype.h> 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm> 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector> 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h" 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/third_party/dmg_fp/dmg_fp.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversion_utils.h" 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/third_party/icu/icu_utf.h" 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Force the singleton used by Empty[W]String[16] to be a unique type. This 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// prevents other code that might accidentally use Singleton<string> from 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// getting our internal one. 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct EmptyStrings { 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EmptyStrings() {} 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string s; 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::wstring ws; 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16 s16; 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static EmptyStrings* GetInstance() { 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return Singleton<EmptyStrings>::get(); 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Used by ReplaceStringPlaceholders to track the position in the string of 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// replaced parameters. 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct ReplacementOffset { 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ReplacementOffset(uintptr_t parameter, size_t offset) 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : parameter(parameter), 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset(offset) {} 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Index of the parameter. 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uintptr_t parameter; 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Starting position in the string. 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t offset; 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic bool CompareParameter(const ReplacementOffset& elem1, 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const ReplacementOffset& elem2) { 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return elem1.parameter < elem2.parameter; 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool IsWprintfFormatPortable(const wchar_t* format) { 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (const wchar_t* position = format; *position != '\0'; ++position) { 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*position == '%') { 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool in_specification = true; 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool modifier_l = false; 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (in_specification) { 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Eat up characters until reaching a known specifier. 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*++position == '\0') { 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The format string ended in the middle of a specification. Call 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // it portable because no unportable specifications were found. The 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // string is equally broken on all platforms. 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*position == 'l') { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 'l' is the only thing that can save the 's' and 'c' specifiers. 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott modifier_l = true; 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (((*position == 's' || *position == 'c') && !modifier_l) || 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *position == 'S' || *position == 'C' || *position == 'F' || 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *position == 'D' || *position == 'O' || *position == 'U') { 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not portable. 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (wcschr(L"diouxXeEfgGaAcspn%", *position)) { 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Portable, keep scanning the rest of the format string. 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_specification = false; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string& EmptyString() { 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return EmptyStrings::GetInstance()->s; 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::wstring& EmptyWString() { 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return EmptyStrings::GetInstance()->ws; 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst string16& EmptyString16() { 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return EmptyStrings::GetInstance()->s16; 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define WHITESPACE_UNICODE \ 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x0009, /* <control-0009> to <control-000D> */ \ 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x000A, \ 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x000B, \ 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x000C, \ 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x000D, \ 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x0020, /* Space */ \ 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x0085, /* <control-0085> */ \ 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x00A0, /* No-Break Space */ \ 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x1680, /* Ogham Space Mark */ \ 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x180E, /* Mongolian Vowel Separator */ \ 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2000, /* En Quad to Hair Space */ \ 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2001, \ 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2002, \ 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2003, \ 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2004, \ 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2005, \ 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2006, \ 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2007, \ 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2008, \ 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2009, \ 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x200A, \ 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x200C, /* Zero Width Non-Joiner */ \ 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2028, /* Line Separator */ \ 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x2029, /* Paragraph Separator */ \ 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x202F, /* Narrow No-Break Space */ \ 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x205F, /* Medium Mathematical Space */ \ 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x3000, /* Ideographic Space */ \ 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst wchar_t kWhitespaceWide[] = { 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WHITESPACE_UNICODE 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char16 kWhitespaceUTF16[] = { 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WHITESPACE_UNICODE 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kWhitespaceASCII[] = { 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x09, // <control-0009> to <control-000D> 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x0A, 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x0B, 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x0C, 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x0D, 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0x20, // Space 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kUtf8ByteOrderMark[] = "\xEF\xBB\xBF"; 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<typename STR> 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveCharsT(const STR& input, 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const typename STR::value_type remove_chars[], 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STR* output) { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool removed = false; 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t found; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *output = input; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch found = output->find_first_of(remove_chars); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (found != STR::npos) { 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch removed = true; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->replace(found, 1, STR()); 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch found = output->find_first_of(remove_chars, found); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return removed; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveChars(const std::wstring& input, 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const wchar_t remove_chars[], 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring* output) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RemoveCharsT(input, remove_chars, output); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if !defined(WCHAR_T_IS_UTF16) 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveChars(const string16& input, 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char16 remove_chars[], 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string16* output) { 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RemoveCharsT(input, remove_chars, output); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool RemoveChars(const std::string& input, 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char remove_chars[], 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* output) { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return RemoveCharsT(input, remove_chars, output); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate<typename STR> 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTrimPositions TrimStringT(const STR& input, 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const typename STR::value_type trim_chars[], 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrimPositions positions, 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott STR* output) { 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Find the edges of leading/trailing whitespace as desired. 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const typename STR::size_type last_char = input.length() - 1; 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const typename STR::size_type first_good_char = (positions & TRIM_LEADING) ? 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott input.find_first_not_of(trim_chars) : 0; 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const typename STR::size_type last_good_char = (positions & TRIM_TRAILING) ? 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott input.find_last_not_of(trim_chars) : last_char; 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // When the string was all whitespace, report that we stripped off whitespace 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // from whichever position the caller was interested in. For empty input, we 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // stripped no whitespace, but we still need to clear |output|. 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (input.empty() || 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (first_good_char == STR::npos) || (last_good_char == STR::npos)) { 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool input_was_empty = input.empty(); // in case output == &input 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->clear(); 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return input_was_empty ? TRIM_NONE : positions; 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Trim the whitespace. 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *output = 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott input.substr(first_good_char, last_good_char - first_good_char + 1); 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Return where we trimmed from. 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return static_cast<TrimPositions>( 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TrimString(const std::wstring& input, 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const wchar_t trim_chars[], 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring* output) { 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TrimString(const string16& input, 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char16 trim_chars[], 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string16* output) { 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool TrimString(const std::string& input, 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char trim_chars[], 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* output) { 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TruncateUTF8ToByteSize(const std::string& input, 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t byte_size, 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* output) { 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(output); 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (byte_size > input.length()) { 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *output = input; 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_LE(byte_size, static_cast<uint32>(kint32max)); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: This cast is necessary because CBU8_NEXT uses int32s. 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 truncation_length = static_cast<int32>(byte_size); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 char_index = truncation_length - 1; 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data = input.data(); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Using CBU8, we will move backwards from the truncation point 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the beginning of the string looking for a valid UTF8 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // character. Once a full UTF8 character is found, we will 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // truncate the string to the end of that character. 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (char_index >= 0) { 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 prev = char_index; 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint32 code_point = 0; 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CBU8_NEXT(data, char_index, truncation_length, code_point); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!base::IsValidCharacter(code_point) || 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !base::IsValidCodepoint(code_point)) { 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch char_index = prev - 1; 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (char_index >= 0 ) 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *output = input.substr(0, char_index); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->clear(); 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTrimPositions TrimWhitespace(const std::wstring& input, 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrimPositions positions, 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring* output) { 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TrimStringT(input, kWhitespaceWide, positions, output); 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTrimPositions TrimWhitespace(const string16& input, 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrimPositions positions, 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string16* output) { 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TrimStringT(input, kWhitespaceUTF16, positions, output); 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTrimPositions TrimWhitespaceASCII(const std::string& input, 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrimPositions positions, 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* output) { 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TrimStringT(input, kWhitespaceASCII, positions, output); 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This function is only for backward-compatibility. 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// To be removed when all callers are updated. 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTrimPositions TrimWhitespace(const std::string& input, 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrimPositions positions, 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* output) { 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TrimWhitespaceASCII(input, positions, output); 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<typename STR> 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSTR CollapseWhitespaceT(const STR& text, 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool trim_sequences_with_line_breaks) { 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott STR result; 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.resize(text.size()); 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set flags to pretend we're already in a trimmed whitespace sequence, so we 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // will trim any leading whitespace. 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool in_whitespace = true; 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool already_trimmed = true; 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int chars_written = 0; 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (typename STR::const_iterator i(text.begin()); i != text.end(); ++i) { 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsWhitespace(*i)) { 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!in_whitespace) { 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reduce all whitespace sequences to a single space. 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_whitespace = true; 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result[chars_written++] = L' '; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (trim_sequences_with_line_breaks && !already_trimmed && 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ((*i == '\n') || (*i == '\r'))) { 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Whitespace sequences containing CR or LF are eliminated entirely. 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott already_trimmed = true; 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --chars_written; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Non-whitespace chracters are copied straight across. 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_whitespace = false; 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott already_trimmed = false; 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result[chars_written++] = *i; 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (in_whitespace && !already_trimmed) { 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Any trailing whitespace is eliminated. 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --chars_written; 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result.resize(chars_written); 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::wstring CollapseWhitespace(const std::wstring& text, 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool trim_sequences_with_line_breaks) { 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstring16 CollapseWhitespace(const string16& text, 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool trim_sequences_with_line_breaks) { 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string CollapseWhitespaceASCII(const std::string& text, 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool trim_sequences_with_line_breaks) { 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CollapseWhitespaceT(text, trim_sequences_with_line_breaks); 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ContainsOnlyWhitespaceASCII(const std::string& str) { 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (std::string::const_iterator i(str.begin()); i != str.end(); ++i) { 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsAsciiWhitespace(*i)) 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ContainsOnlyWhitespace(const string16& str) { 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (string16::const_iterator i(str.begin()); i != str.end(); ++i) { 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsWhitespace(*i)) 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtemplate<typename STR> 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool ContainsOnlyCharsT(const STR& input, const STR& characters) { 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (typename STR::const_iterator iter = input.begin(); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter != input.end(); ++iter) { 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (characters.find(*iter) == STR::npos) 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ContainsOnlyChars(const std::wstring& input, 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::wstring& characters) { 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ContainsOnlyCharsT(input, characters); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if !defined(WCHAR_T_IS_UTF16) 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ContainsOnlyChars(const string16& input, const string16& characters) { 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ContainsOnlyCharsT(input, characters); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ContainsOnlyChars(const std::string& input, 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& characters) { 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ContainsOnlyCharsT(input, characters); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string WideToASCII(const std::wstring& wide) { 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(IsStringASCII(wide)) << wide; 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string(wide.begin(), wide.end()); 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string UTF16ToASCII(const string16& utf16) { 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(IsStringASCII(utf16)) << utf16; 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string(utf16.begin(), utf16.end()); 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Latin1 is just the low range of Unicode, so we can copy directly to convert. 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool WideToLatin1(const std::wstring& wide, std::string* latin1) { 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string output; 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output.resize(wide.size()); 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott latin1->clear(); 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < wide.size(); i++) { 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (wide[i] > 255) 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output[i] = static_cast<char>(wide[i]); 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott latin1->swap(output); 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<class STR> 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic bool DoIsStringASCII(const STR& str) { 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < str.length(); i++) { 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename ToUnsigned<typename STR::value_type>::Unsigned c = str[i]; 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (c > 0x7F) 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool IsStringASCII(const std::wstring& str) { 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoIsStringASCII(str); 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool IsStringASCII(const string16& str) { 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoIsStringASCII(str); 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool IsStringASCII(const base::StringPiece& str) { 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoIsStringASCII(str); 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsStringUTF8(const std::string& str) { 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char *src = str.data(); 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 src_len = static_cast<int32>(str.length()); 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 char_index = 0; 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (char_index < src_len) { 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int32 code_point; 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CBU8_NEXT(src, char_index, src_len, code_point); 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!base::IsValidCharacter(code_point)) 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<typename Iter> 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic inline bool DoLowerCaseEqualsASCII(Iter a_begin, 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Iter a_end, 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* b) { 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (Iter it = a_begin; it != a_end; ++it, ++b) { 491513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (!*b || base::ToLowerASCII(*it) != *b) 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return *b == 0; 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Front-ends for LowerCaseEqualsASCII. 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(const std::string& a, const char* b) { 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(const std::wstring& a, const char* b) { 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(const string16& a, const char* b) { 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a.begin(), a.end(), b); 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(std::string::const_iterator a_begin, 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator a_end, 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* b) { 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a_begin, a_end, b); 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(std::wstring::const_iterator a_begin, 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring::const_iterator a_end, 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* b) { 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a_begin, a_end, b); 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(string16::const_iterator a_begin, 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string16::const_iterator a_end, 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* b) { 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a_begin, a_end, b); 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#if !defined(ANDROID) 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(const char* a_begin, 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* a_end, 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* b) { 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a_begin, a_end, b); 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 53800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#endif // !ANDROID 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 54000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#if !defined(ANDROID) 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(const wchar_t* a_begin, 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const wchar_t* a_end, 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* b) { 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a_begin, a_end, b); 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 54600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#endif // !ANDROID 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 54800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#if !defined(WCHAR_T_IS_UTF16) && !defined(ANDROID) 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool LowerCaseEqualsASCII(const char16* a_begin, 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char16* a_end, 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* b) { 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoLowerCaseEqualsASCII(a_begin, a_end, b); 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EqualsASCII(const string16& a, const base::StringPiece& b) { 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (a.length() != b.length()) 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::equal(b.begin(), b.end(), a.begin()); 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool StartsWithASCII(const std::string& str, 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& search, 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool case_sensitive) { 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (case_sensitive) 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return str.compare(0, search.length(), search) == 0; 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott else 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return base::strncasecmp(str.c_str(), search.c_str(), search.length()) == 0; 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename STR> 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool StartsWithT(const STR& str, const STR& search, bool case_sensitive) { 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (case_sensitive) { 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return str.compare(0, search.length(), search) == 0; 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (search.size() > str.size()) 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::equal(search.begin(), search.end(), str.begin(), 579513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::CaseInsensitiveCompare<typename STR::value_type>()); 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool StartsWith(const std::wstring& str, const std::wstring& search, 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool case_sensitive) { 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return StartsWithT(str, search, case_sensitive); 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool StartsWith(const string16& str, const string16& search, 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool case_sensitive) { 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return StartsWithT(str, search, case_sensitive); 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename STR> 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EndsWithT(const STR& str, const STR& search, bool case_sensitive) { 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename STR::size_type str_length = str.length(); 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename STR::size_type search_length = search.length(); 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (search_length > str_length) 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (case_sensitive) { 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return str.compare(str_length - search_length, search_length, search) == 0; 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::equal(search.begin(), search.end(), 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott str.begin() + (str_length - search_length), 606513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::CaseInsensitiveCompare<typename STR::value_type>()); 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EndsWith(const std::string& str, const std::string& search, 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool case_sensitive) { 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return EndsWithT(str, search, case_sensitive); 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EndsWith(const std::wstring& str, const std::wstring& search, 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool case_sensitive) { 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return EndsWithT(str, search, case_sensitive); 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EndsWith(const string16& str, const string16& search, 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool case_sensitive) { 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return EndsWithT(str, search, case_sensitive); 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottDataUnits GetByteDisplayUnits(int64 bytes) { 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The byte thresholds at which we display amounts. A byte count is displayed 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1]. 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This must match the DataUnits enum. 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static const int64 kUnitThresholds[] = { 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, // DATA_UNITS_BYTE, 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3*1024, // DATA_UNITS_KIBIBYTE, 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2*1024*1024, // DATA_UNITS_MEBIBYTE, 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1024*1024*1024 // DATA_UNITS_GIBIBYTE, 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott }; 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes < 0) { 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "Negative bytes value"; 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DATA_UNITS_BYTE; 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int unit_index = arraysize(kUnitThresholds); 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (--unit_index > 0) { 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes >= kUnitThresholds[unit_index]) 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(unit_index >= DATA_UNITS_BYTE && unit_index <= DATA_UNITS_GIBIBYTE); 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DataUnits(unit_index); 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(mpcomplete): deal with locale 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Byte suffixes. This must match the DataUnits enum. 6553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const char* const kByteStrings[] = { 6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "B", 6573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "kB", 6583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "MB", 6593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "GB" 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic const char* const kSpeedStrings[] = { 6633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "B/s", 6643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "kB/s", 6653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "MB/s", 6663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "GB/s" 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstring16 FormatBytesInternal(int64 bytes, 6703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DataUnits units, 6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool show_units, 6723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* const* suffix) { 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes < 0) { 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "Negative bytes value"; 6753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return string16(); 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(units >= DATA_UNITS_BYTE && units <= DATA_UNITS_GIBIBYTE); 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Put the quantity in the right units. 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott double unit_amount = static_cast<double>(bytes); 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < units; ++i) 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unit_amount /= 1024.0; 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick char buf[64]; 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes != 0 && units != DATA_UNITS_BYTE && unit_amount < 100) 6873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::snprintf(buf, arraysize(buf), "%.1lf", unit_amount); 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 6893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::snprintf(buf, arraysize(buf), "%.0lf", unit_amount); 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string ret(buf); 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (show_units) { 6933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ret += " "; 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ret += suffix[units]; 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return ASCIIToUTF16(ret); 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstring16 FormatBytes(int64 bytes, DataUnits units, bool show_units) { 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return FormatBytesInternal(bytes, units, show_units, kByteStrings); 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstring16 FormatSpeed(int64 bytes, DataUnits units, bool show_units) { 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return FormatBytesInternal(bytes, units, show_units, kSpeedStrings); 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<class StringType> 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid DoReplaceSubstringsAfterOffset(StringType* str, 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename StringType::size_type start_offset, 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const StringType& find_this, 712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const StringType& replace_with, 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool replace_all) { 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((start_offset == StringType::npos) || (start_offset >= str->length())) 715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!find_this.empty()); 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (typename StringType::size_type offs(str->find(find_this, start_offset)); 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offs != StringType::npos; offs = str->find(find_this, offs)) { 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott str->replace(offs, find_this.length(), replace_with); 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offs += replace_with.length(); 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!replace_all) 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ReplaceFirstSubstringAfterOffset(string16* str, 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string16::size_type start_offset, 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16& find_this, 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16& replace_with) { 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott false); // replace first instance 734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ReplaceFirstSubstringAfterOffset(std::string* str, 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::size_type start_offset, 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& find_this, 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& replace_with) { 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott false); // replace first instance 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ReplaceSubstringsAfterOffset(string16* str, 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string16::size_type start_offset, 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16& find_this, 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16& replace_with) { 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true); // replace all instances 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ReplaceSubstringsAfterOffset(std::string* str, 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::size_type start_offset, 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& find_this, 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& replace_with) { 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with, 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true); // replace all instances 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<typename STR> 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic size_t TokenizeT(const STR& str, 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const STR& delimiters, 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<STR>* tokens) { 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tokens->clear(); 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename STR::size_type start = str.find_first_not_of(delimiters); 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (start != STR::npos) { 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename STR::size_type end = str.find_first_of(delimiters, start + 1); 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end == STR::npos) { 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tokens->push_back(str.substr(start)); 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tokens->push_back(str.substr(start, end - start)); 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott start = str.find_first_not_of(delimiters, end + 1); 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return tokens->size(); 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t Tokenize(const std::wstring& str, 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::wstring& delimiters, 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<std::wstring>* tokens) { 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TokenizeT(str, delimiters, tokens); 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if !defined(WCHAR_T_IS_UTF16) 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t Tokenize(const string16& str, 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16& delimiters, 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<string16>* tokens) { 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TokenizeT(str, delimiters, tokens); 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t Tokenize(const std::string& str, 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& delimiters, 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<std::string>* tokens) { 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TokenizeT(str, delimiters, tokens); 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsize_t Tokenize(const base::StringPiece& str, 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const base::StringPiece& delimiters, 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<base::StringPiece>* tokens) { 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return TokenizeT(str, delimiters, tokens); 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<typename STR> 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic STR JoinStringT(const std::vector<STR>& parts, 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename STR::value_type sep) { 811dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (parts.empty()) 812dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return STR(); 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott STR result(parts[0]); 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typename std::vector<STR>::const_iterator iter = parts.begin(); 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++iter; 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; iter != parts.end(); ++iter) { 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result += sep; 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result += *iter; 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string JoinString(const std::vector<std::string>& parts, char sep) { 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return JoinStringT(parts, sep); 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstring16 JoinString(const std::vector<string16>& parts, char16 sep) { 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return JoinStringT(parts, sep); 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<class FormatStringType, class OutStringType> 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottOutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string, 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::vector<OutStringType>& subst, std::vector<size_t>* offsets) { 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t substitutions = subst.size(); 838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(substitutions < 10); 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t sub_length = 0; 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (typename std::vector<OutStringType>::const_iterator iter = subst.begin(); 842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott iter != subst.end(); ++iter) { 843731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick sub_length += iter->length(); 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OutStringType formatted; 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott formatted.reserve(format_string.length() + sub_length); 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<ReplacementOffset> r_offsets; 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (typename FormatStringType::const_iterator i = format_string.begin(); 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i != format_string.end(); ++i) { 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ('$' == *i) { 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i + 1 != format_string.end()) { 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++i; 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i; 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ('$' == *i) { 8573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick while (i != format_string.end() && '$' == *i) { 8583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick formatted.push_back('$'); 8593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ++i; 8603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 8613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick --i; 862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uintptr_t index = *i - '1'; 864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offsets) { 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ReplacementOffset r_offset(index, 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<int>(formatted.size())); 867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott r_offsets.insert(std::lower_bound(r_offsets.begin(), 868731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick r_offsets.end(), 869731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick r_offset, 870731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick &CompareParameter), 871731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick r_offset); 872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (index < substitutions) 874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott formatted.append(subst.at(index)); 875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott formatted.push_back(*i); 879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offsets) { 882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (std::vector<ReplacementOffset>::const_iterator i = r_offsets.begin(); 883731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick i != r_offsets.end(); ++i) { 884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offsets->push_back(i->offset); 885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return formatted; 888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstring16 ReplaceStringPlaceholders(const string16& format_string, 891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::vector<string16>& subst, 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<size_t>* offsets) { 893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoReplaceStringPlaceholders(format_string, subst, offsets); 894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string ReplaceStringPlaceholders(const base::StringPiece& format_string, 897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::vector<std::string>& subst, 898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<size_t>* offsets) { 899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return DoReplaceStringPlaceholders(format_string, subst, offsets); 900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstring16 ReplaceStringPlaceholders(const string16& format_string, 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const string16& a, 904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t* offset) { 905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<size_t> offsets; 906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<string16> subst; 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott subst.push_back(a); 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott string16 result = ReplaceStringPlaceholders(format_string, subst, &offsets); 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(offsets.size() == 1); 911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (offset) { 912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *offset = offsets[0]; 913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic bool IsWildcard(base_icu::UChar32 character) { 918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return character == '*' || character == '?'; 919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Move the strings pointers to the point where they start to differ. 9223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricktemplate <typename CHAR, typename NEXT> 9233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic void EatSameChars(const CHAR** pattern, const CHAR* pattern_end, 9243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CHAR** string, const CHAR* string_end, 9253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NEXT next) { 9263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CHAR* escape = NULL; 9273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick while (*pattern != pattern_end && *string != string_end) { 9283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!escape && IsWildcard(**pattern)) { 929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We don't want to match wildcard here, except if it's escaped. 930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check if the escapement char is found. If so, skip it and move to the 934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // next character. 9353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!escape && **pattern == '\\') { 9363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick escape = *pattern; 9373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next(pattern, pattern_end); 938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check if the chars match, if so, increment the ptrs. 9423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CHAR* pattern_next = *pattern; 9433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CHAR* string_next = *string; 9443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base_icu::UChar32 pattern_char = next(&pattern_next, pattern_end); 9453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (pattern_char == next(&string_next, string_end) && 9463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pattern_char != (base_icu::UChar32) CBU_SENTINEL) { 9473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *pattern = pattern_next; 9483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *string = string_next; 949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Uh ho, it did not match, we are done. If the last char was an 951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // escapement, that means that it was an error to advance the ptr here, 952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // let's put it back where it was. This also mean that the MatchPattern 953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // function will return false because if we can't match an escape char 954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // here, then no one will. 9553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (escape) { 9563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *pattern = escape; 957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick escape = NULL; 962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricktemplate <typename CHAR, typename NEXT> 9663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic void EatWildcard(const CHAR** pattern, const CHAR* end, NEXT next) { 9673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick while (*pattern != end) { 968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsWildcard(**pattern)) 969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 9703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next(pattern, end); 971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricktemplate <typename CHAR, typename NEXT> 9753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstatic bool MatchPatternT(const CHAR* eval, const CHAR* eval_end, 9763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CHAR* pattern, const CHAR* pattern_end, 9773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int depth, 9783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NEXT next) { 979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const int kMaxDepth = 16; 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (depth > kMaxDepth) 981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Eat all the matching chars. 9843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EatSameChars(&pattern, pattern_end, &eval, eval_end, next); 985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the string is empty, then the pattern must be empty too, or contains 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // only wildcards. 9883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (eval == eval_end) { 9893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EatWildcard(&pattern, pattern_end, next); 9903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return pattern == pattern_end; 991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Pattern is empty but not string, this is not a match. 9943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (pattern == pattern_end) 995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If this is a question mark, then we need to compare the rest with 998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the current string or the string with one character eaten. 9993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CHAR* next_pattern = pattern; 10003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next(&next_pattern, pattern_end); 1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pattern[0] == '?') { 10023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, 10033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick depth + 1, next)) 10043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 10053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const CHAR* next_eval = eval; 10063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick next(&next_eval, eval_end); 10073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (MatchPatternT(next_eval, eval_end, next_pattern, pattern_end, 10083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick depth + 1, next)) 1009c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1010c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1011c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1012c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is a *, try to match all the possible substrings with the remainder 1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // of the pattern. 1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pattern[0] == '*') { 1015731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Collapse duplicate wild cards (********** into *) so that the 1016731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // method does not recurse unnecessarily. http://crbug.com/52839 1017731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EatWildcard(&next_pattern, pattern_end, next); 1018731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 10193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick while (eval != eval_end) { 10203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (MatchPatternT(eval, eval_end, next_pattern, pattern_end, 10213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick depth + 1, next)) 1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott eval++; 1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1026c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We reached the end of the string, let see if the pattern contains only 1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // wildcards. 10283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (eval == eval_end) { 10293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EatWildcard(&pattern, pattern_end, next); 10303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (pattern != pattern_end) 1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstruct NextCharUTF8 { 10403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base_icu::UChar32 operator()(const char** p, const char* end) { 10413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base_icu::UChar32 c; 10423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int offset = 0; 10433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CBU8_NEXT(*p, offset, end - *p, c); 10443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *p += offset; 10453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return c; 1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 10473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstruct NextCharUTF16 { 10503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base_icu::UChar32 operator()(const char16** p, const char16* end) { 10513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base_icu::UChar32 c; 10523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int offset = 0; 10533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CBU16_NEXT(*p, offset, end - *p, c); 10543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *p += offset; 10553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return c; 10563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 10573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}; 1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool MatchPattern(const base::StringPiece& eval, 10603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const base::StringPiece& pattern) { 10613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return MatchPatternT(eval.data(), eval.data() + eval.size(), 10623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pattern.data(), pattern.data() + pattern.size(), 10633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, NextCharUTF8()); 1064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool MatchPattern(const string16& eval, const string16& pattern) { 10673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return MatchPatternT(eval.c_str(), eval.c_str() + eval.size(), 10683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick pattern.c_str(), pattern.c_str() + pattern.size(), 10693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, NextCharUTF16()); 1070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The following code is compatible with the OpenBSD lcpy interface. See: 1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// http://www.gratisoft.us/todd/papers/strlcpy.html 1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c 1075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate <typename CHAR> 1079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) { 1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < dst_size; ++i) { 1081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL. 1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return i; 1083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We were left off at dst_size. We over copied 1 byte. Null terminate. 1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dst_size != 0) 1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dst[dst_size - 1] = 0; 1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Count the rest of the |src|, and return it's length in characters. 1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (src[dst_size]) ++dst_size; 1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return dst_size; 1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t base::strlcpy(char* dst, const char* src, size_t dst_size) { 1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return lcpyT<char>(dst, src, dst_size); 1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) { 1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return lcpyT<wchar_t>(dst, src, dst_size); 1101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1102