summaryrefslogtreecommitdiff
path: root/absl/strings/internal
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-06-17 14:16:51 -0700
committerGravatar Andy Getz <durandal@google.com>2020-06-18 16:10:44 -0400
commit4ccc0fce09836a25b474f4b1453146dae2c29f4d (patch)
treeeb4e2c17bd7a605337192b21af4e9fe694b6e429 /absl/strings/internal
parent4a851046a0102cd986a5714a1af8deef28a544c4 (diff)
Export of internal Abseil changes
-- 34c0d521b11ed4191ea3e071a864a84e5e5941b7 by Matthew Brown <matthewbr@google.com>: Release absl::StrFormat custom type extensions - Allows StrFormat methods to be extended to accept types which implement AbslFormatConvert() - NOLINTNEXTLINE(readability-redundant-declaration) used, declarations are required in some compilers. PiperOrigin-RevId: 316963065 -- 4d475b5ad02d41057447d722ad35573fc4f48d1f by Evan Brown <ezb@google.com>: Small fix to previous change: the first overload of insert_iterator_unique wasn't actually being selected. Fix that issue and add tests to verify that it actually works. Note: couldn't use TestInstanceTracker here because that counts instances (and decrements in destructor) rather than counting all constructor calls. PiperOrigin-RevId: 316927690 GitOrigin-RevId: 34c0d521b11ed4191ea3e071a864a84e5e5941b7 Change-Id: If8bbb8317b93af4084ac4cc55b752b99b1581b58
Diffstat (limited to 'absl/strings/internal')
-rw-r--r--absl/strings/internal/str_format/arg.h34
-rw-r--r--absl/strings/internal/str_format/arg_test.cc10
-rw-r--r--absl/strings/internal/str_format/extension.cc23
-rw-r--r--absl/strings/internal/str_format/extension.h6
-rw-r--r--absl/strings/internal/str_format/extension_test.cc15
5 files changed, 82 insertions, 6 deletions
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index d441e87f..3dbc1526 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -25,10 +25,12 @@ class Cord;
class FormatCountCapture;
class FormatSink;
-namespace str_format_internal {
-
+template <absl::FormatConversionCharSet C>
+struct FormatConvertResult;
class FormatConversionSpec;
+namespace str_format_internal {
+
template <typename T, typename = void>
struct HasUserDefinedConvert : std::false_type {};
@@ -39,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;
@@ -46,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;
@@ -62,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/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc
index bf3d7e8e..f53fd6bd 100644
--- a/absl/strings/internal/str_format/arg_test.cc
+++ b/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);
}
diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc
index 94f2b9c2..bb0d96cf 100644
--- a/absl/strings/internal/str_format/extension.cc
+++ b/absl/strings/internal/str_format/extension.cc
@@ -33,6 +33,29 @@ std::string Flags::ToString() const {
return s;
}
+#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;
diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h
index 6c60c6c3..a9b9e137 100644
--- a/absl/strings/internal/str_format/extension.h
+++ b/absl/strings/internal/str_format/extension.h
@@ -31,11 +31,11 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace str_format_internal {
-
enum class FormatConversionChar : uint8_t;
enum class FormatConversionCharSet : uint64_t;
+namespace str_format_internal {
+
class FormatRawSinkImpl {
public:
// Implicitly convert from any type that provides the hook function as
@@ -361,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;
};
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc
index 0a023f9c..1c93fdb1 100644
--- a/absl/strings/internal/str_format/extension_test.cc
+++ b/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