Commit 7179fc9f authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Commit Bot

[base] Introduce wide string split utilities

This change implements wide string overloads to string_split.h
and string_util.h.
Since these functions are not supposed to be used by Cross-Platform
code it is guarded by correpsonding #ifdef guards. Furthermore,
this change performs some minor code clean-ups and performance
improvements.

Bug: 911896
Change-Id: I579b55a398307c890b30a027699b74a9afb1a77e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1823851
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#703617}
parent 1b186eeb
...@@ -219,8 +219,11 @@ size_t find_first_of(const StringPiece& self, ...@@ -219,8 +219,11 @@ size_t find_first_of(const StringPiece& self,
size_t find_first_of(const StringPiece16& self, size_t find_first_of(const StringPiece16& self,
const StringPiece16& s, const StringPiece16& s,
size_t pos) { size_t pos) {
// Use the faster std::find() if searching for a single character.
StringPiece16::const_iterator found = StringPiece16::const_iterator found =
std::find_first_of(self.begin() + pos, self.end(), s.begin(), s.end()); s.size() == 1 ? std::find(self.begin() + pos, self.end(), s[0])
: std::find_first_of(self.begin() + pos, self.end(),
s.begin(), s.end());
if (found == self.end()) if (found == self.end())
return StringPiece16::npos; return StringPiece16::npos;
return found - self.begin(); return found - self.begin();
......
...@@ -14,27 +14,15 @@ namespace base { ...@@ -14,27 +14,15 @@ namespace base {
namespace { namespace {
// PieceToOutputType converts a StringPiece as needed to a given output type,
// which is either the same type of StringPiece (a NOP) or the corresponding
// non-piece string type.
//
// The default converter is a NOP, it works when the OutputType is the
// correct StringPiece.
template<typename Str, typename OutputType>
OutputType PieceToOutputType(BasicStringPiece<Str> piece) {
return piece;
}
template<> // Convert StringPiece to std::string
std::string PieceToOutputType<std::string, std::string>(StringPiece piece) {
return piece.as_string();
}
template<> // Convert StringPiece16 to string16.
string16 PieceToOutputType<string16, string16>(StringPiece16 piece) {
return piece.as_string();
}
// Returns either the ASCII or UTF-16 whitespace. // Returns either the ASCII or UTF-16 whitespace.
template<typename Str> BasicStringPiece<Str> WhitespaceForType(); template<typename Str> BasicStringPiece<Str> WhitespaceForType();
#if defined(OS_WIN) && defined(BASE_STRING16_IS_STD_U16STRING)
template <>
WStringPiece WhitespaceForType<std::wstring>() {
return kWhitespaceWide;
}
#endif
template<> StringPiece16 WhitespaceForType<string16>() { template<> StringPiece16 WhitespaceForType<string16>() {
return kWhitespaceUTF16; return kWhitespaceUTF16;
} }
...@@ -42,37 +30,12 @@ template<> StringPiece WhitespaceForType<std::string>() { ...@@ -42,37 +30,12 @@ template<> StringPiece WhitespaceForType<std::string>() {
return kWhitespaceASCII; return kWhitespaceASCII;
} }
// Optimize the single-character case to call find() on the string instead,
// since this is the common case and can be made faster. This could have been
// done with template specialization too, but would have been less clear.
//
// There is no corresponding FindFirstNotOf because StringPiece already
// implements these different versions that do the optimized searching.
size_t FindFirstOf(StringPiece piece, char c, size_t pos) {
return piece.find(c, pos);
}
size_t FindFirstOf(StringPiece16 piece, char16 c, size_t pos) {
return piece.find(c, pos);
}
size_t FindFirstOf(StringPiece piece, StringPiece one_of, size_t pos) {
return piece.find_first_of(one_of, pos);
}
size_t FindFirstOf(StringPiece16 piece, StringPiece16 one_of, size_t pos) {
return piece.find_first_of(one_of, pos);
}
// General string splitter template. Can take 8- or 16-bit input, can produce // General string splitter template. Can take 8- or 16-bit input, can produce
// the corresponding string or StringPiece output, and can take single- or // the corresponding string or StringPiece output.
// multiple-character delimiters. template <typename OutputStringType, typename Str>
//
// DelimiterType is either a character (Str::value_type) or a string piece of
// multiple characters (BasicStringPiece<Str>). StringPiece has a version of
// find for both of these cases, and the single-character version is the most
// common and can be implemented faster, which is why this is a template.
template<typename Str, typename OutputStringType, typename DelimiterType>
static std::vector<OutputStringType> SplitStringT( static std::vector<OutputStringType> SplitStringT(
BasicStringPiece<Str> str, BasicStringPiece<Str> str,
DelimiterType delimiter, BasicStringPiece<Str> delimiter,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
std::vector<OutputStringType> result; std::vector<OutputStringType> result;
...@@ -81,7 +44,7 @@ static std::vector<OutputStringType> SplitStringT( ...@@ -81,7 +44,7 @@ static std::vector<OutputStringType> SplitStringT(
size_t start = 0; size_t start = 0;
while (start != Str::npos) { while (start != Str::npos) {
size_t end = FindFirstOf(str, delimiter, start); size_t end = str.find_first_of(delimiter, start);
BasicStringPiece<Str> piece; BasicStringPiece<Str> piece;
if (end == Str::npos) { if (end == Str::npos) {
...@@ -96,7 +59,7 @@ static std::vector<OutputStringType> SplitStringT( ...@@ -96,7 +59,7 @@ static std::vector<OutputStringType> SplitStringT(
piece = TrimString(piece, WhitespaceForType<Str>(), TRIM_ALL); piece = TrimString(piece, WhitespaceForType<Str>(), TRIM_ALL);
if (result_type == SPLIT_WANT_ALL || !piece.empty()) if (result_type == SPLIT_WANT_ALL || !piece.empty())
result.push_back(PieceToOutputType<Str, OutputStringType>(piece)); result.emplace_back(piece);
} }
return result; return result;
} }
...@@ -130,16 +93,16 @@ bool AppendStringKeyValue(StringPiece input, ...@@ -130,16 +93,16 @@ bool AppendStringKeyValue(StringPiece input,
return true; return true;
} }
template <typename Str, typename OutputStringType> template <typename OutputStringType, typename Str>
void SplitStringUsingSubstrT(BasicStringPiece<Str> input, std::vector<OutputStringType> SplitStringUsingSubstrT(
BasicStringPiece<Str> delimiter, BasicStringPiece<Str> input,
WhitespaceHandling whitespace, BasicStringPiece<Str> delimiter,
SplitResult result_type, WhitespaceHandling whitespace,
std::vector<OutputStringType>* result) { SplitResult result_type) {
using Piece = BasicStringPiece<Str>; using Piece = BasicStringPiece<Str>;
using size_type = typename Piece::size_type; using size_type = typename Piece::size_type;
result->clear(); std::vector<OutputStringType> result;
for (size_type begin_index = 0, end_index = 0; end_index != Piece::npos; for (size_type begin_index = 0, end_index = 0; end_index != Piece::npos;
begin_index = end_index + delimiter.size()) { begin_index = end_index + delimiter.size()) {
end_index = input.find(delimiter, begin_index); end_index = input.find(delimiter, begin_index);
...@@ -151,8 +114,10 @@ void SplitStringUsingSubstrT(BasicStringPiece<Str> input, ...@@ -151,8 +114,10 @@ void SplitStringUsingSubstrT(BasicStringPiece<Str> input,
term = TrimString(term, WhitespaceForType<Str>(), TRIM_ALL); term = TrimString(term, WhitespaceForType<Str>(), TRIM_ALL);
if (result_type == SPLIT_WANT_ALL || !term.empty()) if (result_type == SPLIT_WANT_ALL || !term.empty())
result->push_back(PieceToOutputType<Str, OutputStringType>(term)); result.emplace_back(term);
} }
return result;
} }
} // namespace } // namespace
...@@ -161,48 +126,29 @@ std::vector<std::string> SplitString(StringPiece input, ...@@ -161,48 +126,29 @@ std::vector<std::string> SplitString(StringPiece input,
StringPiece separators, StringPiece separators,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
if (separators.size() == 1) { return SplitStringT<std::string>(input, separators, whitespace, result_type);
return SplitStringT<std::string, std::string, char>(
input, separators[0], whitespace, result_type);
}
return SplitStringT<std::string, std::string, StringPiece>(
input, separators, whitespace, result_type);
} }
std::vector<string16> SplitString(StringPiece16 input, std::vector<string16> SplitString(StringPiece16 input,
StringPiece16 separators, StringPiece16 separators,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
if (separators.size() == 1) { return SplitStringT<string16>(input, separators, whitespace, result_type);
return SplitStringT<string16, string16, char16>(
input, separators[0], whitespace, result_type);
}
return SplitStringT<string16, string16, StringPiece16>(
input, separators, whitespace, result_type);
} }
std::vector<StringPiece> SplitStringPiece(StringPiece input, std::vector<StringPiece> SplitStringPiece(StringPiece input,
StringPiece separators, StringPiece separators,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
if (separators.size() == 1) { return SplitStringT<StringPiece>(input, separators, whitespace, result_type);
return SplitStringT<std::string, StringPiece, char>(
input, separators[0], whitespace, result_type);
}
return SplitStringT<std::string, StringPiece, StringPiece>(
input, separators, whitespace, result_type);
} }
std::vector<StringPiece16> SplitStringPiece(StringPiece16 input, std::vector<StringPiece16> SplitStringPiece(StringPiece16 input,
StringPiece16 separators, StringPiece16 separators,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
if (separators.size() == 1) { return SplitStringT<StringPiece16>(input, separators, whitespace,
return SplitStringT<string16, StringPiece16, char16>( result_type);
input, separators[0], whitespace, result_type);
}
return SplitStringT<string16, StringPiece16, StringPiece16>(
input, separators, whitespace, result_type);
} }
bool SplitStringIntoKeyValuePairs(StringPiece input, bool SplitStringIntoKeyValuePairs(StringPiece input,
...@@ -240,18 +186,16 @@ std::vector<string16> SplitStringUsingSubstr(StringPiece16 input, ...@@ -240,18 +186,16 @@ std::vector<string16> SplitStringUsingSubstr(StringPiece16 input,
StringPiece16 delimiter, StringPiece16 delimiter,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
std::vector<string16> result; return SplitStringUsingSubstrT<string16>(input, delimiter, whitespace,
SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); result_type);
return result;
} }
std::vector<std::string> SplitStringUsingSubstr(StringPiece input, std::vector<std::string> SplitStringUsingSubstr(StringPiece input,
StringPiece delimiter, StringPiece delimiter,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
std::vector<std::string> result; return SplitStringUsingSubstrT<std::string>(input, delimiter, whitespace,
SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); result_type);
return result;
} }
std::vector<StringPiece16> SplitStringPieceUsingSubstr( std::vector<StringPiece16> SplitStringPieceUsingSubstr(
...@@ -260,8 +204,8 @@ std::vector<StringPiece16> SplitStringPieceUsingSubstr( ...@@ -260,8 +204,8 @@ std::vector<StringPiece16> SplitStringPieceUsingSubstr(
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
std::vector<StringPiece16> result; std::vector<StringPiece16> result;
SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); return SplitStringUsingSubstrT<StringPiece16>(input, delimiter, whitespace,
return result; result_type);
} }
std::vector<StringPiece> SplitStringPieceUsingSubstr( std::vector<StringPiece> SplitStringPieceUsingSubstr(
...@@ -269,9 +213,41 @@ std::vector<StringPiece> SplitStringPieceUsingSubstr( ...@@ -269,9 +213,41 @@ std::vector<StringPiece> SplitStringPieceUsingSubstr(
StringPiece delimiter, StringPiece delimiter,
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type) { SplitResult result_type) {
std::vector<StringPiece> result; return SplitStringUsingSubstrT<StringPiece>(input, delimiter, whitespace,
SplitStringUsingSubstrT(input, delimiter, whitespace, result_type, &result); result_type);
return result; }
#if defined(OS_WIN) && defined(BASE_STRING16_IS_STD_U16STRING)
std::vector<std::wstring> SplitString(WStringPiece input,
WStringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type) {
return SplitStringT<std::wstring>(input, separators, whitespace, result_type);
}
std::vector<WStringPiece> SplitStringPiece(WStringPiece input,
WStringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type) {
return SplitStringT<WStringPiece>(input, separators, whitespace, result_type);
}
std::vector<std::wstring> SplitStringUsingSubstr(WStringPiece input,
WStringPiece delimiter,
WhitespaceHandling whitespace,
SplitResult result_type) {
return SplitStringUsingSubstrT<std::wstring>(input, delimiter, whitespace,
result_type);
}
std::vector<WStringPiece> SplitStringPieceUsingSubstr(
WStringPiece input,
WStringPiece delimiter,
WhitespaceHandling whitespace,
SplitResult result_type) {
return SplitStringUsingSubstrT<WStringPiece>(input, delimiter, whitespace,
result_type);
} }
#endif
} // namespace base } // namespace base
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "build/build_config.h"
namespace base { namespace base {
...@@ -132,6 +133,31 @@ BASE_EXPORT std::vector<StringPiece> SplitStringPieceUsingSubstr( ...@@ -132,6 +133,31 @@ BASE_EXPORT std::vector<StringPiece> SplitStringPieceUsingSubstr(
WhitespaceHandling whitespace, WhitespaceHandling whitespace,
SplitResult result_type); SplitResult result_type);
#if defined(OS_WIN) && defined(BASE_STRING16_IS_STD_U16STRING)
BASE_EXPORT std::vector<std::wstring> SplitString(WStringPiece input,
WStringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type);
BASE_EXPORT std::vector<WStringPiece> SplitStringPiece(
WStringPiece input,
WStringPiece separators,
WhitespaceHandling whitespace,
SplitResult result_type);
BASE_EXPORT std::vector<std::wstring> SplitStringUsingSubstr(
WStringPiece input,
WStringPiece delimiter,
WhitespaceHandling whitespace,
SplitResult result_type);
BASE_EXPORT std::vector<WStringPiece> SplitStringPieceUsingSubstr(
WStringPiece input,
WStringPiece delimiter,
WhitespaceHandling whitespace,
SplitResult result_type);
#endif
} // namespace base } // namespace base
#endif // BASE_STRINGS_STRING_SPLIT_H_ #endif // BASE_STRINGS_STRING_SPLIT_H_
...@@ -262,8 +262,8 @@ bool RemoveChars(const std::string& input, ...@@ -262,8 +262,8 @@ bool RemoveChars(const std::string& input,
return ReplaceCharsT(input, remove_chars, StringPiece(), output); return ReplaceCharsT(input, remove_chars, StringPiece(), output);
} }
template<typename Str> template <typename Str>
TrimPositions TrimStringT(const Str& input, TrimPositions TrimStringT(BasicStringPiece<Str> input,
BasicStringPiece<Str> trim_chars, BasicStringPiece<Str> trim_chars,
TrimPositions positions, TrimPositions positions,
Str* output) { Str* output) {
...@@ -271,40 +271,40 @@ TrimPositions TrimStringT(const Str& input, ...@@ -271,40 +271,40 @@ TrimPositions TrimStringT(const Str& input,
// a StringPiece version of input to be able to call find* on it with the // a StringPiece version of input to be able to call find* on it with the
// StringPiece version of trim_chars (normally the trim_chars will be a // StringPiece version of trim_chars (normally the trim_chars will be a
// constant so avoid making a copy). // constant so avoid making a copy).
BasicStringPiece<Str> input_piece(input);
const size_t last_char = input.length() - 1; const size_t last_char = input.length() - 1;
const size_t first_good_char = (positions & TRIM_LEADING) ? const size_t first_good_char =
input_piece.find_first_not_of(trim_chars) : 0; (positions & TRIM_LEADING) ? input.find_first_not_of(trim_chars) : 0;
const size_t last_good_char = (positions & TRIM_TRAILING) ? const size_t last_good_char = (positions & TRIM_TRAILING)
input_piece.find_last_not_of(trim_chars) : last_char; ? input.find_last_not_of(trim_chars)
: last_char;
// When the string was all trimmed, report that we stripped off characters // When the string was all trimmed, report that we stripped off characters
// from whichever position the caller was interested in. For empty input, we // from whichever position the caller was interested in. For empty input, we
// stripped no characters, but we still need to clear |output|. // stripped no characters, but we still need to clear |output|.
if (input.empty() || if (input.empty() || first_good_char == Str::npos ||
(first_good_char == Str::npos) || (last_good_char == Str::npos)) { last_good_char == Str::npos) {
bool input_was_empty = input.empty(); // in case output == &input bool input_was_empty = input.empty(); // in case output == &input
output->clear(); output->clear();
return input_was_empty ? TRIM_NONE : positions; return input_was_empty ? TRIM_NONE : positions;
} }
// Trim. // Trim.
*output = output->assign(input.data() + first_good_char,
input.substr(first_good_char, last_good_char - first_good_char + 1); last_good_char - first_good_char + 1);
// Return where we trimmed from. // Return where we trimmed from.
return static_cast<TrimPositions>( return static_cast<TrimPositions>(
((first_good_char == 0) ? TRIM_NONE : TRIM_LEADING) | (first_good_char == 0 ? TRIM_NONE : TRIM_LEADING) |
((last_good_char == last_char) ? TRIM_NONE : TRIM_TRAILING)); (last_good_char == last_char ? TRIM_NONE : TRIM_TRAILING));
} }
bool TrimString(const string16& input, bool TrimString(StringPiece16 input,
StringPiece16 trim_chars, StringPiece16 trim_chars,
string16* output) { string16* output) {
return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
} }
bool TrimString(const std::string& input, bool TrimString(StringPiece input,
StringPiece trim_chars, StringPiece trim_chars,
std::string* output) { std::string* output) {
return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE; return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
...@@ -370,7 +370,7 @@ void TruncateUTF8ToByteSize(const std::string& input, ...@@ -370,7 +370,7 @@ void TruncateUTF8ToByteSize(const std::string& input,
output->clear(); output->clear();
} }
TrimPositions TrimWhitespace(const string16& input, TrimPositions TrimWhitespace(StringPiece16 input,
TrimPositions positions, TrimPositions positions,
string16* output) { string16* output) {
return TrimStringT(input, StringPiece16(kWhitespaceUTF16), positions, output); return TrimStringT(input, StringPiece16(kWhitespaceUTF16), positions, output);
...@@ -381,7 +381,7 @@ StringPiece16 TrimWhitespace(StringPiece16 input, ...@@ -381,7 +381,7 @@ StringPiece16 TrimWhitespace(StringPiece16 input,
return TrimStringPieceT(input, StringPiece16(kWhitespaceUTF16), positions); return TrimStringPieceT(input, StringPiece16(kWhitespaceUTF16), positions);
} }
TrimPositions TrimWhitespaceASCII(const std::string& input, TrimPositions TrimWhitespaceASCII(StringPiece input,
TrimPositions positions, TrimPositions positions,
std::string* output) { std::string* output) {
return TrimStringT(input, StringPiece(kWhitespaceASCII), positions, output); return TrimStringT(input, StringPiece(kWhitespaceASCII), positions, output);
...@@ -1085,6 +1085,32 @@ string16 ReplaceStringPlaceholders(const string16& format_string, ...@@ -1085,6 +1085,32 @@ string16 ReplaceStringPlaceholders(const string16& format_string,
return result; return result;
} }
#if defined(OS_WIN) && defined(BASE_STRING16_IS_STD_U16STRING)
TrimPositions TrimWhitespace(WStringPiece input,
TrimPositions positions,
std::wstring* output) {
return TrimStringT(input, WStringPiece(kWhitespaceWide), positions, output);
}
WStringPiece TrimWhitespace(WStringPiece input, TrimPositions positions) {
return TrimStringPieceT(input, WStringPiece(kWhitespaceWide), positions);
}
bool TrimString(WStringPiece input,
WStringPiece trim_chars,
std::wstring* output) {
return TrimStringT(input, trim_chars, TRIM_ALL, output) != TRIM_NONE;
}
WStringPiece TrimString(WStringPiece input,
WStringPiece trim_chars,
TrimPositions positions) {
return TrimStringPieceT(input, trim_chars, positions);
}
#endif
// The following code is compatible with the OpenBSD lcpy interface. See: // The following code is compatible with the OpenBSD lcpy interface. See:
// http://www.gratisoft.us/todd/papers/strlcpy.html // http://www.gratisoft.us/todd/papers/strlcpy.html
// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c // ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c
......
...@@ -204,10 +204,10 @@ enum TrimPositions { ...@@ -204,10 +204,10 @@ enum TrimPositions {
// //
// It is safe to use the same variable for both |input| and |output| (this is // It is safe to use the same variable for both |input| and |output| (this is
// the normal usage to trim in-place). // the normal usage to trim in-place).
BASE_EXPORT bool TrimString(const string16& input, BASE_EXPORT bool TrimString(StringPiece16 input,
StringPiece16 trim_chars, StringPiece16 trim_chars,
string16* output); string16* output);
BASE_EXPORT bool TrimString(const std::string& input, BASE_EXPORT bool TrimString(StringPiece input,
StringPiece trim_chars, StringPiece trim_chars,
std::string* output); std::string* output);
...@@ -296,12 +296,12 @@ inline string16 AsString16(WStringPiece str) { ...@@ -296,12 +296,12 @@ inline string16 AsString16(WStringPiece str) {
// //
// The std::string versions return where whitespace was found. // The std::string versions return where whitespace was found.
// NOTE: Safe to use the same variable for both input and output. // NOTE: Safe to use the same variable for both input and output.
BASE_EXPORT TrimPositions TrimWhitespace(const string16& input, BASE_EXPORT TrimPositions TrimWhitespace(StringPiece16 input,
TrimPositions positions, TrimPositions positions,
string16* output); string16* output);
BASE_EXPORT StringPiece16 TrimWhitespace(StringPiece16 input, BASE_EXPORT StringPiece16 TrimWhitespace(StringPiece16 input,
TrimPositions positions); TrimPositions positions);
BASE_EXPORT TrimPositions TrimWhitespaceASCII(const std::string& input, BASE_EXPORT TrimPositions TrimWhitespaceASCII(StringPiece input,
TrimPositions positions, TrimPositions positions,
std::string* output); std::string* output);
BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input, BASE_EXPORT StringPiece TrimWhitespaceASCII(StringPiece input,
...@@ -532,6 +532,23 @@ BASE_EXPORT string16 ReplaceStringPlaceholders(const string16& format_string, ...@@ -532,6 +532,23 @@ BASE_EXPORT string16 ReplaceStringPlaceholders(const string16& format_string,
const string16& a, const string16& a,
size_t* offset); size_t* offset);
#if defined(OS_WIN) && defined(BASE_STRING16_IS_STD_U16STRING)
BASE_EXPORT TrimPositions TrimWhitespace(WStringPiece input,
TrimPositions positions,
std::wstring* output);
BASE_EXPORT WStringPiece TrimWhitespace(WStringPiece input,
TrimPositions positions);
BASE_EXPORT bool TrimString(WStringPiece input,
WStringPiece trim_chars,
std::wstring* output);
BASE_EXPORT WStringPiece TrimString(WStringPiece input,
WStringPiece trim_chars,
TrimPositions positions);
#endif
} // namespace base } // namespace base
#if defined(OS_WIN) #if defined(OS_WIN)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment