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