summaryrefslogtreecommitdiff
path: root/chromium/third_party/abseil-cpp/absl/strings
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/abseil-cpp/absl/strings')
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/cord.cc65
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/cord.h35
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc36
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h32
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc14
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc8
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc6
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc38
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h84
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc15
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc12
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/str_format.h272
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/str_format_test.cc171
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/str_split.h1
-rw-r--r--chromium/third_party/abseil-cpp/absl/strings/string_view.h2
15 files changed, 603 insertions, 188 deletions
diff --git a/chromium/third_party/abseil-cpp/absl/strings/cord.cc b/chromium/third_party/abseil-cpp/absl/strings/cord.cc
index 1ddd6aec91a..68f5398791d 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/cord.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/cord.cc
@@ -705,6 +705,37 @@ Cord::Cord(absl::string_view src) {
}
}
+template <typename T, Cord::EnableIfString<T>>
+Cord::Cord(T&& src) {
+ if (
+ // String is short: copy data to avoid external block overhead.
+ src.size() <= kMaxBytesToCopy ||
+ // String is wasteful: copy data to avoid pinning too much unused memory.
+ src.size() < src.capacity() / 2
+ ) {
+ if (src.size() <= InlineRep::kMaxInline) {
+ contents_.set_data(src.data(), src.size(), false);
+ } else {
+ contents_.set_tree(NewTree(src.data(), src.size(), 0));
+ }
+ } else {
+ struct StringReleaser {
+ void operator()(absl::string_view /* data */) {}
+ std::string data;
+ };
+ const absl::string_view original_data = src;
+ CordRepExternal* rep =
+ static_cast<CordRepExternal*>(absl::cord_internal::NewExternalRep(
+ original_data, StringReleaser{std::move(src)}));
+ // Moving src may have invalidated its data pointer, so adjust it.
+ rep->base =
+ static_cast<StringReleaser*>(GetExternalReleaser(rep))->data.data();
+ contents_.set_tree(rep);
+ }
+}
+
+template Cord::Cord(std::string&& src);
+
// The destruction code is separate so that the compiler can determine
// that it does not need to call the destructor on a moved-from Cord.
void Cord::DestroyCordSlow() {
@@ -742,6 +773,18 @@ Cord& Cord::operator=(absl::string_view src) {
return *this;
}
+template <typename T, Cord::EnableIfString<T>>
+Cord& Cord::operator=(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ *this = absl::string_view(src);
+ } else {
+ *this = Cord(std::move(src));
+ }
+ return *this;
+}
+
+template Cord& Cord::operator=(std::string&& src);
+
// TODO(sanjay): Move to Cord::InlineRep section of file. For now,
// we keep it here to make diffs easier.
void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
@@ -853,6 +896,17 @@ void Cord::Append(const Cord& src) { AppendImpl(src); }
void Cord::Append(Cord&& src) { AppendImpl(std::move(src)); }
+template <typename T, Cord::EnableIfString<T>>
+void Cord::Append(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Append(absl::string_view(src));
+ } else {
+ Append(Cord(std::move(src)));
+ }
+}
+
+template void Cord::Append(std::string&& src);
+
void Cord::Prepend(const Cord& src) {
CordRep* src_tree = src.contents_.tree();
if (src_tree != nullptr) {
@@ -882,6 +936,17 @@ void Cord::Prepend(absl::string_view src) {
}
}
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Prepend(absl::string_view(src));
+ } else {
+ Prepend(Cord(std::move(src)));
+ }
+}
+
+template void Cord::Prepend(std::string&& src);
+
static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
if (n >= node->length) return nullptr;
if (n == 0) return Ref(node);
diff --git a/chromium/third_party/abseil-cpp/absl/strings/cord.h b/chromium/third_party/abseil-cpp/absl/strings/cord.h
index 3be8d7d875f..8580d80315c 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/cord.h
+++ b/chromium/third_party/abseil-cpp/absl/strings/cord.h
@@ -147,11 +147,8 @@ class Cord {
// Creates a Cord from a `std::string&&` rvalue. These constructors are
// templated to avoid ambiguities for types that are convertible to both
// `absl::string_view` and `std::string`, such as `const char*`.
- //
- // Note that these functions reserve the right to use the `string&&`'s
- // memory and that they will do so in the future.
template <typename T, EnableIfString<T> = 0>
- explicit Cord(T&& src) : Cord(absl::string_view(src)) {}
+ explicit Cord(T&& src);
template <typename T, EnableIfString<T> = 0>
Cord& operator=(T&& src);
@@ -860,16 +857,16 @@ ExternalRepReleaserPair NewExternalWithUninitializedReleaser(
struct Rank1 {};
struct Rank0 : Rank1 {};
-template <typename Releaser, typename = ::absl::base_internal::InvokeT<
+template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
Releaser, absl::string_view>>
void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
- ::absl::base_internal::Invoke(std::forward<Releaser>(releaser), data);
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
}
template <typename Releaser,
- typename = ::absl::base_internal::InvokeT<Releaser>>
+ typename = ::absl::base_internal::invoke_result_t<Releaser>>
void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
- ::absl::base_internal::Invoke(std::forward<Releaser>(releaser));
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser));
}
// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
@@ -1048,11 +1045,8 @@ inline Cord& Cord::operator=(Cord&& x) noexcept {
return *this;
}
-template <typename T, Cord::EnableIfString<T>>
-inline Cord& Cord::operator=(T&& src) {
- *this = absl::string_view(src);
- return *this;
-}
+extern template Cord::Cord(std::string&& src);
+extern template Cord& Cord::operator=(std::string&& src);
inline size_t Cord::size() const {
// Length is 1st field in str.rep_
@@ -1098,19 +1092,8 @@ inline void Cord::Append(absl::string_view src) {
contents_.AppendArray(src.data(), src.size());
}
-template <typename T, Cord::EnableIfString<T>>
-inline void Cord::Append(T&& src) {
- // Note that this function reserves the right to reuse the `string&&`'s
- // memory and that it will do so in the future.
- Append(absl::string_view(src));
-}
-
-template <typename T, Cord::EnableIfString<T>>
-inline void Cord::Prepend(T&& src) {
- // Note that this function reserves the right to reuse the `string&&`'s
- // memory and that it will do so in the future.
- Prepend(absl::string_view(src));
-}
+extern template void Cord::Append(std::string&& src);
+extern template void Cord::Prepend(std::string&& src);
inline int Cord::Compare(const Cord& rhs) const {
if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc
index 02646addec1..9feb2248793 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc
@@ -267,38 +267,42 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
using U = typename MakeUnsigned<T>::type;
IntDigits as_digits;
- switch (conv.conversion_char()) {
- case FormatConversionCharInternal::c:
+ // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
+ // it to complain about a switch/case type mismatch, even though both are
+ // FormatConverionChar. Likely this is because at this point
+ // FormatConversionChar is declared, but not defined.
+ switch (static_cast<uint8_t>(conv.conversion_char())) {
+ case static_cast<uint8_t>(FormatConversionCharInternal::c):
return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
- case FormatConversionCharInternal::o:
+ case static_cast<uint8_t>(FormatConversionCharInternal::o):
as_digits.PrintAsOct(static_cast<U>(v));
break;
- case FormatConversionCharInternal::x:
+ case static_cast<uint8_t>(FormatConversionCharInternal::x):
as_digits.PrintAsHexLower(static_cast<U>(v));
break;
- case FormatConversionCharInternal::X:
+ case static_cast<uint8_t>(FormatConversionCharInternal::X):
as_digits.PrintAsHexUpper(static_cast<U>(v));
break;
- case FormatConversionCharInternal::u:
+ case static_cast<uint8_t>(FormatConversionCharInternal::u):
as_digits.PrintAsDec(static_cast<U>(v));
break;
- case FormatConversionCharInternal::d:
- case FormatConversionCharInternal::i:
+ case static_cast<uint8_t>(FormatConversionCharInternal::d):
+ case static_cast<uint8_t>(FormatConversionCharInternal::i):
as_digits.PrintAsDec(v);
break;
- case FormatConversionCharInternal::a:
- case FormatConversionCharInternal::e:
- case FormatConversionCharInternal::f:
- case FormatConversionCharInternal::g:
- case FormatConversionCharInternal::A:
- case FormatConversionCharInternal::E:
- case FormatConversionCharInternal::F:
- case FormatConversionCharInternal::G:
+ case static_cast<uint8_t>(FormatConversionCharInternal::a):
+ case static_cast<uint8_t>(FormatConversionCharInternal::e):
+ case static_cast<uint8_t>(FormatConversionCharInternal::f):
+ case static_cast<uint8_t>(FormatConversionCharInternal::g):
+ case static_cast<uint8_t>(FormatConversionCharInternal::A):
+ case static_cast<uint8_t>(FormatConversionCharInternal::E):
+ case static_cast<uint8_t>(FormatConversionCharInternal::F):
+ case static_cast<uint8_t>(FormatConversionCharInternal::G):
return ConvertFloatImpl(static_cast<double>(v), conv, sink);
default:
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h
index 8f79948bd91..3dbc1526d06 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h
@@ -25,6 +25,10 @@ class Cord;
class FormatCountCapture;
class FormatSink;
+template <absl::FormatConversionCharSet C>
+struct FormatConvertResult;
+class FormatConversionSpec;
+
namespace str_format_internal {
template <typename T, typename = void>
@@ -37,6 +41,22 @@ struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
std::declval<FormatSink*>()))>>
: std::true_type {};
+void AbslFormatConvert(); // Stops the lexical name lookup
+template <typename T>
+auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink)
+ -> decltype(AbslFormatConvert(v,
+ std::declval<const FormatConversionSpec&>(),
+ std::declval<FormatSink*>())) {
+ using FormatConversionSpecT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
+ using FormatSinkT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+ auto fcs = conv.Wrap<FormatConversionSpecT>();
+ auto fs = sink->Wrap<FormatSinkT>();
+ return AbslFormatConvert(v, fcs, &fs);
+}
+
template <typename T>
class StreamedWrapper;
@@ -44,6 +64,13 @@ class StreamedWrapper;
// then convert it, appending to `sink` and return `true`.
// Otherwise fail and return `false`.
+// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
+// as an extension mechanism. These FormatConvertImpl functions are the default
+// implementations.
+// The ADL search is augmented via the 'Sink*' parameter, which also
+// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
+// functions in the namespaces associated with 'v'.
+
// Raw pointers.
struct VoidPtr {
VoidPtr() = default;
@@ -60,6 +87,11 @@ struct ArgConvertResult {
};
template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
+ return C;
+}
+
+template <FormatConversionCharSet C>
constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
return C;
}
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
index 37e5b7545f8..f53fd6bd145 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
@@ -23,8 +23,17 @@ class FormatArgImplTest : public ::testing::Test {
enum Color { kRed, kGreen, kBlue };
static const char *hi() { return "hi"; }
+
+ struct X {};
+
+ X x_;
};
+inline FormatConvertResult<FormatConversionCharSet{}> AbslFormatConvert(
+ const FormatArgImplTest::X &, const FormatConversionSpec &, FormatSink *) {
+ return {false};
+}
+
TEST_F(FormatArgImplTest, ToInt) {
int out = 0;
EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(1), &out));
@@ -59,6 +68,7 @@ TEST_F(FormatArgImplTest, ToInt) {
FormatArgImpl(static_cast<int *>(nullptr)), &out));
EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(hi()), &out));
EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl("hi"), &out));
+ EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(x_), &out));
EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(kBlue), &out));
EXPECT_EQ(2, out);
}
@@ -96,8 +106,8 @@ TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) {
std::string s;
FormatSinkImpl sink(&s);
FormatConversionSpecImpl conv;
- FormatConversionSpecImplFriend::SetConversionChar(FormatConversionChar::s,
- &conv);
+ FormatConversionSpecImplFriend::SetConversionChar(
+ FormatConversionCharInternal::s, &conv);
FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);
FormatConversionSpecImplFriend::SetWidth(-1, &conv);
FormatConversionSpecImplFriend::SetPrecision(-1, &conv);
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
index 233481747bf..a76d70b0586 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
@@ -11,13 +11,13 @@ namespace {
std::string ConvToString(FormatConversionCharSet conv) {
std::string out;
-#define CONV_SET_CASE(c) \
- if (Contains(conv, FormatConversionCharSet::c)) { \
- out += #c; \
+#define CONV_SET_CASE(c) \
+ if (Contains(conv, FormatConversionCharSetInternal::c)) { \
+ out += #c; \
}
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
#undef CONV_SET_CASE
- if (Contains(conv, FormatConversionCharSet::kStar)) {
+ if (Contains(conv, FormatConversionCharSetInternal::kStar)) {
out += "*";
}
return out;
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
index 20c6229fcb3..0e8535c27b7 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
@@ -764,6 +764,12 @@ TEST_F(FormatConvertTest, LongDouble) {
}
}
+ // Regression tests
+ //
+ // Using a string literal because not all platforms support hex literals or it
+ // might be out of range.
+ doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr));
+
for (const char *fmt : kFormats) {
for (char f : {'f', 'F', //
'g', 'G', //
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc
index 2e5bc2ce0be..bb0d96cf321 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc
@@ -33,16 +33,40 @@ std::string Flags::ToString() const {
return s;
}
-bool FormatSinkImpl::PutPaddedString(string_view v, int w, int p, bool l) {
+#define ABSL_INTERNAL_X_VAL(id) \
+ constexpr absl::FormatConversionChar FormatConversionCharInternal::id;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr absl::FormatConversionChar FormatConversionCharInternal::kNone;
+
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ constexpr FormatConversionCharSet FormatConversionCharSetInternal::c;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
+
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kStar;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kIntegral;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kFloating;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kNumeric;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
+
+bool FormatSinkImpl::PutPaddedString(string_view value, int width,
+ int precision, bool left) {
size_t space_remaining = 0;
- if (w >= 0) space_remaining = w;
- size_t n = v.size();
- if (p >= 0) n = std::min(n, static_cast<size_t>(p));
- string_view shown(v.data(), n);
+ if (width >= 0) space_remaining = width;
+ size_t n = value.size();
+ if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
+ string_view shown(value.data(), n);
space_remaining = Excess(shown.size(), space_remaining);
- if (!l) Append(space_remaining, ' ');
+ if (!left) Append(space_remaining, ' ');
Append(shown);
- if (l) Append(space_remaining, ' ');
+ if (left) Append(space_remaining, ' ');
return true;
}
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h
index 36e70646d7d..a9b9e137deb 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h
@@ -31,9 +31,10 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-enum class FormatConversionCharSet : uint64_t;
enum class FormatConversionChar : uint8_t;
+enum class FormatConversionCharSet : uint64_t;
+
+namespace str_format_internal {
class FormatRawSinkImpl {
public:
@@ -106,7 +107,7 @@ class FormatSinkImpl {
size_t size() const { return size_; }
// Put 'v' to 'sink' with specified width, precision, and left flag.
- bool PutPaddedString(string_view v, int w, int p, bool l);
+ bool PutPaddedString(string_view v, int width, int precision, bool left);
template <typename T>
T Wrap() {
@@ -360,14 +361,12 @@ struct FormatConversionCharSetInternal {
static constexpr FormatConversionCharSet kStar =
FormatConversionCharToConvValue('*');
- // Some predefined values (TODO(matthewbr), delete any that are unused).
static constexpr FormatConversionCharSet kIntegral =
FormatConversionCharSetUnion(d, i, u, o, x, X);
static constexpr FormatConversionCharSet kFloating =
FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
static constexpr FormatConversionCharSet kNumeric =
FormatConversionCharSetUnion(kIntegral, kFloating);
- static constexpr FormatConversionCharSet kString = s;
static constexpr FormatConversionCharSet kPointer = p;
};
@@ -420,81 +419,6 @@ inline size_t Excess(size_t used, size_t capacity) {
return used < capacity ? capacity - used : 0;
}
-class FormatConversionSpec {
- public:
- // Width and precison are not specified, no flags are set.
- bool is_basic() const { return impl_.is_basic(); }
- bool has_left_flag() const { return impl_.has_left_flag(); }
- bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
- bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
- bool has_alt_flag() const { return impl_.has_alt_flag(); }
- bool has_zero_flag() const { return impl_.has_zero_flag(); }
-
- FormatConversionChar conversion_char() const {
- return impl_.conversion_char();
- }
-
- // Returns the specified width. If width is unspecfied, it returns a negative
- // value.
- int width() const { return impl_.width(); }
- // Returns the specified precision. If precision is unspecfied, it returns a
- // negative value.
- int precision() const { return impl_.precision(); }
-
- private:
- explicit FormatConversionSpec(
- str_format_internal::FormatConversionSpecImpl impl)
- : impl_(impl) {}
-
- friend str_format_internal::FormatConversionSpecImpl;
-
- absl::str_format_internal::FormatConversionSpecImpl impl_;
-};
-
-// clang-format off
-enum class FormatConversionChar : uint8_t {
- c, s, // text
- d, i, o, u, x, X, // int
- f, F, e, E, g, G, a, A, // float
- n, p // misc
-};
-// clang-format on
-
-enum class FormatConversionCharSet : uint64_t {
- // text
- c = str_format_internal::FormatConversionCharToConvInt('c'),
- s = str_format_internal::FormatConversionCharToConvInt('s'),
- // integer
- d = str_format_internal::FormatConversionCharToConvInt('d'),
- i = str_format_internal::FormatConversionCharToConvInt('i'),
- o = str_format_internal::FormatConversionCharToConvInt('o'),
- u = str_format_internal::FormatConversionCharToConvInt('u'),
- x = str_format_internal::FormatConversionCharToConvInt('x'),
- X = str_format_internal::FormatConversionCharToConvInt('X'),
- // Float
- f = str_format_internal::FormatConversionCharToConvInt('f'),
- F = str_format_internal::FormatConversionCharToConvInt('F'),
- e = str_format_internal::FormatConversionCharToConvInt('e'),
- E = str_format_internal::FormatConversionCharToConvInt('E'),
- g = str_format_internal::FormatConversionCharToConvInt('g'),
- G = str_format_internal::FormatConversionCharToConvInt('G'),
- a = str_format_internal::FormatConversionCharToConvInt('a'),
- A = str_format_internal::FormatConversionCharToConvInt('A'),
- // misc
- n = str_format_internal::FormatConversionCharToConvInt('n'),
- p = str_format_internal::FormatConversionCharToConvInt('p'),
-
- // Used for width/precision '*' specification.
- kStar = str_format_internal::FormatConversionCharToConvInt('*'),
-
- // Some predefined values:
- kIntegral = d | i | u | o | x | X,
- kFloating = a | e | f | g | A | E | F | G,
- kNumeric = kIntegral | kFloating,
- kString = s,
- kPointer = p,
-};
-
} // namespace str_format_internal
ABSL_NAMESPACE_END
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
index 0a023f9c033..1c93fdb1c75 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
@@ -80,4 +80,19 @@ TEST(FormatExtensionTest, SinkAppendChars) {
EXPECT_EQ(actual, expected);
}
}
+
+TEST(FormatExtensionTest, VerifyEnumEquality) {
+#define X_VAL(id) \
+ EXPECT_EQ(absl::FormatConversionChar::id, \
+ absl::str_format_internal::FormatConversionCharInternal::id);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );
+#undef X_VAL
+
+#define X_VAL(id) \
+ EXPECT_EQ(absl::FormatConversionCharSet::id, \
+ absl::str_format_internal::FormatConversionCharSetInternal::id);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );
+#undef X_VAL
+}
+
} // namespace
diff --git a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
index a761a5a5f9c..10e4695411b 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
@@ -224,13 +224,13 @@ class FractionalDigitGenerator {
// This function will allocate enough stack space to perform the conversion.
static void RunConversion(
uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {
+ using Limits = std::numeric_limits<long double>;
assert(-exp < 0);
- assert(-exp >= std::numeric_limits<long double>::min_exponent - 128);
- static_assert(
- StackArray::kMaxCapacity >=
- (128 - std::numeric_limits<long double>::min_exponent + 31) / 32,
- "");
- StackArray::RunWithCapacity((exp + 31) / 32,
+ assert(-exp >= Limits::min_exponent - 128);
+ static_assert(StackArray::kMaxCapacity >=
+ (Limits::digits + 128 - Limits::min_exponent + 31) / 32,
+ "");
+ StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
[=](absl::Span<uint32_t> input) {
f(FractionalDigitGenerator(input, v, exp));
});
diff --git a/chromium/third_party/abseil-cpp/absl/strings/str_format.h b/chromium/third_party/abseil-cpp/absl/strings/str_format.h
index f48510b45b3..01465107e10 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/str_format.h
+++ b/chromium/third_party/abseil-cpp/absl/strings/str_format.h
@@ -19,7 +19,7 @@
//
// The `str_format` library is a typesafe replacement for the family of
// `printf()` string formatting routines within the `<cstdio>` standard library
-// header. Like the `printf` family, the `str_format` uses a "format string" to
+// header. Like the `printf` family, `str_format` uses a "format string" to
// perform argument substitutions based on types. See the `FormatSpec` section
// below for format string documentation.
//
@@ -65,8 +65,7 @@
// boolean from a runtime check.
//
// In addition, the `str_format` library provides extension points for
-// augmenting formatting to new types. These extensions are fully documented
-// within the `str_format_extension.h` header file.
+// augmenting formatting to new types. See "StrFormat Extensions" below.
#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
@@ -282,9 +281,36 @@ using FormatSpec = str_format_internal::FormatSpecTemplate<
// } else {
// ... error case ...
// }
+
+#if defined(__cpp_nontype_template_parameter_auto)
+// If C++17 is available, an 'extended' format is also allowed that can specify
+// multiple conversion characters per format argument, using a combination of
+// `absl::FormatConversionCharSet` enum values (logically a set union)
+// via the `|` operator. (Single character-based arguments are still accepted,
+// but cannot be combined). Some common conversions also have predefined enum
+// values, such as `absl::FormatConversionCharSet::kIntegral`.
+//
+// Example:
+// // Extended format supports multiple conversion characters per argument,
+// // specified via a combination of `FormatConversionCharSet` enums.
+// using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
+// absl::FormatConversionCharSet::x>;
+// MyFormat GetFormat(bool use_hex) {
+// if (use_hex) return MyFormat("foo %x bar");
+// return MyFormat("foo %d bar");
+// }
+// // `format` can be used with any value that supports 'd' and 'x',
+// // like `int`.
+// auto format = GetFormat(use_hex);
+// value = StringF(format, i);
+template <auto... Conv>
+using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
+ absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#else
template <char... Conv>
using ParsedFormat = str_format_internal::ExtendedParsedFormat<
absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#endif // defined(__cpp_nontype_template_parameter_auto)
// StrFormat()
//
@@ -541,6 +567,246 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped(
str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
}
+//------------------------------------------------------------------------------
+// StrFormat Extensions
+//------------------------------------------------------------------------------
+//
+// AbslFormatConvert()
+//
+// The StrFormat library provides a customization API for formatting
+// user-defined types using absl::StrFormat(). The API relies on detecting an
+// overload in the user-defined type's namespace of a free (non-member)
+// `AbslFormatConvert()` function, usually as a friend definition with the
+// following signature:
+//
+// absl::FormatConvertResult<...> AbslFormatConvert(
+// const X& value,
+// const absl::FormatConversionSpec& spec,
+// absl::FormatSink *sink);
+//
+// An `AbslFormatConvert()` overload for a type should only be declared in the
+// same file and namespace as said type.
+//
+// The abstractions within this definition include:
+//
+// * An `absl::FormatConversionSpec` to specify the fields to pull from a
+// user-defined type's format string
+// * An `absl::FormatSink` to hold the converted string data during the
+// conversion process.
+// * An `absl::FormatConvertResult` to hold the status of the returned
+// formatting operation
+//
+// The return type encodes all the conversion characters that your
+// AbslFormatConvert() routine accepts. The return value should be {true}.
+// A return value of {false} will result in `StrFormat()` returning
+// an empty string. This result will be propagated to the result of
+// `FormatUntyped`.
+//
+// Example:
+//
+// struct Point {
+// // To add formatting support to `Point`, we simply need to add a free
+// // (non-member) function `AbslFormatConvert()`. This method interprets
+// // `spec` to print in the request format. The allowed conversion characters
+// // can be restricted via the type of the result, in this example
+// // string and integral formatting are allowed (but not, for instance
+// // floating point characters like "%f"). You can add such a free function
+// // using a friend declaration within the body of the class:
+// friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+// absl::FormatConversionCharSet::kIntegral>
+// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+// absl::FormatSink* s) {
+// if (spec.conversion_char() == absl::FormatConversionChar::s) {
+// s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+// } else {
+// s->Append(absl::StrCat(p.x, ",", p.y));
+// }
+// return {true};
+// }
+//
+// int x;
+// int y;
+// };
+
+// clang-format off
+
+// FormatConversionChar
+//
+// Specifies the formatting character provided in the format string
+// passed to `StrFormat()`.
+enum class FormatConversionChar : uint8_t {
+ c, s, // text
+ d, i, o, u, x, X, // int
+ f, F, e, E, g, G, a, A, // float
+ n, p // misc
+};
+// clang-format on
+
+// FormatConversionSpec
+//
+// Specifies modifications to the conversion of the format string, through use
+// of one or more format flags in the source format string.
+class FormatConversionSpec {
+ public:
+ // FormatConversionSpec::is_basic()
+ //
+ // Indicates that width and precision are not specified, and no additional
+ // flags are set for this conversion character in the format string.
+ bool is_basic() const { return impl_.is_basic(); }
+
+ // FormatConversionSpec::has_left_flag()
+ //
+ // Indicates whether the result should be left justified for this conversion
+ // character in the format string. This flag is set through use of a '-'
+ // character in the format string. E.g. "%-s"
+ bool has_left_flag() const { return impl_.has_left_flag(); }
+
+ // FormatConversionSpec::has_show_pos_flag()
+ //
+ // Indicates whether a sign column is prepended to the result for this
+ // conversion character in the format string, even if the result is positive.
+ // This flag is set through use of a '+' character in the format string.
+ // E.g. "%+d"
+ bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
+
+ // FormatConversionSpec::has_sign_col_flag()
+ //
+ // Indicates whether a mandatory sign column is added to the result for this
+ // conversion character. This flag is set through use of a space character
+ // (' ') in the format string. E.g. "% i"
+ bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
+
+ // FormatConversionSpec::has_alt_flag()
+ //
+ // Indicates whether an "alternate" format is applied to the result for this
+ // conversion character. Alternative forms depend on the type of conversion
+ // character, and unallowed alternatives are undefined. This flag is set
+ // through use of a '#' character in the format string. E.g. "%#h"
+ bool has_alt_flag() const { return impl_.has_alt_flag(); }
+
+ // FormatConversionSpec::has_zero_flag()
+ //
+ // Indicates whether zeroes should be prepended to the result for this
+ // conversion character instead of spaces. This flag is set through use of the
+ // '0' character in the format string. E.g. "%0f"
+ bool has_zero_flag() const { return impl_.has_zero_flag(); }
+
+ // FormatConversionSpec::conversion_char()
+ //
+ // Returns the underlying conversion character.
+ FormatConversionChar conversion_char() const {
+ return impl_.conversion_char();
+ }
+
+ // FormatConversionSpec::width()
+ //
+ // Returns the specified width (indicated through use of a non-zero integer
+ // value or '*' character) of the conversion character. If width is
+ // unspecified, it returns a negative value.
+ int width() const { return impl_.width(); }
+
+ // FormatConversionSpec::precision()
+ //
+ // Returns the specified precision (through use of the '.' character followed
+ // by a non-zero integer value or '*' character) of the conversion character.
+ // If precision is unspecified, it returns a negative value.
+ int precision() const { return impl_.precision(); }
+
+ private:
+ explicit FormatConversionSpec(
+ str_format_internal::FormatConversionSpecImpl impl)
+ : impl_(impl) {}
+
+ friend str_format_internal::FormatConversionSpecImpl;
+
+ absl::str_format_internal::FormatConversionSpecImpl impl_;
+};
+
+// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
+// conversion chars in custom format converters.
+constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
+ FormatConversionCharSet b) {
+ return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
+ static_cast<uint64_t>(b));
+}
+
+// FormatConversionCharSet
+//
+// Specifies the _accepted_ conversion types as a template parameter to
+// FormatConvertResult for custom implementations of `AbslFormatConvert`.
+// Note the helper predefined alias definitions (kIntegral, etc.) below.
+enum class FormatConversionCharSet : uint64_t {
+ // text
+ c = str_format_internal::FormatConversionCharToConvInt('c'),
+ s = str_format_internal::FormatConversionCharToConvInt('s'),
+ // integer
+ d = str_format_internal::FormatConversionCharToConvInt('d'),
+ i = str_format_internal::FormatConversionCharToConvInt('i'),
+ o = str_format_internal::FormatConversionCharToConvInt('o'),
+ u = str_format_internal::FormatConversionCharToConvInt('u'),
+ x = str_format_internal::FormatConversionCharToConvInt('x'),
+ X = str_format_internal::FormatConversionCharToConvInt('X'),
+ // Float
+ f = str_format_internal::FormatConversionCharToConvInt('f'),
+ F = str_format_internal::FormatConversionCharToConvInt('F'),
+ e = str_format_internal::FormatConversionCharToConvInt('e'),
+ E = str_format_internal::FormatConversionCharToConvInt('E'),
+ g = str_format_internal::FormatConversionCharToConvInt('g'),
+ G = str_format_internal::FormatConversionCharToConvInt('G'),
+ a = str_format_internal::FormatConversionCharToConvInt('a'),
+ A = str_format_internal::FormatConversionCharToConvInt('A'),
+ // misc
+ n = str_format_internal::FormatConversionCharToConvInt('n'),
+ p = str_format_internal::FormatConversionCharToConvInt('p'),
+
+ // Used for width/precision '*' specification.
+ kStar = static_cast<uint64_t>(
+ absl::str_format_internal::FormatConversionCharSetInternal::kStar),
+ // Some predefined values:
+ kIntegral = d | i | u | o | x | X,
+ kFloating = a | e | f | g | A | E | F | G,
+ kNumeric = kIntegral | kFloating,
+ kString = s,
+ kPointer = p,
+};
+
+// FormatSink
+//
+// An abstraction to which conversions write their string data.
+//
+class FormatSink {
+ public:
+ // Appends `count` copies of `ch`.
+ void Append(size_t count, char ch) { sink_->Append(count, ch); }
+
+ void Append(string_view v) { sink_->Append(v); }
+
+ // Appends the first `precision` bytes of `v`. If this is less than
+ // `width`, spaces will be appended first (if `left` is false), or
+ // after (if `left` is true) to ensure the total amount appended is
+ // at least `width`.
+ bool PutPaddedString(string_view v, int width, int precision, bool left) {
+ return sink_->PutPaddedString(v, width, precision, left);
+ }
+
+ private:
+ friend str_format_internal::FormatSinkImpl;
+ explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}
+ str_format_internal::FormatSinkImpl* sink_;
+};
+
+// FormatConvertResult
+//
+// Indicates whether a call to AbslFormatConvert() was successful.
+// This return type informs the StrFormat extension framework (through
+// ADL but using the return type) of what conversion characters are supported.
+// It is strongly discouraged to return {false}, as this will result in an
+// empty string in StrFormat.
+template <FormatConversionCharSet C>
+struct FormatConvertResult {
+ bool value;
+};
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/chromium/third_party/abseil-cpp/absl/strings/str_format_test.cc b/chromium/third_party/abseil-cpp/absl/strings/str_format_test.cc
index 3f14dba3e35..d9fb25af09a 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/str_format_test.cc
+++ b/chromium/third_party/abseil-cpp/absl/strings/str_format_test.cc
@@ -1,4 +1,6 @@
+#include "absl/strings/str_format.h"
+
#include <cstdarg>
#include <cstdint>
#include <cstdio>
@@ -6,7 +8,8 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/strings/str_format.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
namespace absl {
@@ -350,6 +353,7 @@ TEST(StrFormat, BehavesAsDocumented) {
EXPECT_EQ(StrFormat("%s", "C"), "C");
EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
+ EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
// Integral Conversion
// These format integral types: char, int, long, uint64_t, etc.
EXPECT_EQ(StrFormat("%d", char{10}), "10");
@@ -532,103 +536,152 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
}
-using absl::str_format_internal::FormatConversionCharSet;
+#if defined(__cpp_nontype_template_parameter_auto)
+
+template <auto T>
+std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);
+
+template <auto T>
+std::false_type IsValidParsedFormatArgTest(...);
+
+template <auto T>
+using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));
+
+TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {
+ ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);
+
+ ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);
+
+ ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::value);
+ ASSERT_TRUE(
+ IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);
+
+ // This is an easy mistake to make, however, this will reduce to an integer
+ // which has no meaning, so we need to ensure it doesn't compile.
+ ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);
+
+ // For now, we disallow construction based on ConversionChar (rather than
+ // CharSet)
+ ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);
+}
+
+TEST_F(ParsedFormatTest, ExtendedTyping) {
+ EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
+ ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
+ auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s");
+ ASSERT_TRUE(v1);
+ auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s");
+ ASSERT_TRUE(v2);
+ auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::s,
+ 's'>::New("%d%s");
+ ASSERT_TRUE(v3);
+ auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::s,
+ 's'>::New("%s%s");
+ ASSERT_TRUE(v4);
+}
+#endif
TEST_F(ParsedFormatTest, UncheckedCorrect) {
- auto f = ExtendedParsedFormat<FormatConversionCharSet::d>::New("ABC%dDEF");
+ auto f =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
std::string format = "%sFFF%dZZZ%f";
- auto f2 =
- ExtendedParsedFormat<FormatConversionCharSet::kString,
- FormatConversionCharSet::d,
- FormatConversionCharSet::kFloating>::New(format);
+ auto f2 = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::kFloating>::New(format);
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
- f2 =
- ExtendedParsedFormat<FormatConversionCharSet::kString,
- FormatConversionCharSet::d,
- FormatConversionCharSet::kFloating>::New("%s %d %f");
+ f2 = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
- auto star = ExtendedParsedFormat<FormatConversionCharSet::kStar,
- FormatConversionCharSet::d>::New("%*d");
+ auto star =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
+ absl::FormatConversionCharSet::d>::New("%*d");
ASSERT_TRUE(star);
EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
auto dollar =
- ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("%2$s %1$d");
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%2$s %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
// with reuse
- dollar =
- ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
+ dollar = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
SummarizeParsedFormat(*dollar));
}
TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
- EXPECT_FALSE((ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("ABC")));
EXPECT_FALSE(
- (ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("%dABC")));
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("ABC")));
EXPECT_FALSE(
- (ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::New("ABC%2$s")));
- auto f =
- ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::s>::NewAllowIgnored("ABC");
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%dABC")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("ABC%2$s")));
+ auto f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
f = ExtendedParsedFormat<
- FormatConversionCharSet::d,
- FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
ASSERT_TRUE(f);
EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
f = ExtendedParsedFormat<
- FormatConversionCharSet::d,
- FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
}
TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
- auto dx = ExtendedParsedFormat<FormatConversionCharSet::d |
- FormatConversionCharSet::x>::New("%1$d %1$x");
+ auto dx =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::New("%1$d %1$x");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
- dx = ExtendedParsedFormat<FormatConversionCharSet::d |
- FormatConversionCharSet::x>::New("%1$d");
+ dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::New("%1$d");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
}
TEST_F(ParsedFormatTest, UncheckedIncorrect) {
- EXPECT_FALSE(ExtendedParsedFormat<FormatConversionCharSet::d>::New(""));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
- EXPECT_FALSE(
- ExtendedParsedFormat<FormatConversionCharSet::d>::New("ABC%dDEF%d"));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
+ "ABC%dDEF%d"));
std::string format = "%sFFF%dZZZ%f";
- EXPECT_FALSE((ExtendedParsedFormat<FormatConversionCharSet::s,
- FormatConversionCharSet::d,
- FormatConversionCharSet::g>::New(format)));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::g>::New(format)));
}
TEST_F(ParsedFormatTest, RegressionMixPositional) {
EXPECT_FALSE(
- (ExtendedParsedFormat<FormatConversionCharSet::d,
- FormatConversionCharSet::o>::New("%1$d %o")));
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::o>::New("%1$d %o")));
}
using FormatWrapperTest = ::testing::Test;
@@ -653,6 +706,38 @@ TEST_F(FormatWrapperTest, ParsedFormat) {
ABSL_NAMESPACE_END
} // namespace absl
+using FormatExtensionTest = ::testing::Test;
+
+struct Point {
+ friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+ absl::FormatConversionCharSet::kIntegral>
+ AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+ absl::FormatSink* s) {
+ if (spec.conversion_char() == absl::FormatConversionChar::s) {
+ s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+ } else {
+ s->Append(absl::StrCat(p.x, ",", p.y));
+ }
+ return {true};
+ }
+
+ int x = 10;
+ int y = 20;
+};
+
+TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
+ Point p;
+ EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
+ EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
+
+ // Typed formatting will fail to compile an invalid format.
+ // StrFormat("%f", p); // Does not compile.
+ std::string actual;
+ absl::UntypedFormatSpec f1("%f");
+ // FormatUntyped will return false for bad character.
+ EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
+}
+
// Some codegen thunks that we can use to easily dump the generated assembly for
// different StrFormat calls.
diff --git a/chromium/third_party/abseil-cpp/absl/strings/str_split.h b/chromium/third_party/abseil-cpp/absl/strings/str_split.h
index a79cd4a0ce0..1ce17f38aa8 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/str_split.h
+++ b/chromium/third_party/abseil-cpp/absl/strings/str_split.h
@@ -44,6 +44,7 @@
#include <vector>
#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
#include "absl/strings/internal/str_split_internal.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
diff --git a/chromium/third_party/abseil-cpp/absl/strings/string_view.h b/chromium/third_party/abseil-cpp/absl/strings/string_view.h
index 8a9db8c3d79..7fb03330033 100644
--- a/chromium/third_party/abseil-cpp/absl/strings/string_view.h
+++ b/chromium/third_party/abseil-cpp/absl/strings/string_view.h
@@ -586,7 +586,7 @@ constexpr bool operator>=(string_view x, string_view y) noexcept {
}
// IO Insertion Operator
-std::ostream& operator<<(std::ostream& o, string_view piece);
+ABSL_DLL std::ostream& operator<<(std::ostream& o, string_view piece);
ABSL_NAMESPACE_END
} // namespace absl