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