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