Export of internal Abseil changes.
-- f9f068aa8a260dc576398e47b8e4540902e41358 by Derek Mauro <dmauro@google.com>: Fix test string with embedded NUL. Currently parses as octal. PiperOrigin-RevId: 237088193 -- d271ffdd3f450f817f6d30e98ff39d439aaf3a98 by Abseil Team <absl-team@google.com>: Make symbolizer examine any mapping with read+exec permission regardless of 'w' bit. PiperOrigin-RevId: 237056461 -- af315f8306d36a7367a452fd0b58cafdbf20719d by Abseil Team <absl-team@google.com>: Switch comments referencing base:: CondVar and Mutex to absl::. PiperOrigin-RevId: 236917884 -- c624d5d1c0bdb917bff5e651ba40599472f84e0e by Gennadiy Rozental <rogeeff@google.com>: Internal change PiperOrigin-RevId: 236898300 -- 3cdc82429af964846d1152f49148abc61d196a4b by Samuel Benzaquen <sbenza@google.com>: Make the `long double` overload if AbslHashValue a template to avoid invalid conversions with implicit operators. This overload was never meant to capture anything other than `long double` and any current caller to it that wasn't a `long double` is potentially a bug. In particular, any type with an implicit `bool` conversion is calling this overload instead of trying to find a hash<> specialization, thus causing pretty bad hash behavior. PiperOrigin-RevId: 236877073 GitOrigin-RevId: f9f068aa8a260dc576398e47b8e4540902e41358 Change-Id: If9cc008dd814f0ca06ed881f612c06575f1f7137
This commit is contained in:
parent
9fdf5e5b80
commit
febc5ee6a9
70 changed files with 483 additions and 410 deletions
|
|
@ -279,7 +279,8 @@ void TestHalfwayValue(const std::string& mantissa, int exponent,
|
|||
absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low);
|
||||
EXPECT_EQ(expected_low, actual_low);
|
||||
|
||||
std::string high_rep = absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
|
||||
std::string high_rep =
|
||||
absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
|
||||
FloatType actual_high = 0;
|
||||
absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(),
|
||||
actual_high);
|
||||
|
|
|
|||
|
|
@ -179,7 +179,8 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
|
|||
ch = (ch << 4) + hex_digit_to_int(*++p);
|
||||
if (ch > 0xFF) {
|
||||
if (error) {
|
||||
*error = "Value of \\" + std::string(hex_start, p + 1 - hex_start) +
|
||||
*error = "Value of \\" +
|
||||
std::string(hex_start, p + 1 - hex_start) +
|
||||
" exceeds 0xff";
|
||||
}
|
||||
return false;
|
||||
|
|
@ -294,7 +295,7 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
|
|||
// ----------------------------------------------------------------------
|
||||
// CUnescapeInternal()
|
||||
//
|
||||
// Same as above but uses a C++ string for output. 'source' and 'dest'
|
||||
// Same as above but uses a std::string for output. 'source' and 'dest'
|
||||
// may be the same.
|
||||
// ----------------------------------------------------------------------
|
||||
bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
|
||||
|
|
@ -324,7 +325,8 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
|
|||
//
|
||||
// Escaped chars: \n, \r, \t, ", ', \, and !absl::ascii_isprint().
|
||||
// ----------------------------------------------------------------------
|
||||
std::string CEscapeInternal(absl::string_view src, bool use_hex, bool utf8_safe) {
|
||||
std::string CEscapeInternal(absl::string_view src, bool use_hex,
|
||||
bool utf8_safe) {
|
||||
std::string dest;
|
||||
bool last_hex_escape = false; // true if last output char was \xNN.
|
||||
|
||||
|
|
@ -1011,7 +1013,8 @@ void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
|
|||
}
|
||||
}
|
||||
|
||||
// This is a templated function so that T can be either a char* or a string.
|
||||
// This is a templated function so that T can be either a char* or a
|
||||
// std::string.
|
||||
template <typename T>
|
||||
void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
|
||||
auto dest_ptr = &dest[0];
|
||||
|
|
@ -1028,7 +1031,8 @@ void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
|
|||
//
|
||||
// See CUnescapeInternal() for implementation details.
|
||||
// ----------------------------------------------------------------------
|
||||
bool CUnescape(absl::string_view source, std::string* dest, std::string* error) {
|
||||
bool CUnescape(absl::string_view source, std::string* dest,
|
||||
std::string* error) {
|
||||
return CUnescapeInternal(source, kUnescapeNulls, dest, error);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,18 +36,19 @@ struct epair {
|
|||
|
||||
TEST(CEscape, EscapeAndUnescape) {
|
||||
const std::string inputs[] = {
|
||||
std::string("foo\nxx\r\b\0023"),
|
||||
std::string(""),
|
||||
std::string("abc"),
|
||||
std::string("\1chad_rules"),
|
||||
std::string("\1arnar_drools"),
|
||||
std::string("xxxx\r\t'\"\\"),
|
||||
std::string("\0xx\0", 4),
|
||||
std::string("\x01\x31"),
|
||||
std::string("abc\xb\x42\141bc"),
|
||||
std::string("123\1\x31\x32\x33"),
|
||||
std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
|
||||
std::string("\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
|
||||
std::string("foo\nxx\r\b\0023"),
|
||||
std::string(""),
|
||||
std::string("abc"),
|
||||
std::string("\1chad_rules"),
|
||||
std::string("\1arnar_drools"),
|
||||
std::string("xxxx\r\t'\"\\"),
|
||||
std::string("\0xx\0", 4),
|
||||
std::string("\x01\x31"),
|
||||
std::string("abc\xb\x42\141bc"),
|
||||
std::string("123\1\x31\x32\x33"),
|
||||
std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
|
||||
std::string(
|
||||
"\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
|
||||
};
|
||||
// Do this twice, once for octal escapes and once for hex escapes.
|
||||
for (int kind = 0; kind < 4; kind++) {
|
||||
|
|
@ -159,15 +160,14 @@ TEST(Unescape, BasicFunction) {
|
|||
EXPECT_TRUE(absl::CUnescape(val.escaped, &out));
|
||||
EXPECT_EQ(out, val.unescaped);
|
||||
}
|
||||
std::string bad[] =
|
||||
{"\\u1", // too short
|
||||
"\\U1", // too short
|
||||
"\\Uffffff", // exceeds 0x10ffff (largest Unicode)
|
||||
"\\U00110000", // exceeds 0x10ffff (largest Unicode)
|
||||
"\\uD835", // surrogate character (D800-DFFF)
|
||||
"\\U0000DD04", // surrogate character (D800-DFFF)
|
||||
"\\777", // exceeds 0xff
|
||||
"\\xABCD"}; // exceeds 0xff
|
||||
std::string bad[] = {"\\u1", // too short
|
||||
"\\U1", // too short
|
||||
"\\Uffffff", // exceeds 0x10ffff (largest Unicode)
|
||||
"\\U00110000", // exceeds 0x10ffff (largest Unicode)
|
||||
"\\uD835", // surrogate character (D800-DFFF)
|
||||
"\\U0000DD04", // surrogate character (D800-DFFF)
|
||||
"\\777", // exceeds 0xff
|
||||
"\\xABCD"}; // exceeds 0xff
|
||||
for (const std::string& e : bad) {
|
||||
std::string error;
|
||||
std::string out;
|
||||
|
|
@ -258,9 +258,11 @@ TEST_F(CUnescapeTest, UnescapesMultipleOctalNulls) {
|
|||
// All escapes, including newlines and null escapes, should have been
|
||||
// converted to the equivalent characters.
|
||||
EXPECT_EQ(std::string("\0\n"
|
||||
"0\n"
|
||||
"\0\n"
|
||||
"\0", 7), result_string_);
|
||||
"0\n"
|
||||
"\0\n"
|
||||
"\0",
|
||||
7),
|
||||
result_string_);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -268,17 +270,21 @@ TEST_F(CUnescapeTest, UnescapesMultipleHexNulls) {
|
|||
std::string original_string(kStringWithMultipleHexNulls);
|
||||
EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
|
||||
EXPECT_EQ(std::string("\0\n"
|
||||
"0\n"
|
||||
"\0\n"
|
||||
"\0", 7), result_string_);
|
||||
"0\n"
|
||||
"\0\n"
|
||||
"\0",
|
||||
7),
|
||||
result_string_);
|
||||
}
|
||||
|
||||
TEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) {
|
||||
std::string original_string(kStringWithMultipleUnicodeNulls);
|
||||
EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
|
||||
EXPECT_EQ(std::string("\0\n"
|
||||
"0\n"
|
||||
"\0", 5), result_string_);
|
||||
"0\n"
|
||||
"\0",
|
||||
5),
|
||||
result_string_);
|
||||
}
|
||||
|
||||
static struct {
|
||||
|
|
|
|||
|
|
@ -25,18 +25,18 @@
|
|||
namespace absl {
|
||||
namespace strings_internal {
|
||||
|
||||
// The same as std::ostringstream but appends to a user-specified string,
|
||||
// The same as std::ostringstream but appends to a user-specified std::string,
|
||||
// and is faster. It is ~70% faster to create, ~50% faster to write to, and
|
||||
// completely free to extract the result string.
|
||||
// completely free to extract the result std::string.
|
||||
//
|
||||
// string s;
|
||||
// std::string s;
|
||||
// OStringStream strm(&s);
|
||||
// strm << 42 << ' ' << 3.14; // appends to `s`
|
||||
//
|
||||
// The stream object doesn't have to be named. Starting from C++11 operator<<
|
||||
// works with rvalues of std::ostream.
|
||||
//
|
||||
// string s;
|
||||
// std::string s;
|
||||
// OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s`
|
||||
//
|
||||
// OStringStream is faster to create than std::ostringstream but it's still
|
||||
|
|
@ -45,14 +45,14 @@ namespace strings_internal {
|
|||
//
|
||||
// Creates unnecessary instances of OStringStream: slow.
|
||||
//
|
||||
// string s;
|
||||
// std::string s;
|
||||
// OStringStream(&s) << 42;
|
||||
// OStringStream(&s) << ' ';
|
||||
// OStringStream(&s) << 3.14;
|
||||
//
|
||||
// Creates a single instance of OStringStream and reuses it: fast.
|
||||
//
|
||||
// string s;
|
||||
// std::string s;
|
||||
// OStringStream strm(&s);
|
||||
// strm << 42;
|
||||
// strm << ' ';
|
||||
|
|
@ -64,8 +64,8 @@ class OStringStream : private std::basic_streambuf<char>, public std::ostream {
|
|||
// The argument can be null, in which case you'll need to call str(p) with a
|
||||
// non-null argument before you can write to the stream.
|
||||
//
|
||||
// The destructor of OStringStream doesn't use the std::string. It's OK to destroy
|
||||
// the std::string before the stream.
|
||||
// The destructor of OStringStream doesn't use the std::string. It's OK to
|
||||
// destroy the std::string before the stream.
|
||||
explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {}
|
||||
|
||||
std::string* str() { return s_; }
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ struct ResizeUninitializedTraits<
|
|||
}
|
||||
};
|
||||
|
||||
// Returns true if the string implementation supports a resize where
|
||||
// the new characters added to the string are left untouched.
|
||||
// Returns true if the std::string implementation supports a resize where
|
||||
// the new characters added to the std::string are left untouched.
|
||||
//
|
||||
// (A better name might be "STLStringSupportsUninitializedResize", alluding to
|
||||
// the previous function.)
|
||||
|
|
@ -60,7 +60,7 @@ inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
|
|||
// Like str->resize(new_size), except any new characters added to "*str" as a
|
||||
// result of resizing may be left uninitialized, rather than being filled with
|
||||
// '0' bytes. Typically used when code is then going to overwrite the backing
|
||||
// store of the string with known data. Uses a Google extension to ::string.
|
||||
// store of the std::string with known data.
|
||||
template <typename string_type, typename = void>
|
||||
inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
|
||||
ResizeUninitializedTraits<string_type>::Resize(s, new_size);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
|
|||
FormatSinkImpl* sink);
|
||||
|
||||
// Strings.
|
||||
ConvertResult<Conv::s> FormatConvertImpl(const std::string& v, ConversionSpec conv,
|
||||
ConvertResult<Conv::s> FormatConvertImpl(const std::string& v,
|
||||
ConversionSpec conv,
|
||||
FormatSinkImpl* sink);
|
||||
ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
|
||||
FormatSinkImpl* sink);
|
||||
|
|
@ -409,7 +410,7 @@ class FormatArgImpl {
|
|||
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \
|
||||
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \
|
||||
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \
|
||||
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \
|
||||
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \
|
||||
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
|
||||
|
||||
ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ bool BindWithPack(const UnboundConversion* props,
|
|||
}
|
||||
|
||||
std::string Summarize(const UntypedFormatSpecImpl format,
|
||||
absl::Span<const FormatArgImpl> args) {
|
||||
absl::Span<const FormatArgImpl> args) {
|
||||
typedef SummarizingConverter Converter;
|
||||
std::string out;
|
||||
{
|
||||
|
|
@ -188,7 +188,7 @@ std::ostream& Streamable::Print(std::ostream& os) const {
|
|||
}
|
||||
|
||||
std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,
|
||||
absl::Span<const FormatArgImpl> args) {
|
||||
absl::Span<const FormatArgImpl> args) {
|
||||
size_t orig = out->size();
|
||||
if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {
|
||||
out->erase(orig);
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ class Streamable {
|
|||
|
||||
// for testing
|
||||
std::string Summarize(UntypedFormatSpecImpl format,
|
||||
absl::Span<const FormatArgImpl> args);
|
||||
absl::Span<const FormatArgImpl> args);
|
||||
bool BindWithPack(const UnboundConversion* props,
|
||||
absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
|
||||
|
||||
|
|
@ -162,10 +162,10 @@ bool FormatUntyped(FormatRawSinkImpl raw_sink,
|
|||
absl::Span<const FormatArgImpl> args);
|
||||
|
||||
std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
|
||||
absl::Span<const FormatArgImpl> args);
|
||||
absl::Span<const FormatArgImpl> args);
|
||||
|
||||
inline std::string FormatPack(const UntypedFormatSpecImpl format,
|
||||
absl::Span<const FormatArgImpl> args) {
|
||||
absl::Span<const FormatArgImpl> args) {
|
||||
std::string out;
|
||||
AppendPack(&out, format, args);
|
||||
return out;
|
||||
|
|
@ -176,7 +176,7 @@ int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
|
|||
int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
|
||||
absl::Span<const FormatArgImpl> args);
|
||||
|
||||
// Returned by Streamed(v). Converts via '%s' to the string created
|
||||
// Returned by Streamed(v). Converts via '%s' to the std::string created
|
||||
// by std::ostream << v.
|
||||
template <typename T>
|
||||
class StreamedWrapper {
|
||||
|
|
|
|||
|
|
@ -62,32 +62,32 @@ TEST(StrFormatChecker, ValidFormat) {
|
|||
ValidFormat<int>("%% %d"), //
|
||||
ValidFormat<int>("%ld"), //
|
||||
ValidFormat<int>("%lld"), //
|
||||
ValidFormat<std::string>("%s"), //
|
||||
ValidFormat<std::string>("%10s"), //
|
||||
ValidFormat<std::string>("%s"), //
|
||||
ValidFormat<std::string>("%10s"), //
|
||||
ValidFormat<int>("%.10x"), //
|
||||
ValidFormat<int, int>("%*.3x"), //
|
||||
ValidFormat<int>("%1.d"), //
|
||||
ValidFormat<int>("%.d"), //
|
||||
ValidFormat<int, double>("%d %g"), //
|
||||
ValidFormat<int, std::string>("%*s"), //
|
||||
ValidFormat<int, std::string>("%*s"), //
|
||||
ValidFormat<int, double>("%.*f"), //
|
||||
ValidFormat<void (*)(), volatile int*>("%p %p"), //
|
||||
ValidFormat<string_view, const char*, double, void*>(
|
||||
"string_view=%s const char*=%s double=%f void*=%p)"),
|
||||
|
||||
ValidFormat<int>("%% %1$d"), //
|
||||
ValidFormat<int>("%1$ld"), //
|
||||
ValidFormat<int>("%1$lld"), //
|
||||
ValidFormat<std::string>("%1$s"), //
|
||||
ValidFormat<std::string>("%1$10s"), //
|
||||
ValidFormat<int>("%1$.10x"), //
|
||||
ValidFormat<int>("%1$*1$.*1$d"), //
|
||||
ValidFormat<int, int>("%1$*2$.3x"), //
|
||||
ValidFormat<int>("%1$1.d"), //
|
||||
ValidFormat<int>("%1$.d"), //
|
||||
ValidFormat<double, int>("%2$d %1$g"), //
|
||||
ValidFormat<int, std::string>("%2$*1$s"), //
|
||||
ValidFormat<int, double>("%2$.*1$f"), //
|
||||
ValidFormat<int>("%% %1$d"), //
|
||||
ValidFormat<int>("%1$ld"), //
|
||||
ValidFormat<int>("%1$lld"), //
|
||||
ValidFormat<std::string>("%1$s"), //
|
||||
ValidFormat<std::string>("%1$10s"), //
|
||||
ValidFormat<int>("%1$.10x"), //
|
||||
ValidFormat<int>("%1$*1$.*1$d"), //
|
||||
ValidFormat<int, int>("%1$*2$.3x"), //
|
||||
ValidFormat<int>("%1$1.d"), //
|
||||
ValidFormat<int>("%1$.d"), //
|
||||
ValidFormat<double, int>("%2$d %1$g"), //
|
||||
ValidFormat<int, std::string>("%2$*1$s"), //
|
||||
ValidFormat<int, double>("%2$.*1$f"), //
|
||||
ValidFormat<void*, string_view, const char*, double>(
|
||||
"string_view=%2$s const char*=%3$s double=%4$f void*=%1$p "
|
||||
"repeat=%3$s)")};
|
||||
|
|
@ -99,25 +99,25 @@ TEST(StrFormatChecker, ValidFormat) {
|
|||
constexpr Case falses[] = {
|
||||
ValidFormat<int>(""), //
|
||||
|
||||
ValidFormat<e>("%s"), //
|
||||
ValidFormat<e2>("%s"), //
|
||||
ValidFormat<>("%s"), //
|
||||
ValidFormat<>("%r"), //
|
||||
ValidFormat<int>("%s"), //
|
||||
ValidFormat<int>("%.1.d"), //
|
||||
ValidFormat<int>("%*1d"), //
|
||||
ValidFormat<int>("%1-d"), //
|
||||
ValidFormat<e>("%s"), //
|
||||
ValidFormat<e2>("%s"), //
|
||||
ValidFormat<>("%s"), //
|
||||
ValidFormat<>("%r"), //
|
||||
ValidFormat<int>("%s"), //
|
||||
ValidFormat<int>("%.1.d"), //
|
||||
ValidFormat<int>("%*1d"), //
|
||||
ValidFormat<int>("%1-d"), //
|
||||
ValidFormat<std::string, int>("%*s"), //
|
||||
ValidFormat<int>("%*d"), //
|
||||
ValidFormat<int>("%*d"), //
|
||||
ValidFormat<std::string>("%p"), //
|
||||
ValidFormat<int (*)(int)>("%d"), //
|
||||
ValidFormat<int (*)(int)>("%d"), //
|
||||
|
||||
ValidFormat<>("%3$d"), //
|
||||
ValidFormat<>("%1$r"), //
|
||||
ValidFormat<int>("%1$s"), //
|
||||
ValidFormat<int>("%1$.1.d"), //
|
||||
ValidFormat<int>("%1$*2$1d"), //
|
||||
ValidFormat<int>("%1$1-d"), //
|
||||
ValidFormat<>("%3$d"), //
|
||||
ValidFormat<>("%1$r"), //
|
||||
ValidFormat<int>("%1$s"), //
|
||||
ValidFormat<int>("%1$.1.d"), //
|
||||
ValidFormat<int>("%1$*2$1d"), //
|
||||
ValidFormat<int>("%1$1-d"), //
|
||||
ValidFormat<std::string, int>("%2$*1$s"), //
|
||||
ValidFormat<std::string>("%1$p"),
|
||||
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@ enum class Conv : uint64_t {
|
|||
integral = d | i | u | o | x | X,
|
||||
floating = a | e | f | g | A | E | F | G,
|
||||
numeric = integral | floating,
|
||||
string = s, // absl:ignore(std::string)
|
||||
string = s,
|
||||
pointer = p
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,6 @@ TEST(InvokeFlush, String) {
|
|||
std::string str = "ABC";
|
||||
str_format_internal::InvokeFlush(&str, "DEF");
|
||||
EXPECT_EQ(str, "ABCDEF");
|
||||
|
||||
#if UTIL_FORMAT_HAS_GLOBAL_STRING
|
||||
std::string str2 = "ABC";
|
||||
str_format_internal::InvokeFlush(&str2, "DEF");
|
||||
EXPECT_EQ(str2, "ABCDEF");
|
||||
#endif // UTIL_FORMAT_HAS_GLOBAL_STRING
|
||||
}
|
||||
|
||||
TEST(InvokeFlush, Stream) {
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ struct DefaultFormatter<std::unique_ptr<ValueType>>
|
|||
// and formats each element using the provided Formatter object.
|
||||
template <typename Iterator, typename Formatter>
|
||||
std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
|
||||
Formatter&& f) {
|
||||
Formatter&& f) {
|
||||
std::string result;
|
||||
absl::string_view sep("");
|
||||
for (Iterator it = start; it != end; ++it) {
|
||||
|
|
@ -212,7 +212,7 @@ std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
|
|||
// This is an overload of the previous JoinAlgorithm() function. Here the
|
||||
// Formatter argument is of type NoFormatter. Since NoFormatter is an internal
|
||||
// type, this overload is only invoked when strings::Join() is called with a
|
||||
// range of string-like objects (e.g., string, absl::string_view), and an
|
||||
// range of string-like objects (e.g., std::string, absl::string_view), and an
|
||||
// explicit Formatter argument was NOT specified.
|
||||
//
|
||||
// The optimization is that the needed space will be reserved in the output
|
||||
|
|
@ -224,7 +224,7 @@ template <typename Iterator,
|
|||
typename std::iterator_traits<Iterator>::iterator_category,
|
||||
std::forward_iterator_tag>::value>::type>
|
||||
std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
|
||||
NoFormatter) {
|
||||
NoFormatter) {
|
||||
std::string result;
|
||||
if (start != end) {
|
||||
// Sums size
|
||||
|
|
@ -276,14 +276,15 @@ struct JoinTupleLoop<N, N> {
|
|||
|
||||
template <typename... T, typename Formatter>
|
||||
std::string JoinAlgorithm(const std::tuple<T...>& tup, absl::string_view sep,
|
||||
Formatter&& fmt) {
|
||||
Formatter&& fmt) {
|
||||
std::string result;
|
||||
JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
std::string JoinRange(Iterator first, Iterator last, absl::string_view separator) {
|
||||
std::string JoinRange(Iterator first, Iterator last,
|
||||
absl::string_view separator) {
|
||||
// No formatter was explicitly given, so a default must be chosen.
|
||||
typedef typename std::iterator_traits<Iterator>::value_type ValueType;
|
||||
typedef typename DefaultFormatter<ValueType>::Type Formatter;
|
||||
|
|
@ -292,7 +293,7 @@ std::string JoinRange(Iterator first, Iterator last, absl::string_view separator
|
|||
|
||||
template <typename Range, typename Formatter>
|
||||
std::string JoinRange(const Range& range, absl::string_view separator,
|
||||
Formatter&& fmt) {
|
||||
Formatter&& fmt) {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return JoinAlgorithm(begin(range), end(range), separator, fmt);
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ ConvertibleToStringView(std::string&& s) // NOLINT(runtime/explicit)
|
|||
}
|
||||
}
|
||||
|
||||
// Holds the data moved from temporary std::string arguments. Declared first so
|
||||
// that 'value' can refer to 'copy_'.
|
||||
// Holds the data moved from temporary std::string arguments. Declared first
|
||||
// so that 'value' can refer to 'copy_'.
|
||||
std::string copy_;
|
||||
absl::string_view value_;
|
||||
};
|
||||
|
|
@ -376,10 +376,10 @@ class Splitter {
|
|||
|
||||
// Partial specialization for a std::vector<std::string>.
|
||||
//
|
||||
// Optimized for the common case of splitting to a std::vector<std::string>. In
|
||||
// this case we first split the results to a std::vector<absl::string_view> so
|
||||
// the returned std::vector<std::string> can have space reserved to avoid std::string
|
||||
// moves.
|
||||
// Optimized for the common case of splitting to a std::vector<std::string>.
|
||||
// In this case we first split the results to a std::vector<absl::string_view>
|
||||
// so the returned std::vector<std::string> can have space reserved to avoid
|
||||
// std::string moves.
|
||||
template <typename A>
|
||||
struct ConvertToContainer<std::vector<std::string, A>, std::string, false> {
|
||||
std::vector<std::string, A> operator()(const Splitter& splitter) const {
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ namespace {
|
|||
#endif
|
||||
TEST(EncodeUTF8Char, BasicFunction) {
|
||||
std::pair<char32_t, std::string> tests[] = {{0x0030, u8"\u0030"},
|
||||
{0x00A3, u8"\u00A3"},
|
||||
{0x00010000, u8"\U00010000"},
|
||||
{0x0000FFFF, u8"\U0000FFFF"},
|
||||
{0x0010FFFD, u8"\U0010FFFD"}};
|
||||
{0x00A3, u8"\u00A3"},
|
||||
{0x00010000, u8"\U00010000"},
|
||||
{0x0000FFFF, u8"\U0000FFFF"},
|
||||
{0x0010FFFD, u8"\U0010FFFD"}};
|
||||
for (auto &test : tests) {
|
||||
char buf0[7] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'};
|
||||
char buf1[7] = {'\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF'};
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
namespace {
|
||||
|
||||
TEST(MatchTest, StartsWith) {
|
||||
const std::string s1("123" "\0" "456", 7);
|
||||
const std::string s1("123\0abc", 7);
|
||||
const absl::string_view a("foobar");
|
||||
const absl::string_view b(s1);
|
||||
const absl::string_view e;
|
||||
|
|
@ -36,7 +36,7 @@ TEST(MatchTest, StartsWith) {
|
|||
}
|
||||
|
||||
TEST(MatchTest, EndsWith) {
|
||||
const std::string s1("123" "\0" "456", 7);
|
||||
const std::string s1("123\0abc", 7);
|
||||
const absl::string_view a("foobar");
|
||||
const absl::string_view b(s1);
|
||||
const absl::string_view e;
|
||||
|
|
|
|||
|
|
@ -191,7 +191,8 @@ void CheckUInt64(uint64_t x) {
|
|||
EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
|
||||
|
||||
char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
|
||||
EXPECT_EQ(expected, std::string(&buffer[1], generic_actual)) << " Input " << x;
|
||||
EXPECT_EQ(expected, std::string(&buffer[1], generic_actual))
|
||||
<< " Input " << x;
|
||||
|
||||
char* my_actual =
|
||||
absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]);
|
||||
|
|
@ -879,8 +880,8 @@ TEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) {
|
|||
char buf[kSixDigitsToBufferSize];
|
||||
ABSL_RAW_LOG(
|
||||
INFO, "%s",
|
||||
absl::StrCat("Exp ", exponent, " powten=", powten, "(",
|
||||
powten, ") (",
|
||||
absl::StrCat("Exp ", exponent, " powten=", powten, "(", powten,
|
||||
") (",
|
||||
std::string(buf, SixDigitsToBuffer(powten, buf)), ")")
|
||||
.c_str());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ AlphaNum::AlphaNum(Dec dec) {
|
|||
|
||||
// ----------------------------------------------------------------------
|
||||
// StrCat()
|
||||
// This merges the given strings or integers, with no delimiter. This
|
||||
// This merges the given strings or integers, with no delimiter. This
|
||||
// is designed to be the fastest possible way to construct a string out
|
||||
// of a mix of raw C strings, string_views, strings, and integer values.
|
||||
// ----------------------------------------------------------------------
|
||||
|
|
@ -119,7 +119,7 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
|
|||
}
|
||||
|
||||
std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
|
||||
const AlphaNum& d) {
|
||||
const AlphaNum& d) {
|
||||
std::string result;
|
||||
strings_internal::STLStringResizeUninitialized(
|
||||
&result, a.size() + b.size() + c.size() + d.size());
|
||||
|
|
|
|||
|
|
@ -245,6 +245,7 @@ class AlphaNum {
|
|||
|
||||
AlphaNum(const char* c_str) : piece_(c_str) {} // NOLINT(runtime/explicit)
|
||||
AlphaNum(absl::string_view pc) : piece_(pc) {} // NOLINT(runtime/explicit)
|
||||
|
||||
template <typename Allocator>
|
||||
AlphaNum( // NOLINT(runtime/explicit)
|
||||
const std::basic_string<char, std::char_traits<char>, Allocator>& str)
|
||||
|
|
@ -317,16 +318,15 @@ ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) {
|
|||
|
||||
ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
|
||||
ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c);
|
||||
const AlphaNum& c);
|
||||
ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d);
|
||||
const AlphaNum& c, const AlphaNum& d);
|
||||
|
||||
// Support 5 or more arguments
|
||||
template <typename... AV>
|
||||
ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a, const AlphaNum& b,
|
||||
const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e,
|
||||
const AV&... args) {
|
||||
ABSL_MUST_USE_RESULT inline std::string StrCat(
|
||||
const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
|
||||
const AlphaNum& e, const AV&... args) {
|
||||
return strings_internal::CatPieces(
|
||||
{a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
|
||||
static_cast<const AlphaNum&>(args).Piece()...});
|
||||
|
|
@ -344,18 +344,18 @@ ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a, const AlphaNum
|
|||
// not try to check each of its input arguments to be sure that they are not
|
||||
// a subset of the string being appended to. That is, while this will work:
|
||||
//
|
||||
// string s = "foo";
|
||||
// std::string s = "foo";
|
||||
// s += s;
|
||||
//
|
||||
// This output is undefined:
|
||||
//
|
||||
// string s = "foo";
|
||||
// std::string s = "foo";
|
||||
// StrAppend(&s, s);
|
||||
//
|
||||
// This output is undefined as well, since `absl::string_view` does not own its
|
||||
// data:
|
||||
//
|
||||
// string s = "foobar";
|
||||
// std::string s = "foobar";
|
||||
// absl::string_view p = s;
|
||||
// StrAppend(&s, p);
|
||||
|
||||
|
|
|
|||
|
|
@ -106,11 +106,7 @@ TEST(StrCat, Enums) {
|
|||
TEST(StrCat, Basics) {
|
||||
std::string result;
|
||||
|
||||
std::string strs[] = {
|
||||
"Hello",
|
||||
"Cruel",
|
||||
"World"
|
||||
};
|
||||
std::string strs[] = {"Hello", "Cruel", "World"};
|
||||
|
||||
std::string stdstrs[] = {
|
||||
"std::Hello",
|
||||
|
|
@ -164,9 +160,10 @@ TEST(StrCat, Basics) {
|
|||
result = absl::StrCat(ui64s[0], ", ", ui64s[1], "!");
|
||||
EXPECT_EQ(result, "12345678910, 10987654321!");
|
||||
|
||||
std::string one = "1"; // Actually, it's the size of this std::string that we want; a
|
||||
// 64-bit build distinguishes between size_t and uint64_t,
|
||||
// even though they're both unsigned 64-bit values.
|
||||
std::string one =
|
||||
"1"; // Actually, it's the size of this std::string that we want; a
|
||||
// 64-bit build distinguishes between size_t and uint64_t,
|
||||
// even though they're both unsigned 64-bit values.
|
||||
result = absl::StrCat("And a ", one.size(), " and a ",
|
||||
&result[2] - &result[0], " and a ", one, " 2 3 4", "!");
|
||||
EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
|
||||
|
|
@ -306,11 +303,7 @@ TEST(StrCat, MaxArgs) {
|
|||
TEST(StrAppend, Basics) {
|
||||
std::string result = "existing text";
|
||||
|
||||
std::string strs[] = {
|
||||
"Hello",
|
||||
"Cruel",
|
||||
"World"
|
||||
};
|
||||
std::string strs[] = {"Hello", "Cruel", "World"};
|
||||
|
||||
std::string stdstrs[] = {
|
||||
"std::Hello",
|
||||
|
|
@ -365,9 +358,10 @@ TEST(StrAppend, Basics) {
|
|||
absl::StrAppend(&result, ui64s[0], ", ", ui64s[1], "!");
|
||||
EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!");
|
||||
|
||||
std::string one = "1"; // Actually, it's the size of this std::string that we want; a
|
||||
// 64-bit build distinguishes between size_t and uint64_t,
|
||||
// even though they're both unsigned 64-bit values.
|
||||
std::string one =
|
||||
"1"; // Actually, it's the size of this std::string that we want; a
|
||||
// 64-bit build distinguishes between size_t and uint64_t,
|
||||
// even though they're both unsigned 64-bit values.
|
||||
old_size = result.size();
|
||||
absl::StrAppend(&result, "And a ", one.size(), " and a ",
|
||||
&result[2] - &result[0], " and a ", one, " 2 3 4", "!");
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// string s = absl::StrFormat("%s %s You have $%d!", "Hello", name, dollars);
|
||||
// std::string s = absl::StrFormat(
|
||||
// "%s %s You have $%d!", "Hello", name, dollars);
|
||||
//
|
||||
// The library consists of the following basic utilities:
|
||||
//
|
||||
|
|
@ -89,7 +90,7 @@ namespace absl {
|
|||
// Example:
|
||||
//
|
||||
// absl::UntypedFormatSpec format("%d");
|
||||
// string out;
|
||||
// std::string out;
|
||||
// CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)}));
|
||||
class UntypedFormatSpec {
|
||||
public:
|
||||
|
|
@ -135,8 +136,8 @@ str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {
|
|||
// Example:
|
||||
//
|
||||
// int n = 0;
|
||||
// string s = absl::StrFormat("%s%d%n", "hello", 123,
|
||||
// absl::FormatCountCapture(&n));
|
||||
// std::string s = absl::StrFormat("%s%d%n", "hello", 123,
|
||||
// absl::FormatCountCapture(&n));
|
||||
// EXPECT_EQ(8, n);
|
||||
class FormatCountCapture {
|
||||
public:
|
||||
|
|
@ -223,7 +224,7 @@ class FormatCountCapture {
|
|||
// "%p", *int -> "0x7ffdeb6ad2a4"
|
||||
//
|
||||
// int n = 0;
|
||||
// string s = absl::StrFormat(
|
||||
// std::string s = absl::StrFormat(
|
||||
// "%s%d%n", "hello", 123, absl::FormatCountCapture(&n));
|
||||
// EXPECT_EQ(8, n);
|
||||
//
|
||||
|
|
@ -290,14 +291,14 @@ using ParsedFormat = str_format_internal::ExtendedParsedFormat<
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// string s = absl::StrFormat(
|
||||
// std::string s = absl::StrFormat(
|
||||
// "Welcome to %s, Number %d!", "The Village", 6);
|
||||
// EXPECT_EQ("Welcome to The Village, Number 6!", s);
|
||||
//
|
||||
// Returns an empty string in case of error.
|
||||
template <typename... Args>
|
||||
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
|
||||
const Args&... args) {
|
||||
const Args&... args) {
|
||||
return str_format_internal::FormatPack(
|
||||
str_format_internal::UntypedFormatSpecImpl::Extract(format),
|
||||
{str_format_internal::FormatArgImpl(args)...});
|
||||
|
|
@ -311,11 +312,12 @@ ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// string orig("For example PI is approximately ");
|
||||
// std::string orig("For example PI is approximately ");
|
||||
// std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
|
||||
template <typename... Args>
|
||||
std::string& StrAppendFormat(std::string* dst, const FormatSpec<Args...>& format,
|
||||
const Args&... args) {
|
||||
std::string& StrAppendFormat(std::string* dst,
|
||||
const FormatSpec<Args...>& format,
|
||||
const Args&... args) {
|
||||
return str_format_internal::AppendPack(
|
||||
dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
|
||||
{str_format_internal::FormatArgImpl(args)...});
|
||||
|
|
@ -434,7 +436,8 @@ class FormatRawSink {
|
|||
// `absl::FormatRawSink` interface), using a format string and zero or more
|
||||
// additional arguments.
|
||||
//
|
||||
// By default, `string` and `std::ostream` are supported as destination objects.
|
||||
// By default, `std::string` and `std::ostream` are supported as destination
|
||||
// objects.
|
||||
//
|
||||
// `absl::Format()` is a generic version of `absl::StrFormat(), for custom
|
||||
// sinks. The format string, like format strings for `StrFormat()`, is checked
|
||||
|
|
@ -483,9 +486,10 @@ using FormatArg = str_format_internal::FormatArgImpl;
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// std::optional<string> FormatDynamic(const string& in_format,
|
||||
// const vector<string>& in_args) {
|
||||
// string out;
|
||||
// std::optional<std::string> FormatDynamic(
|
||||
// const std::string& in_format,
|
||||
// const vector<std::string>& in_args) {
|
||||
// std::string out;
|
||||
// std::vector<absl::FormatArg> args;
|
||||
// for (const auto& v : in_args) {
|
||||
// // It is important that 'v' is a reference to the objects in in_args.
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ TEST(StrFormat, BehavesAsDocumented) {
|
|||
EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
|
||||
EXPECT_EQ(StrFormat("%c", long{'a'}), "a"); // NOLINT
|
||||
EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
|
||||
// "s" - std::string Eg: "C" -> "C", std::string("C++") -> "C++"
|
||||
// "s" - std::string Eg: "C" -> "C", std::string("C++") -> "C++"
|
||||
// Formats std::string, char*, string_view, and Cord.
|
||||
EXPECT_EQ(StrFormat("%s", "C"), "C");
|
||||
EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
|
||||
|
|
@ -606,21 +606,21 @@ TEST_F(ParsedFormatTest, RegressionMixPositional) {
|
|||
// Some codegen thunks that we can use to easily dump the generated assembly for
|
||||
// different StrFormat calls.
|
||||
|
||||
std::string CodegenAbslStrFormatInt(int i) { // NOLINT
|
||||
std::string CodegenAbslStrFormatInt(int i) { // NOLINT
|
||||
return absl::StrFormat("%d", i);
|
||||
}
|
||||
|
||||
std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
|
||||
int64_t i64) { // NOLINT
|
||||
int64_t i64) { // NOLINT
|
||||
return absl::StrFormat("%d %s %d", i, s, i64);
|
||||
}
|
||||
|
||||
void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT
|
||||
void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT
|
||||
absl::StrAppendFormat(out, "%d", i);
|
||||
}
|
||||
|
||||
void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
|
||||
const std::string& s,
|
||||
int64_t i64) { // NOLINT
|
||||
const std::string& s,
|
||||
int64_t i64) { // NOLINT
|
||||
absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@
|
|||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file contains functions for joining a range of elements and
|
||||
// returning the result as a string. StrJoin operations are specified by passing
|
||||
// a range, a separator string to use between the elements joined, and an
|
||||
// optional Formatter responsible for converting each argument in the range to a
|
||||
// string. If omitted, a default `AlphaNumFormatter()` is called on the elements
|
||||
// to be joined, using the same formatting that `absl::StrCat()` uses. This
|
||||
// package defines a number of default formatters, and you can define your own
|
||||
// implementations.
|
||||
// returning the result as a std::string. StrJoin operations are specified by
|
||||
// passing a range, a separator string to use between the elements joined, and
|
||||
// an optional Formatter responsible for converting each argument in the range
|
||||
// to a string. If omitted, a default `AlphaNumFormatter()` is called on the
|
||||
// elements to be joined, using the same formatting that `absl::StrCat()` uses.
|
||||
// This package defines a number of default formatters, and you can define your
|
||||
// own implementations.
|
||||
//
|
||||
// Ranges are specified by passing a container with `std::begin()` and
|
||||
// `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
|
||||
|
|
@ -37,8 +37,8 @@
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// std::vector<string> v = {"foo", "bar", "baz"};
|
||||
// string s = absl::StrJoin(v, "-");
|
||||
// std::vector<std::string> v = {"foo", "bar", "baz"};
|
||||
// std::string s = absl::StrJoin(v, "-");
|
||||
// EXPECT_EQ("foo-bar-baz", s);
|
||||
//
|
||||
// See comments on the `absl::StrJoin()` function for more examples.
|
||||
|
|
@ -66,16 +66,16 @@ namespace absl {
|
|||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// A Formatter is a function object that is responsible for formatting its
|
||||
// argument as a string and appending it to a given output string. Formatters
|
||||
// may be implemented as function objects, lambdas, or normal functions. You may
|
||||
// provide your own Formatter to enable `absl::StrJoin()` to work with arbitrary
|
||||
// types.
|
||||
// argument as a string and appending it to a given output std::string.
|
||||
// Formatters may be implemented as function objects, lambdas, or normal
|
||||
// functions. You may provide your own Formatter to enable `absl::StrJoin()` to
|
||||
// work with arbitrary types.
|
||||
//
|
||||
// The following is an example of a custom Formatter that simply uses
|
||||
// `std::to_string()` to format an integer as a string.
|
||||
// `std::to_string()` to format an integer as a std::string.
|
||||
//
|
||||
// struct MyFormatter {
|
||||
// void operator()(string* out, int i) const {
|
||||
// void operator()(std::string* out, int i) const {
|
||||
// out->append(std::to_string(i));
|
||||
// }
|
||||
// };
|
||||
|
|
@ -84,7 +84,7 @@ namespace absl {
|
|||
// argument to `absl::StrJoin()`:
|
||||
//
|
||||
// std::vector<int> v = {1, 2, 3, 4};
|
||||
// string s = absl::StrJoin(v, "-", MyFormatter());
|
||||
// std::string s = absl::StrJoin(v, "-", MyFormatter());
|
||||
// EXPECT_EQ("1-2-3-4", s);
|
||||
//
|
||||
// The following standard formatters are provided within this file:
|
||||
|
|
@ -156,7 +156,7 @@ DereferenceFormatter() {
|
|||
// StrJoin()
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// Joins a range of elements and returns the result as a string.
|
||||
// Joins a range of elements and returns the result as a std::string.
|
||||
// `absl::StrJoin()` takes a range, a separator string to use between the
|
||||
// elements joined, and an optional Formatter responsible for converting each
|
||||
// argument in the range to a string.
|
||||
|
|
@ -167,22 +167,22 @@ DereferenceFormatter() {
|
|||
// Example 1:
|
||||
// // Joins a collection of strings. This pattern also works with a collection
|
||||
// // of `absl::string_view` or even `const char*`.
|
||||
// std::vector<string> v = {"foo", "bar", "baz"};
|
||||
// string s = absl::StrJoin(v, "-");
|
||||
// std::vector<std::string> v = {"foo", "bar", "baz"};
|
||||
// std::string s = absl::StrJoin(v, "-");
|
||||
// EXPECT_EQ("foo-bar-baz", s);
|
||||
//
|
||||
// Example 2:
|
||||
// // Joins the values in the given `std::initializer_list<>` specified using
|
||||
// // brace initialization. This pattern also works with an initializer_list
|
||||
// // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
|
||||
// string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
|
||||
// std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
|
||||
// EXPECT_EQ("foo-bar-baz", s);
|
||||
//
|
||||
// Example 3:
|
||||
// // Joins a collection of ints. This pattern also works with floats,
|
||||
// // doubles, int64s -- any `StrCat()`-compatible type.
|
||||
// std::vector<int> v = {1, 2, 3, -4};
|
||||
// string s = absl::StrJoin(v, "-");
|
||||
// std::string s = absl::StrJoin(v, "-");
|
||||
// EXPECT_EQ("1-2-3--4", s);
|
||||
//
|
||||
// Example 4:
|
||||
|
|
@ -193,7 +193,7 @@ DereferenceFormatter() {
|
|||
// // `std::vector<int*>`.
|
||||
// int x = 1, y = 2, z = 3;
|
||||
// std::vector<int*> v = {&x, &y, &z};
|
||||
// string s = absl::StrJoin(v, "-");
|
||||
// std::string s = absl::StrJoin(v, "-");
|
||||
// EXPECT_EQ("1-2-3", s);
|
||||
//
|
||||
// Example 5:
|
||||
|
|
@ -202,53 +202,53 @@ DereferenceFormatter() {
|
|||
// v.emplace_back(new int(1));
|
||||
// v.emplace_back(new int(2));
|
||||
// v.emplace_back(new int(3));
|
||||
// string s = absl::StrJoin(v, "-");
|
||||
// std::string s = absl::StrJoin(v, "-");
|
||||
// EXPECT_EQ("1-2-3", s);
|
||||
//
|
||||
// Example 6:
|
||||
// // Joins a `std::map`, with each key-value pair separated by an equals
|
||||
// // sign. This pattern would also work with, say, a
|
||||
// // `std::vector<std::pair<>>`.
|
||||
// std::map<string, int> m = {
|
||||
// std::map<std::string, int> m = {
|
||||
// std::make_pair("a", 1),
|
||||
// std::make_pair("b", 2),
|
||||
// std::make_pair("c", 3)};
|
||||
// string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
|
||||
// std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
|
||||
// EXPECT_EQ("a=1,b=2,c=3", s);
|
||||
//
|
||||
// Example 7:
|
||||
// // These examples show how `absl::StrJoin()` handles a few common edge
|
||||
// // cases:
|
||||
// std::vector<string> v_empty;
|
||||
// std::vector<std::string> v_empty;
|
||||
// EXPECT_EQ("", absl::StrJoin(v_empty, "-"));
|
||||
//
|
||||
// std::vector<string> v_one_item = {"foo"};
|
||||
// std::vector<std::string> v_one_item = {"foo"};
|
||||
// EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-"));
|
||||
//
|
||||
// std::vector<string> v_empty_string = {""};
|
||||
// std::vector<std::string> v_empty_string = {""};
|
||||
// EXPECT_EQ("", absl::StrJoin(v_empty_string, "-"));
|
||||
//
|
||||
// std::vector<string> v_one_item_empty_string = {"a", ""};
|
||||
// std::vector<std::string> v_one_item_empty_string = {"a", ""};
|
||||
// EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-"));
|
||||
//
|
||||
// std::vector<string> v_two_empty_string = {"", ""};
|
||||
// std::vector<std::string> v_two_empty_string = {"", ""};
|
||||
// EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-"));
|
||||
//
|
||||
// Example 8:
|
||||
// // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
|
||||
// // a string using the `absl::AlphaNum` class.
|
||||
// string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
|
||||
// // a std::string using the `absl::AlphaNum` class.
|
||||
// std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
|
||||
// EXPECT_EQ("123-abc-0.456", s);
|
||||
|
||||
template <typename Iterator, typename Formatter>
|
||||
std::string StrJoin(Iterator start, Iterator end, absl::string_view sep,
|
||||
Formatter&& fmt) {
|
||||
Formatter&& fmt) {
|
||||
return strings_internal::JoinAlgorithm(start, end, sep, fmt);
|
||||
}
|
||||
|
||||
template <typename Range, typename Formatter>
|
||||
std::string StrJoin(const Range& range, absl::string_view separator,
|
||||
Formatter&& fmt) {
|
||||
Formatter&& fmt) {
|
||||
return strings_internal::JoinRange(range, separator, fmt);
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +260,7 @@ std::string StrJoin(std::initializer_list<T> il, absl::string_view separator,
|
|||
|
||||
template <typename... T, typename Formatter>
|
||||
std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,
|
||||
Formatter&& fmt) {
|
||||
Formatter&& fmt) {
|
||||
return strings_internal::JoinAlgorithm(value, separator, fmt);
|
||||
}
|
||||
|
||||
|
|
@ -280,7 +280,8 @@ std::string StrJoin(std::initializer_list<T> il, absl::string_view separator) {
|
|||
}
|
||||
|
||||
template <typename... T>
|
||||
std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator) {
|
||||
std::string StrJoin(const std::tuple<T...>& value,
|
||||
absl::string_view separator) {
|
||||
return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ void BM_Join2_KeysAndValues(benchmark::State& state) {
|
|||
const int string_len = state.range(0);
|
||||
const int num_pairs = state.range(1);
|
||||
const std::string s(string_len, 'x');
|
||||
const std::vector<std::pair<std::string, int>> v(num_pairs, std::make_pair(s, 42));
|
||||
const std::vector<std::pair<std::string, int>> v(num_pairs,
|
||||
std::make_pair(s, 42));
|
||||
for (auto _ : state) {
|
||||
std::string s = absl::StrJoin(v, ",", absl::PairFormatter("="));
|
||||
benchmark::DoNotOptimize(s);
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ TEST(StrJoin, APIExamples) {
|
|||
|
||||
{
|
||||
// A std::map, which is a collection of std::pair<>s.
|
||||
std::map<std::string, int> m = { {"a", 1}, {"b", 2}, {"c", 3} };
|
||||
std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
|
||||
EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +140,8 @@ TEST(StrJoin, APIExamples) {
|
|||
}
|
||||
|
||||
{
|
||||
// A range of 1 element gives a std::string with that element but no separator.
|
||||
// A range of 1 element gives a std::string with that element but no
|
||||
// separator.
|
||||
std::vector<std::string> v = {"foo"};
|
||||
EXPECT_EQ("foo", absl::StrJoin(v, "-"));
|
||||
}
|
||||
|
|
@ -173,9 +174,10 @@ TEST(StrJoin, APIExamples) {
|
|||
TEST(StrJoin, CustomFormatter) {
|
||||
std::vector<std::string> v{"One", "Two", "Three"};
|
||||
{
|
||||
std::string joined = absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
|
||||
absl::StrAppend(out, "(", in, ")");
|
||||
});
|
||||
std::string joined =
|
||||
absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
|
||||
absl::StrAppend(out, "(", in, ")");
|
||||
});
|
||||
EXPECT_EQ("(One)(Two)(Three)", joined);
|
||||
}
|
||||
{
|
||||
|
|
|
|||
|
|
@ -68,11 +68,12 @@ int ApplySubstitutions(
|
|||
// aren't inlined.
|
||||
|
||||
std::string StrReplaceAll(absl::string_view s,
|
||||
strings_internal::FixedMapping replacements) {
|
||||
strings_internal::FixedMapping replacements) {
|
||||
return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
|
||||
}
|
||||
|
||||
int StrReplaceAll(strings_internal::FixedMapping replacements, std::string* target) {
|
||||
int StrReplaceAll(strings_internal::FixedMapping replacements,
|
||||
std::string* target) {
|
||||
return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// string html_escaped = absl::StrReplaceAll(user_input, {
|
||||
// {"&", "&"},
|
||||
// {"<", "<"},
|
||||
// {">", ">"},
|
||||
// {"\"", """},
|
||||
// {"'", "'"}});
|
||||
// std::string html_escaped = absl::StrReplaceAll(user_input, {
|
||||
// {"&", "&"},
|
||||
// {"<", "<"},
|
||||
// {">", ">"},
|
||||
// {"\"", """},
|
||||
// {"'", "'"}});
|
||||
#ifndef ABSL_STRINGS_STR_REPLACE_H_
|
||||
#define ABSL_STRINGS_STR_REPLACE_H_
|
||||
|
||||
|
|
@ -58,10 +58,11 @@ namespace absl {
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
|
||||
// {{"$count", absl::StrCat(5)},
|
||||
// {"$who", "Bob"},
|
||||
// {"#Noun", "Apples"}});
|
||||
// std::string s = absl::StrReplaceAll(
|
||||
// "$who bought $count #Noun. Thanks $who!",
|
||||
// {{"$count", absl::StrCat(5)},
|
||||
// {"$who", "Bob"},
|
||||
// {"#Noun", "Apples"}});
|
||||
// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
|
||||
ABSL_MUST_USE_RESULT std::string StrReplaceAll(
|
||||
absl::string_view s,
|
||||
|
|
@ -78,20 +79,22 @@ ABSL_MUST_USE_RESULT std::string StrReplaceAll(
|
|||
// replacements["$who"] = "Bob";
|
||||
// replacements["$count"] = "5";
|
||||
// replacements["#Noun"] = "Apples";
|
||||
// string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
|
||||
// replacements);
|
||||
// std::string s = absl::StrReplaceAll(
|
||||
// "$who bought $count #Noun. Thanks $who!",
|
||||
// replacements);
|
||||
// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
|
||||
//
|
||||
// // A std::vector of std::pair elements can be more efficient.
|
||||
// std::vector<std::pair<const absl::string_view, string>> replacements;
|
||||
// std::vector<std::pair<const absl::string_view, std::string>> replacements;
|
||||
// replacements.push_back({"&", "&"});
|
||||
// replacements.push_back({"<", "<"});
|
||||
// replacements.push_back({">", ">"});
|
||||
// string s = absl::StrReplaceAll("if (ptr < &foo)",
|
||||
// std::string s = absl::StrReplaceAll("if (ptr < &foo)",
|
||||
// replacements);
|
||||
// EXPECT_EQ("if (ptr < &foo)", s);
|
||||
template <typename StrToStrMapping>
|
||||
std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements);
|
||||
std::string StrReplaceAll(absl::string_view s,
|
||||
const StrToStrMapping& replacements);
|
||||
|
||||
// Overload of `StrReplaceAll()` to replace character sequences within a given
|
||||
// output string *in place* with replacements provided within an initializer
|
||||
|
|
@ -99,7 +102,7 @@ std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacemen
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// string s = std::string("$who bought $count #Noun. Thanks $who!");
|
||||
// std::string s = std::string("$who bought $count #Noun. Thanks $who!");
|
||||
// int count;
|
||||
// count = absl::StrReplaceAll({{"$count", absl::StrCat(5)},
|
||||
// {"$who", "Bob"},
|
||||
|
|
@ -117,7 +120,7 @@ int StrReplaceAll(
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// string s = std::string("if (ptr < &foo)");
|
||||
// std::string s = std::string("if (ptr < &foo)");
|
||||
// int count = absl::StrReplaceAll({{"&", "&"},
|
||||
// {"<", "<"},
|
||||
// {">", ">"}}, &s);
|
||||
|
|
@ -187,7 +190,8 @@ int ApplySubstitutions(absl::string_view s,
|
|||
} // namespace strings_internal
|
||||
|
||||
template <typename StrToStrMapping>
|
||||
std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements) {
|
||||
std::string StrReplaceAll(absl::string_view s,
|
||||
const StrToStrMapping& replacements) {
|
||||
auto subs = strings_internal::FindSubstitutions(s, replacements);
|
||||
std::string result;
|
||||
result.reserve(s.size());
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ void SetUpStrings() {
|
|||
size_t r = 0;
|
||||
big_string = new std::string(1000 * 1000, ' ');
|
||||
for (std::string phrase : {"the quick brown fox jumped over the lazy dogs",
|
||||
"pack my box with the five dozen liquor jugs"}) {
|
||||
"pack my box with the five dozen liquor jugs"}) {
|
||||
for (int i = 0; i < 10 * 1000; ++i) {
|
||||
r = r * 237 + 41; // not very random.
|
||||
memcpy(&(*big_string)[r % (big_string->size() - phrase.size())],
|
||||
|
|
@ -108,11 +108,11 @@ void BM_StrReplaceAll(benchmark::State& state) {
|
|||
std::string src = *big_string;
|
||||
for (auto _ : state) {
|
||||
std::string dest = absl::StrReplaceAll(src, {{"the", "box"},
|
||||
{"brown", "quick"},
|
||||
{"jumped", "liquored"},
|
||||
{"dozen", "brown"},
|
||||
{"lazy", "pack"},
|
||||
{"liquor", "shakes"}});
|
||||
{"brown", "quick"},
|
||||
{"jumped", "liquored"},
|
||||
{"dozen", "brown"},
|
||||
{"lazy", "pack"},
|
||||
{"liquor", "shakes"}});
|
||||
ABSL_RAW_CHECK(dest == *after_replacing_many,
|
||||
"not benchmarking intended behavior");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ TEST(StrReplaceAll, ManyReplacementsInMap) {
|
|||
replacements["$count"] = "5";
|
||||
replacements["#Noun"] = "Apples";
|
||||
std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
|
||||
replacements);
|
||||
replacements);
|
||||
EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,8 +132,7 @@ class ByString {
|
|||
// ByChar
|
||||
//
|
||||
// A single character delimiter. `ByChar` is functionally equivalent to a
|
||||
// 1-char string within a `ByString` delimiter, but slightly more
|
||||
// efficient.
|
||||
// 1-char string within a `ByString` delimiter, but slightly more efficient.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
|
|
@ -414,10 +413,10 @@ struct SkipWhitespace {
|
|||
//
|
||||
// The `StrSplit()` function adapts the returned collection to the collection
|
||||
// specified by the caller (e.g. `std::vector` above). The returned collections
|
||||
// may contain `string`, `absl::string_view` (in which case the original string
|
||||
// being split must ensure that it outlives the collection), or any object that
|
||||
// can be explicitly created from an `absl::string_view`. This behavior works
|
||||
// for:
|
||||
// may contain `std::string`, `absl::string_view` (in which case the original
|
||||
// string being split must ensure that it outlives the collection), or any
|
||||
// object that can be explicitly created from an `absl::string_view`. This
|
||||
// behavior works for:
|
||||
//
|
||||
// 1) All standard STL containers including `std::vector`, `std::list`,
|
||||
// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
|
||||
|
|
@ -461,7 +460,7 @@ struct SkipWhitespace {
|
|||
// Example:
|
||||
//
|
||||
// // Stores first two split strings as the members in a std::pair.
|
||||
// std::pair<string, string> p = absl::StrSplit("a,b,c", ',');
|
||||
// std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ',');
|
||||
// // p.first == "a", p.second == "b" // "c" is omitted.
|
||||
//
|
||||
// The `StrSplit()` function can be used multiple times to perform more
|
||||
|
|
@ -471,7 +470,7 @@ struct SkipWhitespace {
|
|||
//
|
||||
// // The input string "a=b=c,d=e,f=,g" becomes
|
||||
// // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" }
|
||||
// std::map<string, string> m;
|
||||
// std::map<std::string, std::string> m;
|
||||
// for (absl::string_view sp : absl::StrSplit("a=b=c,d=e,f=,g", ',')) {
|
||||
// m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1)));
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ BENCHMARK_RANGE(BM_Split2String, 0, 1 << 20);
|
|||
void BM_Split2SplitStringUsing(benchmark::State& state) {
|
||||
std::string test = MakeTestString(state.range(0));
|
||||
for (auto _ : state) {
|
||||
std::vector<std::string> result = absl::StrSplit(test, ';', absl::SkipEmpty());
|
||||
std::vector<std::string> result =
|
||||
absl::StrSplit(test, ';', absl::SkipEmpty());
|
||||
benchmark::DoNotOptimize(result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ using ::testing::UnorderedElementsAre;
|
|||
TEST(Split, TraitsTest) {
|
||||
static_assert(!absl::strings_internal::SplitterIsConvertibleTo<int>::value,
|
||||
"");
|
||||
static_assert(!absl::strings_internal::SplitterIsConvertibleTo<std::string>::value,
|
||||
"");
|
||||
static_assert(
|
||||
!absl::strings_internal::SplitterIsConvertibleTo<std::string>::value, "");
|
||||
static_assert(absl::strings_internal::SplitterIsConvertibleTo<
|
||||
std::vector<std::string>>::value,
|
||||
"");
|
||||
|
|
@ -182,7 +182,8 @@ TEST(Split, APIExamples) {
|
|||
{
|
||||
// Uses the SkipWhitespace predicate.
|
||||
using absl::SkipWhitespace;
|
||||
std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
|
||||
std::vector<std::string> v =
|
||||
absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
|
||||
EXPECT_THAT(v, ElementsAre(" a ", "b"));
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +216,8 @@ TEST(Split, APIExamples) {
|
|||
|
||||
{
|
||||
// Results stored in a std::multimap.
|
||||
std::multimap<std::string, std::string> m = absl::StrSplit("a,1,b,2,a,3", ',');
|
||||
std::multimap<std::string, std::string> m =
|
||||
absl::StrSplit("a,1,b,2,a,3", ',');
|
||||
EXPECT_EQ(3, m.size());
|
||||
auto it = m.find("a");
|
||||
EXPECT_EQ("1", it->second);
|
||||
|
|
@ -271,7 +273,8 @@ TEST(SplitIterator, Basics) {
|
|||
EXPECT_EQ("a", *it); // tests dereference
|
||||
++it; // tests preincrement
|
||||
EXPECT_NE(it, end);
|
||||
EXPECT_EQ("b", std::string(it->data(), it->size())); // tests dereference as ptr
|
||||
EXPECT_EQ("b",
|
||||
std::string(it->data(), it->size())); // tests dereference as ptr
|
||||
it++; // tests postincrement
|
||||
EXPECT_EQ(it, end);
|
||||
}
|
||||
|
|
@ -295,7 +298,8 @@ TEST(SplitIterator, Predicate) {
|
|||
EXPECT_EQ("a", *it); // tests dereference
|
||||
++it; // tests preincrement -- "b" should be skipped here.
|
||||
EXPECT_NE(it, end);
|
||||
EXPECT_EQ("c", std::string(it->data(), it->size())); // tests dereference as ptr
|
||||
EXPECT_EQ("c",
|
||||
std::string(it->data(), it->size())); // tests dereference as ptr
|
||||
it++; // tests postincrement
|
||||
EXPECT_EQ(it, end);
|
||||
}
|
||||
|
|
@ -421,10 +425,13 @@ TEST(Splitter, ConversionOperator) {
|
|||
TestMapConversionOperator<std::map<std::string, std::string>>(splitter);
|
||||
TestMapConversionOperator<
|
||||
std::multimap<absl::string_view, absl::string_view>>(splitter);
|
||||
TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(splitter);
|
||||
TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(splitter);
|
||||
TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(
|
||||
splitter);
|
||||
TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(
|
||||
splitter);
|
||||
TestMapConversionOperator<std::multimap<std::string, std::string>>(splitter);
|
||||
TestMapConversionOperator<std::unordered_map<std::string, std::string>>(splitter);
|
||||
TestMapConversionOperator<std::unordered_map<std::string, std::string>>(
|
||||
splitter);
|
||||
|
||||
// Tests conversion to std::pair
|
||||
|
||||
|
|
@ -568,10 +575,9 @@ TEST(Split, AcceptsCertainTemporaries) {
|
|||
}
|
||||
|
||||
TEST(Split, Temporary) {
|
||||
// Use a std::string longer than the small-std::string-optimization length, so that when
|
||||
// the temporary is destroyed, if the splitter keeps a reference to the
|
||||
// std::string's contents, it'll reference freed memory instead of just dead
|
||||
// on-stack memory.
|
||||
// Use a std::string longer than the SSO length, so that when the temporary is
|
||||
// destroyed, if the splitter keeps a reference to the std::string's contents,
|
||||
// it'll reference freed memory instead of just dead on-stack memory.
|
||||
const char input[] = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u";
|
||||
EXPECT_LT(sizeof(std::string), ABSL_ARRAYSIZE(input))
|
||||
<< "Input should be larger than fits on the stack.";
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ class string_view {
|
|||
// Checks if the `string_view` is empty (refers to no characters).
|
||||
constexpr bool empty() const noexcept { return length_ == 0; }
|
||||
|
||||
// std::string:view::operator[]
|
||||
// string_view::operator[]
|
||||
//
|
||||
// Returns the ith element of an `string_view` using the array operator.
|
||||
// Note that this operator does not perform any bounds checking.
|
||||
|
|
|
|||
|
|
@ -284,9 +284,10 @@ TEST(StringViewTest, ComparisonOperatorsByCharacterPosition) {
|
|||
}
|
||||
#undef COMPARE
|
||||
|
||||
// Sadly, our users often confuse string::npos with absl::string_view::npos;
|
||||
// So much so that we test here that they are the same. They need to
|
||||
// both be unsigned, and both be the maximum-valued integer of their type.
|
||||
// Sadly, our users often confuse std::string::npos with
|
||||
// absl::string_view::npos; So much so that we test here that they are the same.
|
||||
// They need to both be unsigned, and both be the maximum-valued integer of
|
||||
// their type.
|
||||
|
||||
template <typename T>
|
||||
struct is_type {
|
||||
|
|
@ -995,8 +996,8 @@ TEST(StringViewTest, ConstexprCompiles) {
|
|||
TEST(StringViewTest, Noexcept) {
|
||||
EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
|
||||
const std::string&>::value));
|
||||
EXPECT_TRUE(
|
||||
(std::is_nothrow_constructible<absl::string_view, const std::string&>::value));
|
||||
EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
|
||||
const std::string&>::value));
|
||||
EXPECT_TRUE(std::is_nothrow_constructible<absl::string_view>::value);
|
||||
constexpr absl::string_view sp;
|
||||
EXPECT_TRUE(noexcept(sp.begin()));
|
||||
|
|
|
|||
|
|
@ -36,18 +36,18 @@
|
|||
// use at that location within the format string.
|
||||
//
|
||||
// Example 1:
|
||||
// string s = Substitute("$1 purchased $0 $2. Thanks $1!",
|
||||
// 5, "Bob", "Apples");
|
||||
// std::string s = Substitute("$1 purchased $0 $2. Thanks $1!",
|
||||
// 5, "Bob", "Apples");
|
||||
// EXPECT_EQ("Bob purchased 5 Apples. Thanks Bob!", s);
|
||||
//
|
||||
// Example 2:
|
||||
// string s = "Hi. ";
|
||||
// std::string s = "Hi. ";
|
||||
// SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
|
||||
// EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
|
||||
//
|
||||
//
|
||||
// Supported types:
|
||||
// * absl::string_view, string, const char* (null is equivalent to "")
|
||||
// * absl::string_view, std::string, const char* (null is equivalent to "")
|
||||
// * int32_t, int64_t, uint32_t, uint64
|
||||
// * float, double
|
||||
// * bool (Printed as "true" or "false")
|
||||
|
|
@ -456,7 +456,7 @@ void SubstituteAndAppend(
|
|||
// Example:
|
||||
// template <typename... Args>
|
||||
// void VarMsg(absl::string_view format, const Args&... args) {
|
||||
// string s = absl::Substitute(format, args...);
|
||||
// std::string s = absl::Substitute(format, args...);
|
||||
|
||||
ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) {
|
||||
std::string result;
|
||||
|
|
@ -574,70 +574,70 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0)
|
|||
"contains one of $1-$9");
|
||||
|
||||
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
|
||||
const substitute_internal::Arg& a1)
|
||||
const substitute_internal::Arg& a1)
|
||||
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 3,
|
||||
"There were 2 substitution arguments given, but "
|
||||
"this format std::string is either missing its $0/$1, or "
|
||||
"contains one of $2-$9");
|
||||
|
||||
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2)
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2)
|
||||
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 7,
|
||||
"There were 3 substitution arguments given, but "
|
||||
"this format std::string is either missing its $0/$1/$2, or "
|
||||
"contains one of $3-$9");
|
||||
|
||||
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3)
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3)
|
||||
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 15,
|
||||
"There were 4 substitution arguments given, but "
|
||||
"this format std::string is either missing its $0-$3, or "
|
||||
"contains one of $4-$9");
|
||||
|
||||
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4)
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4)
|
||||
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31,
|
||||
"There were 5 substitution arguments given, but "
|
||||
"this format std::string is either missing its $0-$4, or "
|
||||
"contains one of $5-$9");
|
||||
|
||||
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4,
|
||||
const substitute_internal::Arg& a5)
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4,
|
||||
const substitute_internal::Arg& a5)
|
||||
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63,
|
||||
"There were 6 substitution arguments given, but "
|
||||
"this format std::string is either missing its $0-$5, or "
|
||||
"contains one of $6-$9");
|
||||
|
||||
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4,
|
||||
const substitute_internal::Arg& a5,
|
||||
const substitute_internal::Arg& a6)
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4,
|
||||
const substitute_internal::Arg& a5,
|
||||
const substitute_internal::Arg& a6)
|
||||
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127,
|
||||
"There were 7 substitution arguments given, but "
|
||||
"this format std::string is either missing its $0-$6, or "
|
||||
"contains one of $7-$9");
|
||||
|
||||
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4,
|
||||
const substitute_internal::Arg& a5,
|
||||
const substitute_internal::Arg& a6,
|
||||
const substitute_internal::Arg& a7)
|
||||
const substitute_internal::Arg& a1,
|
||||
const substitute_internal::Arg& a2,
|
||||
const substitute_internal::Arg& a3,
|
||||
const substitute_internal::Arg& a4,
|
||||
const substitute_internal::Arg& a5,
|
||||
const substitute_internal::Arg& a6,
|
||||
const substitute_internal::Arg& a7)
|
||||
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255,
|
||||
"There were 8 substitution arguments given, but "
|
||||
"this format std::string is either missing its $0-$7, or "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue