michael@0: // Copyright 2013 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: // This file defines utility functions for working with strings. michael@0: michael@0: #ifndef BASE_STRINGS_STRING_UTIL_H_ michael@0: #define BASE_STRINGS_STRING_UTIL_H_ michael@0: michael@0: #include michael@0: #include // va_list michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "base/base_export.h" michael@0: #include "base/basictypes.h" michael@0: #include "base/compiler_specific.h" michael@0: #include "base/strings/string16.h" michael@0: #include "base/strings/string_piece.h" // For implicit conversions. michael@0: michael@0: // Safe standard library wrappers for all platforms. michael@0: michael@0: namespace base { michael@0: michael@0: // C standard-library functions like "strncasecmp" and "snprintf" that aren't michael@0: // cross-platform are provided as "base::strncasecmp", and their prototypes michael@0: // are listed below. These functions are then implemented as inline calls michael@0: // to the platform-specific equivalents in the platform-specific headers. michael@0: michael@0: // Compares the two strings s1 and s2 without regard to case using michael@0: // the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if michael@0: // s2 > s1 according to a lexicographic comparison. michael@0: int strcasecmp(const char* s1, const char* s2); michael@0: michael@0: // Compares up to count characters of s1 and s2 without regard to case using michael@0: // the current locale; returns 0 if they are equal, 1 if s1 > s2, and -1 if michael@0: // s2 > s1 according to a lexicographic comparison. michael@0: int strncasecmp(const char* s1, const char* s2, size_t count); michael@0: michael@0: // Same as strncmp but for char16 strings. michael@0: int strncmp16(const char16* s1, const char16* s2, size_t count); michael@0: michael@0: // Wrapper for vsnprintf that always null-terminates and always returns the michael@0: // number of characters that would be in an untruncated formatted michael@0: // string, even when truncation occurs. michael@0: int vsnprintf(char* buffer, size_t size, const char* format, va_list arguments) michael@0: PRINTF_FORMAT(3, 0); michael@0: michael@0: // vswprintf always null-terminates, but when truncation occurs, it will either michael@0: // return -1 or the number of characters that would be in an untruncated michael@0: // formatted string. The actual return value depends on the underlying michael@0: // C library's vswprintf implementation. michael@0: int vswprintf(wchar_t* buffer, size_t size, michael@0: const wchar_t* format, va_list arguments) michael@0: WPRINTF_FORMAT(3, 0); michael@0: michael@0: // Some of these implementations need to be inlined. michael@0: michael@0: // We separate the declaration from the implementation of this inline michael@0: // function just so the PRINTF_FORMAT works. michael@0: inline int snprintf(char* buffer, size_t size, const char* format, ...) michael@0: PRINTF_FORMAT(3, 4); michael@0: inline int snprintf(char* buffer, size_t size, const char* format, ...) { michael@0: va_list arguments; michael@0: va_start(arguments, format); michael@0: int result = vsnprintf(buffer, size, format, arguments); michael@0: va_end(arguments); michael@0: return result; michael@0: } michael@0: michael@0: // We separate the declaration from the implementation of this inline michael@0: // function just so the WPRINTF_FORMAT works. michael@0: inline int swprintf(wchar_t* buffer, size_t size, const wchar_t* format, ...) michael@0: WPRINTF_FORMAT(3, 4); michael@0: inline int swprintf(wchar_t* buffer, size_t size, const wchar_t* format, ...) { michael@0: va_list arguments; michael@0: va_start(arguments, format); michael@0: int result = vswprintf(buffer, size, format, arguments); michael@0: va_end(arguments); michael@0: return result; michael@0: } michael@0: michael@0: // BSD-style safe and consistent string copy functions. michael@0: // Copies |src| to |dst|, where |dst_size| is the total allocated size of |dst|. michael@0: // Copies at most |dst_size|-1 characters, and always NULL terminates |dst|, as michael@0: // long as |dst_size| is not 0. Returns the length of |src| in characters. michael@0: // If the return value is >= dst_size, then the output was truncated. michael@0: // NOTE: All sizes are in number of characters, NOT in bytes. michael@0: BASE_EXPORT size_t strlcpy(char* dst, const char* src, size_t dst_size); michael@0: BASE_EXPORT size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size); michael@0: michael@0: // Scan a wprintf format string to determine whether it's portable across a michael@0: // variety of systems. This function only checks that the conversion michael@0: // specifiers used by the format string are supported and have the same meaning michael@0: // on a variety of systems. It doesn't check for other errors that might occur michael@0: // within a format string. michael@0: // michael@0: // Nonportable conversion specifiers for wprintf are: michael@0: // - 's' and 'c' without an 'l' length modifier. %s and %c operate on char michael@0: // data on all systems except Windows, which treat them as wchar_t data. michael@0: // Use %ls and %lc for wchar_t data instead. michael@0: // - 'S' and 'C', which operate on wchar_t data on all systems except Windows, michael@0: // which treat them as char data. Use %ls and %lc for wchar_t data michael@0: // instead. michael@0: // - 'F', which is not identified by Windows wprintf documentation. michael@0: // - 'D', 'O', and 'U', which are deprecated and not available on all systems. michael@0: // Use %ld, %lo, and %lu instead. michael@0: // michael@0: // Note that there is no portable conversion specifier for char data when michael@0: // working with wprintf. michael@0: // michael@0: // This function is intended to be called from base::vswprintf. michael@0: BASE_EXPORT bool IsWprintfFormatPortable(const wchar_t* format); michael@0: michael@0: // ASCII-specific tolower. The standard library's tolower is locale sensitive, michael@0: // so we don't want to use it here. michael@0: template inline Char ToLowerASCII(Char c) { michael@0: return (c >= 'A' && c <= 'Z') ? (c + ('a' - 'A')) : c; michael@0: } michael@0: michael@0: // ASCII-specific toupper. The standard library's toupper is locale sensitive, michael@0: // so we don't want to use it here. michael@0: template inline Char ToUpperASCII(Char c) { michael@0: return (c >= 'a' && c <= 'z') ? (c + ('A' - 'a')) : c; michael@0: } michael@0: michael@0: // Function objects to aid in comparing/searching strings. michael@0: michael@0: template struct CaseInsensitiveCompare { michael@0: public: michael@0: bool operator()(Char x, Char y) const { michael@0: // TODO(darin): Do we really want to do locale sensitive comparisons here? michael@0: // See http://crbug.com/24917 michael@0: return tolower(x) == tolower(y); michael@0: } michael@0: }; michael@0: michael@0: template struct CaseInsensitiveCompareASCII { michael@0: public: michael@0: bool operator()(Char x, Char y) const { michael@0: return ToLowerASCII(x) == ToLowerASCII(y); michael@0: } michael@0: }; michael@0: michael@0: } // namespace base michael@0: michael@0: #if defined(OS_WIN) michael@0: #include "base/strings/string_util_win.h" michael@0: #elif defined(OS_POSIX) michael@0: #include "base/strings/string_util_posix.h" michael@0: #else michael@0: #error Define string operations appropriately for your platform michael@0: #endif michael@0: michael@0: // These threadsafe functions return references to globally unique empty michael@0: // strings. michael@0: // michael@0: // DO NOT USE THESE AS A GENERAL-PURPOSE SUBSTITUTE FOR DEFAULT CONSTRUCTORS. michael@0: // There is only one case where you should use these: functions which need to michael@0: // return a string by reference (e.g. as a class member accessor), and don't michael@0: // have an empty string to use (e.g. in an error case). These should not be michael@0: // used as initializers, function arguments, or return values for functions michael@0: // which return by value or outparam. michael@0: BASE_EXPORT const std::string& EmptyString(); michael@0: BASE_EXPORT const std::wstring& EmptyWString(); michael@0: BASE_EXPORT const string16& EmptyString16(); michael@0: michael@0: BASE_EXPORT extern const wchar_t kWhitespaceWide[]; michael@0: BASE_EXPORT extern const char16 kWhitespaceUTF16[]; michael@0: BASE_EXPORT extern const char kWhitespaceASCII[]; michael@0: michael@0: BASE_EXPORT extern const char kUtf8ByteOrderMark[]; michael@0: michael@0: // Removes characters in |remove_chars| from anywhere in |input|. Returns true michael@0: // if any characters were removed. |remove_chars| must be null-terminated. michael@0: // NOTE: Safe to use the same variable for both |input| and |output|. michael@0: BASE_EXPORT bool RemoveChars(const string16& input, michael@0: const char16 remove_chars[], michael@0: string16* output); michael@0: BASE_EXPORT bool RemoveChars(const std::string& input, michael@0: const char remove_chars[], michael@0: std::string* output); michael@0: michael@0: // Replaces characters in |replace_chars| from anywhere in |input| with michael@0: // |replace_with|. Each character in |replace_chars| will be replaced with michael@0: // the |replace_with| string. Returns true if any characters were replaced. michael@0: // |replace_chars| must be null-terminated. michael@0: // NOTE: Safe to use the same variable for both |input| and |output|. michael@0: BASE_EXPORT bool ReplaceChars(const string16& input, michael@0: const char16 replace_chars[], michael@0: const string16& replace_with, michael@0: string16* output); michael@0: BASE_EXPORT bool ReplaceChars(const std::string& input, michael@0: const char replace_chars[], michael@0: const std::string& replace_with, michael@0: std::string* output); michael@0: michael@0: // Removes characters in |trim_chars| from the beginning and end of |input|. michael@0: // |trim_chars| must be null-terminated. michael@0: // NOTE: Safe to use the same variable for both |input| and |output|. michael@0: BASE_EXPORT bool TrimString(const std::wstring& input, michael@0: const wchar_t trim_chars[], michael@0: std::wstring* output); michael@0: BASE_EXPORT bool TrimString(const string16& input, michael@0: const char16 trim_chars[], michael@0: string16* output); michael@0: BASE_EXPORT bool TrimString(const std::string& input, michael@0: const char trim_chars[], michael@0: std::string* output); michael@0: michael@0: // Truncates a string to the nearest UTF-8 character that will leave michael@0: // the string less than or equal to the specified byte size. michael@0: BASE_EXPORT void TruncateUTF8ToByteSize(const std::string& input, michael@0: const size_t byte_size, michael@0: std::string* output); michael@0: michael@0: // Trims any whitespace from either end of the input string. Returns where michael@0: // whitespace was found. michael@0: // The non-wide version has two functions: michael@0: // * TrimWhitespaceASCII() michael@0: // This function is for ASCII strings and only looks for ASCII whitespace; michael@0: // Please choose the best one according to your usage. michael@0: // NOTE: Safe to use the same variable for both input and output. michael@0: enum TrimPositions { michael@0: TRIM_NONE = 0, michael@0: TRIM_LEADING = 1 << 0, michael@0: TRIM_TRAILING = 1 << 1, michael@0: TRIM_ALL = TRIM_LEADING | TRIM_TRAILING, michael@0: }; michael@0: BASE_EXPORT TrimPositions TrimWhitespace(const string16& input, michael@0: TrimPositions positions, michael@0: string16* output); michael@0: BASE_EXPORT TrimPositions TrimWhitespaceASCII(const std::string& input, michael@0: TrimPositions positions, michael@0: std::string* output); michael@0: michael@0: // Deprecated. This function is only for backward compatibility and calls michael@0: // TrimWhitespaceASCII(). michael@0: BASE_EXPORT TrimPositions TrimWhitespace(const std::string& input, michael@0: TrimPositions positions, michael@0: std::string* output); michael@0: michael@0: // Searches for CR or LF characters. Removes all contiguous whitespace michael@0: // strings that contain them. This is useful when trying to deal with text michael@0: // copied from terminals. michael@0: // Returns |text|, with the following three transformations: michael@0: // (1) Leading and trailing whitespace is trimmed. michael@0: // (2) If |trim_sequences_with_line_breaks| is true, any other whitespace michael@0: // sequences containing a CR or LF are trimmed. michael@0: // (3) All other whitespace sequences are converted to single spaces. michael@0: BASE_EXPORT std::wstring CollapseWhitespace( michael@0: const std::wstring& text, michael@0: bool trim_sequences_with_line_breaks); michael@0: BASE_EXPORT string16 CollapseWhitespace( michael@0: const string16& text, michael@0: bool trim_sequences_with_line_breaks); michael@0: BASE_EXPORT std::string CollapseWhitespaceASCII( michael@0: const std::string& text, michael@0: bool trim_sequences_with_line_breaks); michael@0: michael@0: // Returns true if the passed string is empty or contains only white-space michael@0: // characters. michael@0: BASE_EXPORT bool ContainsOnlyWhitespaceASCII(const std::string& str); michael@0: BASE_EXPORT bool ContainsOnlyWhitespace(const string16& str); michael@0: michael@0: // Returns true if |input| is empty or contains only characters found in michael@0: // |characters|. michael@0: BASE_EXPORT bool ContainsOnlyChars(const std::wstring& input, michael@0: const std::wstring& characters); michael@0: BASE_EXPORT bool ContainsOnlyChars(const string16& input, michael@0: const string16& characters); michael@0: BASE_EXPORT bool ContainsOnlyChars(const std::string& input, michael@0: const std::string& characters); michael@0: michael@0: // Converts to 7-bit ASCII by truncating. The result must be known to be ASCII michael@0: // beforehand. michael@0: BASE_EXPORT std::string WideToASCII(const std::wstring& wide); michael@0: BASE_EXPORT std::string UTF16ToASCII(const string16& utf16); michael@0: michael@0: // Converts the given wide string to the corresponding Latin1. This will fail michael@0: // (return false) if any characters are more than 255. michael@0: BASE_EXPORT bool WideToLatin1(const std::wstring& wide, std::string* latin1); michael@0: michael@0: // Returns true if the specified string matches the criteria. How can a wide michael@0: // string be 8-bit or UTF8? It contains only characters that are < 256 (in the michael@0: // first case) or characters that use only 8-bits and whose 8-bit michael@0: // representation looks like a UTF-8 string (the second case). michael@0: // michael@0: // Note that IsStringUTF8 checks not only if the input is structurally michael@0: // valid but also if it doesn't contain any non-character codepoint michael@0: // (e.g. U+FFFE). It's done on purpose because all the existing callers want michael@0: // to have the maximum 'discriminating' power from other encodings. If michael@0: // there's a use case for just checking the structural validity, we have to michael@0: // add a new function for that. michael@0: BASE_EXPORT bool IsStringUTF8(const std::string& str); michael@0: BASE_EXPORT bool IsStringASCII(const std::wstring& str); michael@0: BASE_EXPORT bool IsStringASCII(const string16& str); michael@0: michael@0: // Converts the elements of the given string. This version uses a pointer to michael@0: // clearly differentiate it from the non-pointer variant. michael@0: template inline void StringToLowerASCII(str* s) { michael@0: for (typename str::iterator i = s->begin(); i != s->end(); ++i) michael@0: *i = base::ToLowerASCII(*i); michael@0: } michael@0: michael@0: template inline str StringToLowerASCII(const str& s) { michael@0: // for std::string and std::wstring michael@0: str output(s); michael@0: StringToLowerASCII(&output); michael@0: return output; michael@0: } michael@0: michael@0: // Converts the elements of the given string. This version uses a pointer to michael@0: // clearly differentiate it from the non-pointer variant. michael@0: template inline void StringToUpperASCII(str* s) { michael@0: for (typename str::iterator i = s->begin(); i != s->end(); ++i) michael@0: *i = base::ToUpperASCII(*i); michael@0: } michael@0: michael@0: template inline str StringToUpperASCII(const str& s) { michael@0: // for std::string and std::wstring michael@0: str output(s); michael@0: StringToUpperASCII(&output); michael@0: return output; michael@0: } michael@0: michael@0: // Compare the lower-case form of the given string against the given ASCII michael@0: // string. This is useful for doing checking if an input string matches some michael@0: // token, and it is optimized to avoid intermediate string copies. This API is michael@0: // borrowed from the equivalent APIs in Mozilla. michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(const std::string& a, const char* b); michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(const std::wstring& a, const char* b); michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(const string16& a, const char* b); michael@0: michael@0: // Same thing, but with string iterators instead. michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(std::string::const_iterator a_begin, michael@0: std::string::const_iterator a_end, michael@0: const char* b); michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(std::wstring::const_iterator a_begin, michael@0: std::wstring::const_iterator a_end, michael@0: const char* b); michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(string16::const_iterator a_begin, michael@0: string16::const_iterator a_end, michael@0: const char* b); michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(const char* a_begin, michael@0: const char* a_end, michael@0: const char* b); michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(const wchar_t* a_begin, michael@0: const wchar_t* a_end, michael@0: const char* b); michael@0: BASE_EXPORT bool LowerCaseEqualsASCII(const char16* a_begin, michael@0: const char16* a_end, michael@0: const char* b); michael@0: michael@0: // Performs a case-sensitive string compare. The behavior is undefined if both michael@0: // strings are not ASCII. michael@0: BASE_EXPORT bool EqualsASCII(const string16& a, const base::StringPiece& b); michael@0: michael@0: // Returns true if str starts with search, or false otherwise. michael@0: BASE_EXPORT bool StartsWithASCII(const std::string& str, michael@0: const std::string& search, michael@0: bool case_sensitive); michael@0: BASE_EXPORT bool StartsWith(const std::wstring& str, michael@0: const std::wstring& search, michael@0: bool case_sensitive); michael@0: BASE_EXPORT bool StartsWith(const string16& str, michael@0: const string16& search, michael@0: bool case_sensitive); michael@0: michael@0: // Returns true if str ends with search, or false otherwise. michael@0: BASE_EXPORT bool EndsWith(const std::string& str, michael@0: const std::string& search, michael@0: bool case_sensitive); michael@0: BASE_EXPORT bool EndsWith(const std::wstring& str, michael@0: const std::wstring& search, michael@0: bool case_sensitive); michael@0: BASE_EXPORT bool EndsWith(const string16& str, michael@0: const string16& search, michael@0: bool case_sensitive); michael@0: michael@0: michael@0: // Determines the type of ASCII character, independent of locale (the C michael@0: // library versions will change based on locale). michael@0: template michael@0: inline bool IsAsciiWhitespace(Char c) { michael@0: return c == ' ' || c == '\r' || c == '\n' || c == '\t'; michael@0: } michael@0: template michael@0: inline bool IsAsciiAlpha(Char c) { michael@0: return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')); michael@0: } michael@0: template michael@0: inline bool IsAsciiDigit(Char c) { michael@0: return c >= '0' && c <= '9'; michael@0: } michael@0: michael@0: template michael@0: inline bool IsHexDigit(Char c) { michael@0: return (c >= '0' && c <= '9') || michael@0: (c >= 'A' && c <= 'F') || michael@0: (c >= 'a' && c <= 'f'); michael@0: } michael@0: michael@0: template michael@0: inline Char HexDigitToInt(Char c) { michael@0: DCHECK(IsHexDigit(c)); michael@0: if (c >= '0' && c <= '9') michael@0: return c - '0'; michael@0: if (c >= 'A' && c <= 'F') michael@0: return c - 'A' + 10; michael@0: if (c >= 'a' && c <= 'f') michael@0: return c - 'a' + 10; michael@0: return 0; michael@0: } michael@0: michael@0: // Returns true if it's a whitespace character. michael@0: inline bool IsWhitespace(wchar_t c) { michael@0: return wcschr(kWhitespaceWide, c) != NULL; michael@0: } michael@0: michael@0: // Return a byte string in human-readable format with a unit suffix. Not michael@0: // appropriate for use in any UI; use of FormatBytes and friends in ui/base is michael@0: // highly recommended instead. TODO(avi): Figure out how to get callers to use michael@0: // FormatBytes instead; remove this. michael@0: BASE_EXPORT string16 FormatBytesUnlocalized(int64 bytes); michael@0: michael@0: // Starting at |start_offset| (usually 0), replace the first instance of michael@0: // |find_this| with |replace_with|. michael@0: BASE_EXPORT void ReplaceFirstSubstringAfterOffset( michael@0: string16* str, michael@0: string16::size_type start_offset, michael@0: const string16& find_this, michael@0: const string16& replace_with); michael@0: BASE_EXPORT void ReplaceFirstSubstringAfterOffset( michael@0: std::string* str, michael@0: std::string::size_type start_offset, michael@0: const std::string& find_this, michael@0: const std::string& replace_with); michael@0: michael@0: // Starting at |start_offset| (usually 0), look through |str| and replace all michael@0: // instances of |find_this| with |replace_with|. michael@0: // michael@0: // This does entire substrings; use std::replace in for single michael@0: // characters, for example: michael@0: // std::replace(str.begin(), str.end(), 'a', 'b'); michael@0: BASE_EXPORT void ReplaceSubstringsAfterOffset( michael@0: string16* str, michael@0: string16::size_type start_offset, michael@0: const string16& find_this, michael@0: const string16& replace_with); michael@0: BASE_EXPORT void ReplaceSubstringsAfterOffset( michael@0: std::string* str, michael@0: std::string::size_type start_offset, michael@0: const std::string& find_this, michael@0: const std::string& replace_with); michael@0: michael@0: // Reserves enough memory in |str| to accommodate |length_with_null| characters, michael@0: // sets the size of |str| to |length_with_null - 1| characters, and returns a michael@0: // pointer to the underlying contiguous array of characters. This is typically michael@0: // used when calling a function that writes results into a character array, but michael@0: // the caller wants the data to be managed by a string-like object. It is michael@0: // convenient in that is can be used inline in the call, and fast in that it michael@0: // avoids copying the results of the call from a char* into a string. michael@0: // michael@0: // |length_with_null| must be at least 2, since otherwise the underlying string michael@0: // would have size 0, and trying to access &((*str)[0]) in that case can result michael@0: // in a number of problems. michael@0: // michael@0: // Internally, this takes linear time because the resize() call 0-fills the michael@0: // underlying array for potentially all michael@0: // (|length_with_null - 1| * sizeof(string_type::value_type)) bytes. Ideally we michael@0: // could avoid this aspect of the resize() call, as we expect the caller to michael@0: // immediately write over this memory, but there is no other way to set the size michael@0: // of the string, and not doing that will mean people who access |str| rather michael@0: // than str.c_str() will get back a string of whatever size |str| had on entry michael@0: // to this function (probably 0). michael@0: template michael@0: inline typename string_type::value_type* WriteInto(string_type* str, michael@0: size_t length_with_null) { michael@0: DCHECK_GT(length_with_null, 1u); michael@0: str->reserve(length_with_null); michael@0: str->resize(length_with_null - 1); michael@0: return &((*str)[0]); michael@0: } michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: // Splits a string into its fields delimited by any of the characters in michael@0: // |delimiters|. Each field is added to the |tokens| vector. Returns the michael@0: // number of tokens found. michael@0: BASE_EXPORT size_t Tokenize(const std::wstring& str, michael@0: const std::wstring& delimiters, michael@0: std::vector* tokens); michael@0: BASE_EXPORT size_t Tokenize(const string16& str, michael@0: const string16& delimiters, michael@0: std::vector* tokens); michael@0: BASE_EXPORT size_t Tokenize(const std::string& str, michael@0: const std::string& delimiters, michael@0: std::vector* tokens); michael@0: BASE_EXPORT size_t Tokenize(const base::StringPiece& str, michael@0: const base::StringPiece& delimiters, michael@0: std::vector* tokens); michael@0: michael@0: // Does the opposite of SplitString(). michael@0: BASE_EXPORT string16 JoinString(const std::vector& parts, char16 s); michael@0: BASE_EXPORT std::string JoinString( michael@0: const std::vector& parts, char s); michael@0: michael@0: // Join |parts| using |separator|. michael@0: BASE_EXPORT std::string JoinString( michael@0: const std::vector& parts, michael@0: const std::string& separator); michael@0: BASE_EXPORT string16 JoinString( michael@0: const std::vector& parts, michael@0: const string16& separator); michael@0: michael@0: // Replace $1-$2-$3..$9 in the format string with |a|-|b|-|c|..|i| respectively. michael@0: // Additionally, any number of consecutive '$' characters is replaced by that michael@0: // number less one. Eg $$->$, $$$->$$, etc. The offsets parameter here can be michael@0: // NULL. This only allows you to use up to nine replacements. michael@0: BASE_EXPORT string16 ReplaceStringPlaceholders( michael@0: const string16& format_string, michael@0: const std::vector& subst, michael@0: std::vector* offsets); michael@0: michael@0: BASE_EXPORT std::string ReplaceStringPlaceholders( michael@0: const base::StringPiece& format_string, michael@0: const std::vector& subst, michael@0: std::vector* offsets); michael@0: michael@0: // Single-string shortcut for ReplaceStringHolders. |offset| may be NULL. michael@0: BASE_EXPORT string16 ReplaceStringPlaceholders(const string16& format_string, michael@0: const string16& a, michael@0: size_t* offset); michael@0: michael@0: // Returns true if the string passed in matches the pattern. The pattern michael@0: // string can contain wildcards like * and ? michael@0: // The backslash character (\) is an escape character for * and ? michael@0: // We limit the patterns to having a max of 16 * or ? characters. michael@0: // ? matches 0 or 1 character, while * matches 0 or more characters. michael@0: BASE_EXPORT bool MatchPattern(const base::StringPiece& string, michael@0: const base::StringPiece& pattern); michael@0: BASE_EXPORT bool MatchPattern(const string16& string, const string16& pattern); michael@0: michael@0: // Hack to convert any char-like type to its unsigned counterpart. michael@0: // For example, it will convert char, signed char and unsigned char to unsigned michael@0: // char. michael@0: template michael@0: struct ToUnsigned { michael@0: typedef T Unsigned; michael@0: }; michael@0: michael@0: template<> michael@0: struct ToUnsigned { michael@0: typedef unsigned char Unsigned; michael@0: }; michael@0: template<> michael@0: struct ToUnsigned { michael@0: typedef unsigned char Unsigned; michael@0: }; michael@0: template<> michael@0: struct ToUnsigned { michael@0: #if defined(WCHAR_T_IS_UTF16) michael@0: typedef unsigned short Unsigned; michael@0: #elif defined(WCHAR_T_IS_UTF32) michael@0: typedef uint32 Unsigned; michael@0: #endif michael@0: }; michael@0: template<> michael@0: struct ToUnsigned { michael@0: typedef unsigned short Unsigned; michael@0: }; michael@0: michael@0: #endif // BASE_STRINGS_STRING_UTIL_H_