Export of internal Abseil changes
-- d857e6e1f9b09a3eb5abd890677a98b23346f07a by Abseil Team <absl-team@google.com>: Simplify internal TryAcquireWithSpinning. No point declaring the `result` variable: we can just return the results directly. PiperOrigin-RevId: 307045800 -- 421952252bc23be51f47f7d23f3422bad1ed382c by Derek Mauro <dmauro@google.com>: Add custom sink support for `absl::Format()` through an ADL extension mechanism. Users can now define `void AbslFormatFlush(MySink* dest, absl::string_view part)` to allow `absl::Format()` to append to a custom sink. PiperOrigin-RevId: 306929052 -- c73d5cdb62cd58ea421ed1aeeab78a0ffcfeeefb by Matt Calabrese <calabrese@google.com>: Internal-only conformance-testing macro ABSL_INTERNAL_ASSERT_CONFORMANCE_OF for compile-time and runtime checks of a specified type, expected properties of that type, and a logically-ordered series of equivalence classes of that type. PiperOrigin-RevId: 306885512 -- a8c2495a07f37d68907855e3f0535bd5c27a3b52 by Abseil Team <absl-team@google.com>: Internal change PiperOrigin-RevId: 306766753 GitOrigin-RevId: d857e6e1f9b09a3eb5abd890677a98b23346f07a Change-Id: Ic23c92ac74f9ffcbb2471ff8c6691f4b7b20354b
This commit is contained in:
parent
db5773a721
commit
b35973e3e3
16 changed files with 3096 additions and 44 deletions
|
|
@ -651,6 +651,7 @@ cc_test(
|
|||
copts = ABSL_TEST_COPTS,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":cord",
|
||||
":str_format",
|
||||
":strings",
|
||||
"//absl/base:core_headers",
|
||||
|
|
@ -666,8 +667,10 @@ cc_test(
|
|||
copts = ABSL_TEST_COPTS,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":cord",
|
||||
":str_format",
|
||||
":str_format_internal",
|
||||
":strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
|
@ -726,6 +729,7 @@ cc_test(
|
|||
copts = ABSL_TEST_COPTS,
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
":cord",
|
||||
":str_format_internal",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -409,6 +409,7 @@ absl_cc_test(
|
|||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::str_format
|
||||
absl::cord
|
||||
absl::strings
|
||||
absl::core_headers
|
||||
gmock_main
|
||||
|
|
@ -424,6 +425,8 @@ absl_cc_test(
|
|||
DEPS
|
||||
absl::str_format
|
||||
absl::str_format_internal
|
||||
absl::cord
|
||||
absl::strings
|
||||
gmock_main
|
||||
)
|
||||
|
||||
|
|
@ -487,6 +490,7 @@ absl_cc_test(
|
|||
${ABSL_TEST_COPTS}
|
||||
DEPS
|
||||
absl::str_format_internal
|
||||
absl::cord
|
||||
gmock_main
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,9 +19,27 @@
|
|||
#include <random>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
|
||||
#include "absl/strings/cord.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
|
||||
namespace my_namespace {
|
||||
class UserDefinedType {
|
||||
public:
|
||||
UserDefinedType() = default;
|
||||
|
||||
void Append(absl::string_view str) { value_.append(str.data(), str.size()); }
|
||||
const std::string& Value() const { return value_; }
|
||||
|
||||
friend void AbslFormatFlush(UserDefinedType* x, absl::string_view str) {
|
||||
x->Append(str);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
};
|
||||
} // namespace my_namespace
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -63,4 +81,21 @@ TEST(FormatExtensionTest, SinkAppendChars) {
|
|||
EXPECT_EQ(actual, expected);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FormatExtensionTest, CordSink) {
|
||||
absl::Cord c;
|
||||
absl::Format(&c, "There were %04d little %s.", 3, "pigs");
|
||||
EXPECT_EQ(c, "There were 0003 little pigs.");
|
||||
absl::Format(&c, "And %-3llx bad wolf!", 1);
|
||||
EXPECT_EQ(c, "There were 0003 little pigs.And 1 bad wolf!");
|
||||
}
|
||||
|
||||
TEST(FormatExtensionTest, CustomSink) {
|
||||
my_namespace::UserDefinedType sink;
|
||||
absl::Format(&sink, "There were %04d little %s.", 3, "pigs");
|
||||
EXPECT_EQ("There were 0003 little pigs.", sink.Value());
|
||||
absl::Format(&sink, "And %-3llx bad wolf!", 1);
|
||||
EXPECT_EQ("There were 0003 little pigs.And 1 bad wolf!", sink.Value());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -91,10 +91,11 @@ inline void AbslFormatFlush(BufferRawSink* sink, string_view v) {
|
|||
sink->Write(v);
|
||||
}
|
||||
|
||||
// This is a SFINAE to get a better compiler error message when the type
|
||||
// is not supported.
|
||||
template <typename T>
|
||||
auto InvokeFlush(T* out, string_view s)
|
||||
-> decltype(str_format_internal::AbslFormatFlush(out, s)) {
|
||||
str_format_internal::AbslFormatFlush(out, s);
|
||||
auto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {
|
||||
AbslFormatFlush(out, s);
|
||||
}
|
||||
|
||||
} // namespace str_format_internal
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/cord.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
|
@ -37,6 +38,12 @@ TEST(InvokeFlush, Stream) {
|
|||
EXPECT_EQ(str.str(), "ABCDEF");
|
||||
}
|
||||
|
||||
TEST(InvokeFlush, Cord) {
|
||||
absl::Cord str("ABC");
|
||||
str_format_internal::InvokeFlush(&str, "DEF");
|
||||
EXPECT_EQ(str, "ABCDEF");
|
||||
}
|
||||
|
||||
TEST(BufferRawSink, Limits) {
|
||||
char buf[16];
|
||||
{
|
||||
|
|
@ -70,4 +77,3 @@ TEST(BufferRawSink, Limits) {
|
|||
} // namespace
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,7 @@
|
|||
// arbitrary sink types:
|
||||
//
|
||||
// * A generic `Format()` function to write outputs to arbitrary sink types,
|
||||
// which must implement a `RawSinkFormat` interface. (See
|
||||
// `str_format_sink.h` for more information.)
|
||||
// which must implement a `FormatRawSink` interface.
|
||||
//
|
||||
// * A `FormatUntyped()` function that is similar to `Format()` except it is
|
||||
// loosely typed. `FormatUntyped()` is not a template and does not perform
|
||||
|
|
@ -432,6 +431,16 @@ int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format,
|
|||
//
|
||||
// FormatRawSink is a type erased wrapper around arbitrary sink objects
|
||||
// specifically used as an argument to `Format()`.
|
||||
//
|
||||
// All the object has to do define an overload of `AbslFormatFlush()` for the
|
||||
// sink, usually by adding a ADL-based free function in the same namespace as
|
||||
// the sink:
|
||||
//
|
||||
// void AbslFormatFlush(MySink* dest, absl::string_view part);
|
||||
//
|
||||
// where `dest` is the pointer passed to `absl::Format()`. The function should
|
||||
// append `part` to `dest`.
|
||||
//
|
||||
// FormatRawSink does not own the passed sink object. The passed object must
|
||||
// outlive the FormatRawSink.
|
||||
class FormatRawSink {
|
||||
|
|
@ -455,12 +464,13 @@ class FormatRawSink {
|
|||
// `absl::FormatRawSink` interface), using a format string and zero or more
|
||||
// additional arguments.
|
||||
//
|
||||
// By default, `std::string` and `std::ostream` are supported as destination
|
||||
// objects. If a `std::string` is used the formatted string is appended to it.
|
||||
// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as
|
||||
// destination objects. If a `std::string` is used the formatted string is
|
||||
// appended to it.
|
||||
//
|
||||
// `absl::Format()` is a generic version of `absl::StrFormat(), for custom
|
||||
// sinks. The format string, like format strings for `StrFormat()`, is checked
|
||||
// at compile-time.
|
||||
// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for
|
||||
// custom sinks. The format string, like format strings for `StrFormat()`, is
|
||||
// checked at compile-time.
|
||||
//
|
||||
// On failure, this function returns `false` and the state of the sink is
|
||||
// unspecified.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue