Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Unified Diff: base/string_util_static.cc

Issue 6877053: Base: More adjustments to BASE_API and project dependencies to (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/string_util_static.cc
===================================================================
--- base/string_util_static.cc (revision 81611)
+++ base/string_util_static.cc (working copy)
@@ -2,121 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/string_util.h"
+#include "base/string_util_static.h"
-#include "build/build_config.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#include <algorithm>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "base/third_party/dmg_fp/dmg_fp.h"
-#include "base/utf_string_conversion_utils.h"
-#include "base/utf_string_conversions.h"
-#include "base/third_party/icu/icu_utf.h"
-
-namespace {
-
-// Force the singleton used by Empty[W]String[16] to be a unique type. This
-// prevents other code that might accidentally use Singleton<string> from
-// getting our internal one.
-struct EmptyStrings {
- EmptyStrings() {}
- const std::string s;
- const std::wstring ws;
- const string16 s16;
-
- static EmptyStrings* GetInstance() {
- return Singleton<EmptyStrings>::get();
- }
-};
-
-// Used by ReplaceStringPlaceholders to track the position in the string of
-// replaced parameters.
-struct ReplacementOffset {
- ReplacementOffset(uintptr_t parameter, size_t offset)
- : parameter(parameter),
- offset(offset) {}
-
- // Index of the parameter.
- uintptr_t parameter;
-
- // Starting position in the string.
- size_t offset;
-};
-
-static bool CompareParameter(const ReplacementOffset& elem1,
- const ReplacementOffset& elem2) {
- return elem1.parameter < elem2.parameter;
-}
-
-} // namespace
-
-namespace base {
-
-bool IsWprintfFormatPortable(const wchar_t* format) {
- for (const wchar_t* position = format; *position != '\0'; ++position) {
- if (*position == '%') {
- bool in_specification = true;
- bool modifier_l = false;
- while (in_specification) {
- // Eat up characters until reaching a known specifier.
- if (*++position == '\0') {
- // The format string ended in the middle of a specification. Call
- // it portable because no unportable specifications were found. The
- // string is equally broken on all platforms.
- return true;
- }
-
- if (*position == 'l') {
- // 'l' is the only thing that can save the 's' and 'c' specifiers.
- modifier_l = true;
- } else if (((*position == 's' || *position == 'c') && !modifier_l) ||
- *position == 'S' || *position == 'C' || *position == 'F' ||
- *position == 'D' || *position == 'O' || *position == 'U') {
- // Not portable.
- return false;
- }
-
- if (wcschr(L"diouxXeEfgGaAcspn%", *position)) {
- // Portable, keep scanning the rest of the format string.
- in_specification = false;
- }
- }
- }
- }
-
- return true;
-}
-
-} // namespace base
-
-
-const std::string& EmptyString() {
- return EmptyStrings::GetInstance()->s;
-}
-
-const std::wstring& EmptyWString() {
- return EmptyStrings::GetInstance()->ws;
-}
-
-const string16& EmptyString16() {
- return EmptyStrings::GetInstance()->s16;
-}
-
#define WHITESPACE_UNICODE \
0x0009, /* <control-0009> to <control-000D> */ \
0x000A, \
@@ -164,934 +51,3 @@
};
const char kUtf8ByteOrderMark[] = "\xEF\xBB\xBF";
-
-template<typename STR>
-bool RemoveCharsT(const STR& input,
- const typename STR::value_type remove_chars[],
- STR* output) {
- bool removed = false;
- size_t found;
-
- *output = input;
-
- found = output->find_first_of(remove_chars);
- while (found != STR::npos) {
- removed = true;
- output->replace(found, 1, STR());
- found = output->find_first_of(remove_chars, found);
- }
-
- return removed;
-}
-
-bool RemoveChars(const std::wstring& input,
- const wchar_t remove_chars[],
- std::wstring* output) {
- return RemoveCharsT(input, remove_chars, output);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool RemoveChars(const string16& input,
- const char16 remove_chars[],
- string16* output) {
- return RemoveCharsT(input, remove_chars, output);
-}
-#endif
-
-bool RemoveChars(const std::string& input,
- const char remove_chars[],
- std::string* output) {
- return RemoveCharsT(input, remove_chars, output);
-}
-
-template<typename STR>
-TrimPositions TrimStringT(const STR& input,
- const typename STR::value_type trim_chars[],
- TrimPositions positions,
- STR* output) {
- // Find the edges of leading/trailing whitespace as desired.
- const typename STR::size_type last_char = input.length() - 1;
- const typename STR::size_type first_good_char = (positions & TRIM_LEADING) ?
- input.find_first_not_of(trim_chars) : 0;
- const typename STR::size_type last_good_char = (positions & TRIM_TRAILING) ?
- input.find_last_not_of(trim_chars) : last_char;
-
- // When the string was all whitespace, report that we stripped off whitespace
- // from whichever position the caller was interested in. For empty input, we
- // stripped no whitespace, but we still need to clear |output|.
- if (input.empty() ||
- (first_good_char == STR::npos) || (last_good_char == STR::npos)) {
- bool input_was_empty = input.empty(); // in case output == &input
- output->clear();
- return input_was_empty ? TRIM_NONE : positions;
- }
-
- // Trim the whitespace.
- *output =
- input.substr(first_good_char, last_good_char - first_good_char + 1);
-
- // Return where we trimmed from.
- return static_cast<TrimPositions>(
- ((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) |
- ((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING));
-}
-
-bool TrimString(const std::wstring& input,
- const wchar_t trim_chars[],
- std::wstring* output) {
- return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool TrimString(const string16& input,
- const char16 trim_chars[],
- string16* output) {
- return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
-}
-#endif
-
-bool TrimString(const std::string& input,
- const char trim_chars[],
- std::string* output) {
- return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
-}
-
-void TruncateUTF8ToByteSize(const std::string& input,
- const size_t byte_size,
- std::string* output) {
- DCHECK(output);
- if (byte_size > input.length()) {
- *output = input;
- return;
- }
- DCHECK_LE(byte_size, static_cast<uint32>(kint32max));
- // Note: This cast is necessary because CBU8_NEXT uses int32s.
- int32 truncation_length = static_cast<int32>(byte_size);
- int32 char_index = truncation_length - 1;
- const char* data = input.data();
-
- // Using CBU8, we will move backwards from the truncation point
- // to the beginning of the string looking for a valid UTF8
- // character. Once a full UTF8 character is found, we will
- // truncate the string to the end of that character.
- while (char_index >= 0) {
- int32 prev = char_index;
- uint32 code_point = 0;
- CBU8_NEXT(data, char_index, truncation_length, code_point);
- if (!base::IsValidCharacter(code_point) ||
- !base::IsValidCodepoint(code_point)) {
- char_index = prev - 1;
- } else {
- break;
- }
- }
-
- if (char_index >= 0 )
- *output = input.substr(0, char_index);
- else
- output->clear();
-}
-
-TrimPositions TrimWhitespace(const std::wstring& input,
- TrimPositions positions,
- std::wstring* output) {
- return TrimStringT(input, kWhitespaceWide, positions, output);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-TrimPositions TrimWhitespace(const string16& input,
- TrimPositions positions,
- string16* output) {
- return TrimStringT(input, kWhitespaceUTF16, positions, output);
-}
-#endif
-
-TrimPositions TrimWhitespaceASCII(const std::string& input,
- TrimPositions positions,
- std::string* output) {
- return TrimStringT(input, kWhitespaceASCII, positions, output);
-}
-
-// This function is only for backward-compatibility.
-// To be removed when all callers are updated.
-TrimPositions TrimWhitespace(const std::string& input,
- TrimPositions positions,
- std::string* output) {
- return TrimWhitespaceASCII(input, positions, output);
-}
-
-template<typename STR>
-STR CollapseWhitespaceT(const STR& text,
- bool trim_sequences_with_line_breaks) {
- STR result;
- result.resize(text.size());
-
- // Set flags to pretend we're already in a trimmed whitespace sequence, so we
- // will trim any leading whitespace.
- bool in_whitespace = true;
- bool already_trimmed = true;
-
- int chars_written = 0;
- for (typename STR::const_iterator i(text.begin()); i != text.end(); ++i) {
- if (IsWhitespace(*i)) {
- if (!in_whitespace) {
- // Reduce all whitespace sequences to a single space.
- in_whitespace = true;
- result[chars_written++] = L' ';
- }
- if (trim_sequences_with_line_breaks && !already_trimmed &&
- ((*i == '\n') || (*i == '\r'))) {
- // Whitespace sequences containing CR or LF are eliminated entirely.
- already_trimmed = true;
- --chars_written;
- }
- } else {
- // Non-whitespace chracters are copied straight across.
- in_whitespace = false;
- already_trimmed = false;
- result[chars_written++] = *i;
- }
- }
-
- if (in_whitespace && !already_trimmed) {
- // Any trailing whitespace is eliminated.
- --chars_written;
- }
-
- result.resize(chars_written);
- return result;
-}
-
-std::wstring CollapseWhitespace(const std::wstring& text,
- bool trim_sequences_with_line_breaks) {
- return CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-string16 CollapseWhitespace(const string16& text,
- bool trim_sequences_with_line_breaks) {
- return CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
-}
-#endif
-
-std::string CollapseWhitespaceASCII(const std::string& text,
- bool trim_sequences_with_line_breaks) {
- return CollapseWhitespaceT(text, trim_sequences_with_line_breaks);
-}
-
-bool ContainsOnlyWhitespaceASCII(const std::string& str) {
- for (std::string::const_iterator i(str.begin()); i != str.end(); ++i) {
- if (!IsAsciiWhitespace(*i))
- return false;
- }
- return true;
-}
-
-bool ContainsOnlyWhitespace(const string16& str) {
- for (string16::const_iterator i(str.begin()); i != str.end(); ++i) {
- if (!IsWhitespace(*i))
- return false;
- }
- return true;
-}
-
-template<typename STR>
-static bool ContainsOnlyCharsT(const STR& input, const STR& characters) {
- for (typename STR::const_iterator iter = input.begin();
- iter != input.end(); ++iter) {
- if (characters.find(*iter) == STR::npos)
- return false;
- }
- return true;
-}
-
-bool ContainsOnlyChars(const std::wstring& input,
- const std::wstring& characters) {
- return ContainsOnlyCharsT(input, characters);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool ContainsOnlyChars(const string16& input, const string16& characters) {
- return ContainsOnlyCharsT(input, characters);
-}
-#endif
-
-bool ContainsOnlyChars(const std::string& input,
- const std::string& characters) {
- return ContainsOnlyCharsT(input, characters);
-}
-
-std::string WideToASCII(const std::wstring& wide) {
- DCHECK(IsStringASCII(wide)) << wide;
- return std::string(wide.begin(), wide.end());
-}
-
-std::string UTF16ToASCII(const string16& utf16) {
- DCHECK(IsStringASCII(utf16)) << utf16;
- return std::string(utf16.begin(), utf16.end());
-}
-
-// Latin1 is just the low range of Unicode, so we can copy directly to convert.
-bool WideToLatin1(const std::wstring& wide, std::string* latin1) {
- std::string output;
- output.resize(wide.size());
- latin1->clear();
- for (size_t i = 0; i < wide.size(); i++) {
- if (wide[i] > 255)
- return false;
- output[i] = static_cast<char>(wide[i]);
- }
- latin1->swap(output);
- return true;
-}
-
-template<class STR>
-static bool DoIsStringASCII(const STR& str) {
- for (size_t i = 0; i < str.length(); i++) {
- typename ToUnsigned<typename STR::value_type>::Unsigned c = str[i];
- if (c > 0x7F)
- return false;
- }
- return true;
-}
-
-bool IsStringASCII(const std::wstring& str) {
- return DoIsStringASCII(str);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool IsStringASCII(const string16& str) {
- return DoIsStringASCII(str);
-}
-#endif
-
-bool IsStringASCII(const base::StringPiece& str) {
- return DoIsStringASCII(str);
-}
-
-bool IsStringUTF8(const std::string& str) {
- const char *src = str.data();
- int32 src_len = static_cast<int32>(str.length());
- int32 char_index = 0;
-
- while (char_index < src_len) {
- int32 code_point;
- CBU8_NEXT(src, char_index, src_len, code_point);
- if (!base::IsValidCharacter(code_point))
- return false;
- }
- return true;
-}
-
-template<typename Iter>
-static inline bool DoLowerCaseEqualsASCII(Iter a_begin,
- Iter a_end,
- const char* b) {
- for (Iter it = a_begin; it != a_end; ++it, ++b) {
- if (!*b || base::ToLowerASCII(*it) != *b)
- return false;
- }
- return *b == 0;
-}
-
-// Front-ends for LowerCaseEqualsASCII.
-bool LowerCaseEqualsASCII(const std::string& a, const char* b) {
- return DoLowerCaseEqualsASCII(a.begin(), a.end(), b);
-}
-
-bool LowerCaseEqualsASCII(const std::wstring& a, const char* b) {
- return DoLowerCaseEqualsASCII(a.begin(), a.end(), b);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool LowerCaseEqualsASCII(const string16& a, const char* b) {
- return DoLowerCaseEqualsASCII(a.begin(), a.end(), b);
-}
-#endif
-
-bool LowerCaseEqualsASCII(std::string::const_iterator a_begin,
- std::string::const_iterator a_end,
- const char* b) {
- return DoLowerCaseEqualsASCII(a_begin, a_end, b);
-}
-
-bool LowerCaseEqualsASCII(std::wstring::const_iterator a_begin,
- std::wstring::const_iterator a_end,
- const char* b) {
- return DoLowerCaseEqualsASCII(a_begin, a_end, b);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool LowerCaseEqualsASCII(string16::const_iterator a_begin,
- string16::const_iterator a_end,
- const char* b) {
- return DoLowerCaseEqualsASCII(a_begin, a_end, b);
-}
-#endif
-
-bool LowerCaseEqualsASCII(const char* a_begin,
- const char* a_end,
- const char* b) {
- return DoLowerCaseEqualsASCII(a_begin, a_end, b);
-}
-
-bool LowerCaseEqualsASCII(const wchar_t* a_begin,
- const wchar_t* a_end,
- const char* b) {
- return DoLowerCaseEqualsASCII(a_begin, a_end, b);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool LowerCaseEqualsASCII(const char16* a_begin,
- const char16* a_end,
- const char* b) {
- return DoLowerCaseEqualsASCII(a_begin, a_end, b);
-}
-#endif
-
-bool EqualsASCII(const string16& a, const base::StringPiece& b) {
- if (a.length() != b.length())
- return false;
- return std::equal(b.begin(), b.end(), a.begin());
-}
-
-bool StartsWithASCII(const std::string& str,
- const std::string& search,
- bool case_sensitive) {
- if (case_sensitive)
- return str.compare(0, search.length(), search) == 0;
- else
- return base::strncasecmp(str.c_str(), search.c_str(), search.length()) == 0;
-}
-
-template <typename STR>
-bool StartsWithT(const STR& str, const STR& search, bool case_sensitive) {
- if (case_sensitive) {
- return str.compare(0, search.length(), search) == 0;
- } else {
- if (search.size() > str.size())
- return false;
- return std::equal(search.begin(), search.end(), str.begin(),
- base::CaseInsensitiveCompare<typename STR::value_type>());
- }
-}
-
-bool StartsWith(const std::wstring& str, const std::wstring& search,
- bool case_sensitive) {
- return StartsWithT(str, search, case_sensitive);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool StartsWith(const string16& str, const string16& search,
- bool case_sensitive) {
- return StartsWithT(str, search, case_sensitive);
-}
-#endif
-
-template <typename STR>
-bool EndsWithT(const STR& str, const STR& search, bool case_sensitive) {
- typename STR::size_type str_length = str.length();
- typename STR::size_type search_length = search.length();
- if (search_length > str_length)
- return false;
- if (case_sensitive) {
- return str.compare(str_length - search_length, search_length, search) == 0;
- } else {
- return std::equal(search.begin(), search.end(),
- str.begin() + (str_length - search_length),
- base::CaseInsensitiveCompare<typename STR::value_type>());
- }
-}
-
-bool EndsWith(const std::string& str, const std::string& search,
- bool case_sensitive) {
- return EndsWithT(str, search, case_sensitive);
-}
-
-bool EndsWith(const std::wstring& str, const std::wstring& search,
- bool case_sensitive) {
- return EndsWithT(str, search, case_sensitive);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-bool EndsWith(const string16& str, const string16& search,
- bool case_sensitive) {
- return EndsWithT(str, search, case_sensitive);
-}
-#endif
-
-DataUnits GetByteDisplayUnits(int64 bytes) {
- // The byte thresholds at which we display amounts. A byte count is displayed
- // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1].
- // This must match the DataUnits enum.
- static const int64 kUnitThresholds[] = {
- 0, // DATA_UNITS_BYTE,
- 3*1024, // DATA_UNITS_KIBIBYTE,
- 2*1024*1024, // DATA_UNITS_MEBIBYTE,
- 1024*1024*1024 // DATA_UNITS_GIBIBYTE,
- };
-
- if (bytes < 0) {
- NOTREACHED() << "Negative bytes value";
- return DATA_UNITS_BYTE;
- }
-
- int unit_index = arraysize(kUnitThresholds);
- while (--unit_index > 0) {
- if (bytes >= kUnitThresholds[unit_index])
- break;
- }
-
- DCHECK(unit_index >= DATA_UNITS_BYTE && unit_index <= DATA_UNITS_GIBIBYTE);
- return DataUnits(unit_index);
-}
-
-// TODO(mpcomplete): deal with locale
-// Byte suffixes. This must match the DataUnits enum.
-static const char* const kByteStrings[] = {
- "B",
- "kB",
- "MB",
- "GB"
-};
-
-static const char* const kSpeedStrings[] = {
- "B/s",
- "kB/s",
- "MB/s",
- "GB/s"
-};
-
-string16 FormatBytesInternal(int64 bytes,
- DataUnits units,
- bool show_units,
- const char* const* suffix) {
- if (bytes < 0) {
- NOTREACHED() << "Negative bytes value";
- return string16();
- }
-
- DCHECK(units >= DATA_UNITS_BYTE && units <= DATA_UNITS_GIBIBYTE);
-
- // Put the quantity in the right units.
- double unit_amount = static_cast<double>(bytes);
- for (int i = 0; i < units; ++i)
- unit_amount /= 1024.0;
-
- char buf[64];
- if (bytes != 0 && units != DATA_UNITS_BYTE && unit_amount < 100)
- base::snprintf(buf, arraysize(buf), "%.1lf", unit_amount);
- else
- base::snprintf(buf, arraysize(buf), "%.0lf", unit_amount);
-
- std::string ret(buf);
- if (show_units) {
- ret += " ";
- ret += suffix[units];
- }
-
- return ASCIIToUTF16(ret);
-}
-
-string16 FormatBytes(int64 bytes, DataUnits units, bool show_units) {
- return FormatBytesInternal(bytes, units, show_units, kByteStrings);
-}
-
-string16 FormatSpeed(int64 bytes, DataUnits units, bool show_units) {
- return FormatBytesInternal(bytes, units, show_units, kSpeedStrings);
-}
-
-template<class StringType>
-void DoReplaceSubstringsAfterOffset(StringType* str,
- typename StringType::size_type start_offset,
- const StringType& find_this,
- const StringType& replace_with,
- bool replace_all) {
- if ((start_offset == StringType::npos) || (start_offset >= str->length()))
- return;
-
- DCHECK(!find_this.empty());
- for (typename StringType::size_type offs(str->find(find_this, start_offset));
- offs != StringType::npos; offs = str->find(find_this, offs)) {
- str->replace(offs, find_this.length(), replace_with);
- offs += replace_with.length();
-
- if (!replace_all)
- break;
- }
-}
-
-void ReplaceFirstSubstringAfterOffset(string16* str,
- string16::size_type start_offset,
- const string16& find_this,
- const string16& replace_with) {
- DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with,
- false); // replace first instance
-}
-
-void ReplaceFirstSubstringAfterOffset(std::string* str,
- std::string::size_type start_offset,
- const std::string& find_this,
- const std::string& replace_with) {
- DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with,
- false); // replace first instance
-}
-
-void ReplaceSubstringsAfterOffset(string16* str,
- string16::size_type start_offset,
- const string16& find_this,
- const string16& replace_with) {
- DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with,
- true); // replace all instances
-}
-
-void ReplaceSubstringsAfterOffset(std::string* str,
- std::string::size_type start_offset,
- const std::string& find_this,
- const std::string& replace_with) {
- DoReplaceSubstringsAfterOffset(str, start_offset, find_this, replace_with,
- true); // replace all instances
-}
-
-
-template<typename STR>
-static size_t TokenizeT(const STR& str,
- const STR& delimiters,
- std::vector<STR>* tokens) {
- tokens->clear();
-
- typename STR::size_type start = str.find_first_not_of(delimiters);
- while (start != STR::npos) {
- typename STR::size_type end = str.find_first_of(delimiters, start + 1);
- if (end == STR::npos) {
- tokens->push_back(str.substr(start));
- break;
- } else {
- tokens->push_back(str.substr(start, end - start));
- start = str.find_first_not_of(delimiters, end + 1);
- }
- }
-
- return tokens->size();
-}
-
-size_t Tokenize(const std::wstring& str,
- const std::wstring& delimiters,
- std::vector<std::wstring>* tokens) {
- return TokenizeT(str, delimiters, tokens);
-}
-
-#if !defined(WCHAR_T_IS_UTF16)
-size_t Tokenize(const string16& str,
- const string16& delimiters,
- std::vector<string16>* tokens) {
- return TokenizeT(str, delimiters, tokens);
-}
-#endif
-
-size_t Tokenize(const std::string& str,
- const std::string& delimiters,
- std::vector<std::string>* tokens) {
- return TokenizeT(str, delimiters, tokens);
-}
-
-size_t Tokenize(const base::StringPiece& str,
- const base::StringPiece& delimiters,
- std::vector<base::StringPiece>* tokens) {
- return TokenizeT(str, delimiters, tokens);
-}
-
-template<typename STR>
-static STR JoinStringT(const std::vector<STR>& parts,
- typename STR::value_type sep) {
- if (parts.empty())
- return STR();
-
- STR result(parts[0]);
- typename std::vector<STR>::const_iterator iter = parts.begin();
- ++iter;
-
- for (; iter != parts.end(); ++iter) {
- result += sep;
- result += *iter;
- }
-
- return result;
-}
-
-std::string JoinString(const std::vector<std::string>& parts, char sep) {
- return JoinStringT(parts, sep);
-}
-
-string16 JoinString(const std::vector<string16>& parts, char16 sep) {
- return JoinStringT(parts, sep);
-}
-
-template<class FormatStringType, class OutStringType>
-OutStringType DoReplaceStringPlaceholders(const FormatStringType& format_string,
- const std::vector<OutStringType>& subst, std::vector<size_t>* offsets) {
- size_t substitutions = subst.size();
- DCHECK(substitutions < 10);
-
- size_t sub_length = 0;
- for (typename std::vector<OutStringType>::const_iterator iter = subst.begin();
- iter != subst.end(); ++iter) {
- sub_length += iter->length();
- }
-
- OutStringType formatted;
- formatted.reserve(format_string.length() + sub_length);
-
- std::vector<ReplacementOffset> r_offsets;
- for (typename FormatStringType::const_iterator i = format_string.begin();
- i != format_string.end(); ++i) {
- if ('$' == *i) {
- if (i + 1 != format_string.end()) {
- ++i;
- DCHECK('$' == *i || '1' <= *i) << "Invalid placeholder: " << *i;
- if ('$' == *i) {
- while (i != format_string.end() && '$' == *i) {
- formatted.push_back('$');
- ++i;
- }
- --i;
- } else {
- uintptr_t index = *i - '1';
- if (offsets) {
- ReplacementOffset r_offset(index,
- static_cast<int>(formatted.size()));
- r_offsets.insert(std::lower_bound(r_offsets.begin(),
- r_offsets.end(),
- r_offset,
- &CompareParameter),
- r_offset);
- }
- if (index < substitutions)
- formatted.append(subst.at(index));
- }
- }
- } else {
- formatted.push_back(*i);
- }
- }
- if (offsets) {
- for (std::vector<ReplacementOffset>::const_iterator i = r_offsets.begin();
- i != r_offsets.end(); ++i) {
- offsets->push_back(i->offset);
- }
- }
- return formatted;
-}
-
-string16 ReplaceStringPlaceholders(const string16& format_string,
- const std::vector<string16>& subst,
- std::vector<size_t>* offsets) {
- return DoReplaceStringPlaceholders(format_string, subst, offsets);
-}
-
-std::string ReplaceStringPlaceholders(const base::StringPiece& format_string,
- const std::vector<std::string>& subst,
- std::vector<size_t>* offsets) {
- return DoReplaceStringPlaceholders(format_string, subst, offsets);
-}
-
-string16 ReplaceStringPlaceholders(const string16& format_string,
- const string16& a,
- size_t* offset) {
- std::vector<size_t> offsets;
- std::vector<string16> subst;
- subst.push_back(a);
- string16 result = ReplaceStringPlaceholders(format_string, subst, &offsets);
-
- DCHECK(offsets.size() == 1);
- if (offset) {
- *offset = offsets[0];
- }
- return result;
-}
-
-static bool IsWildcard(base_icu::UChar32 character) {
- return character == '*' || character == '?';
-}
-
-// Move the strings pointers to the point where they start to differ.
-template <typename CHAR, typename NEXT>
-static void EatSameChars(const CHAR** pattern, const CHAR* pattern_end,
- const CHAR** string, const CHAR* string_end,
- NEXT next) {
- const CHAR* escape = NULL;
- while (*pattern != pattern_end && *string != string_end) {
- if (!escape && IsWildcard(**pattern)) {
- // We don't want to match wildcard here, except if it's escaped.
- return;
- }
-
- // Check if the escapement char is found. If so, skip it and move to the
- // next character.
- if (!escape && **pattern == '\\') {
- escape = *pattern;
- next(pattern, pattern_end);
- continue;
- }
-
- // Check if the chars match, if so, increment the ptrs.
- const CHAR* pattern_next = *pattern;
- const CHAR* string_next = *string;
- base_icu::UChar32 pattern_char = next(&pattern_next, pattern_end);
- if (pattern_char == next(&string_next, string_end) &&
- pattern_char != (base_icu::UChar32) CBU_SENTINEL) {
- *pattern = pattern_next;
- *string = string_next;
- } else {
- // Uh ho, it did not match, we are done. If the last char was an
- // escapement, that means that it was an error to advance the ptr here,
- // let's put it back where it was. This also mean that the MatchPattern
- // function will return false because if we can't match an escape char
- // here, then no one will.
- if (escape) {
- *pattern = escape;
- }
- return;
- }
-
- escape = NULL;
- }
-}
-
-template <typename CHAR, typename NEXT>
-static void EatWildcard(const CHAR** pattern, const CHAR* end, NEXT next) {
- while (*pattern != end) {
- if (!IsWildcard(**pattern))
- return;
- next(pattern, end);
- }
-}
-
-template <typename CHAR, typename NEXT>
-static bool MatchPatternT(const CHAR* eval, const CHAR* eval_end,
- const CHAR* pattern, const CHAR* pattern_end,
- int depth,
- NEXT next) {
- const int kMaxDepth = 16;
- if (depth > kMaxDepth)
- return false;
-
- // Eat all the matching chars.
- EatSameChars(&pattern, pattern_end, &eval, eval_end, next);
-
- // If the string is empty, then the pattern must be empty too, or contains
- // only wildcards.
- if (eval == eval_end) {
- EatWildcard(&pattern, pattern_end, next);
- return pattern == pattern_end;
- }
-
- // Pattern is empty but not string, this is not a match.
- if (pattern == pattern_end)
- return false;
-
- // If this is a question mark, then we need to compare the rest with
- // the current string or the string with one character eaten.
- const CHAR* next_pattern = pattern;
- next(&next_pattern, pattern_end);
- if (pattern[0] == '?') {
- if (MatchPatternT(eval, eval_end, next_pattern, pattern_end,
- depth + 1, next))
- return true;
- const CHAR* next_eval = eval;
- next(&next_eval, eval_end);
- if (MatchPatternT(next_eval, eval_end, next_pattern, pattern_end,
- depth + 1, next))
- return true;
- }
-
- // This is a *, try to match all the possible substrings with the remainder
- // of the pattern.
- if (pattern[0] == '*') {
- // Collapse duplicate wild cards (********** into *) so that the
- // method does not recurse unnecessarily. http://crbug.com/52839
- EatWildcard(&next_pattern, pattern_end, next);
-
- while (eval != eval_end) {
- if (MatchPatternT(eval, eval_end, next_pattern, pattern_end,
- depth + 1, next))
- return true;
- eval++;
- }
-
- // We reached the end of the string, let see if the pattern contains only
- // wildcards.
- if (eval == eval_end) {
- EatWildcard(&pattern, pattern_end, next);
- if (pattern != pattern_end)
- return false;
- return true;
- }
- }
-
- return false;
-}
-
-struct NextCharUTF8 {
- base_icu::UChar32 operator()(const char** p, const char* end) {
- base_icu::UChar32 c;
- int offset = 0;
- CBU8_NEXT(*p, offset, end - *p, c);
- *p += offset;
- return c;
- }
-};
-
-struct NextCharUTF16 {
- base_icu::UChar32 operator()(const char16** p, const char16* end) {
- base_icu::UChar32 c;
- int offset = 0;
- CBU16_NEXT(*p, offset, end - *p, c);
- *p += offset;
- return c;
- }
-};
-
-bool MatchPattern(const base::StringPiece& eval,
- const base::StringPiece& pattern) {
- return MatchPatternT(eval.data(), eval.data() + eval.size(),
- pattern.data(), pattern.data() + pattern.size(),
- 0, NextCharUTF8());
-}
-
-bool MatchPattern(const string16& eval, const string16& pattern) {
- return MatchPatternT(eval.c_str(), eval.c_str() + eval.size(),
- pattern.c_str(), pattern.c_str() + pattern.size(),
- 0, NextCharUTF16());
-}
-
-// The following code is compatible with the OpenBSD lcpy interface. See:
-// http://www.gratisoft.us/todd/papers/strlcpy.html
-// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c
-
-namespace {
-
-template <typename CHAR>
-size_t lcpyT(CHAR* dst, const CHAR* src, size_t dst_size) {
- for (size_t i = 0; i < dst_size; ++i) {
- if ((dst[i] = src[i]) == 0) // We hit and copied the terminating NULL.
- return i;
- }
-
- // We were left off at dst_size. We over copied 1 byte. Null terminate.
- if (dst_size != 0)
- dst[dst_size - 1] = 0;
-
- // Count the rest of the |src|, and return it's length in characters.
- while (src[dst_size]) ++dst_size;
- return dst_size;
-}
-
-} // namespace
-
-size_t base::strlcpy(char* dst, const char* src, size_t dst_size) {
- return lcpyT<char>(dst, src, dst_size);
-}
-size_t base::wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size) {
- return lcpyT<wchar_t>(dst, src, dst_size);
-}

Powered by Google App Engine
This is Rietveld 408576698