]>
git.proxmox.com Git - ceph.git/blob - ceph/src/fmt/test/std-format-test.cc
c67a2a0309230478d2f6246c103507d01f95cace
3 #include "gtest/gtest.h"
5 TEST(std_format_test
, escaping
) {
7 string s
= format("{0}-{{", 8); // s == "8-{"
11 TEST(std_format_test
, indexing
) {
13 string s0
= format("{} to {}", "a", "b"); // OK: automatic indexing
14 string s1
= format("{1} to {0}", "a", "b"); // OK: manual indexing
15 EXPECT_EQ(s0
, "a to b");
16 EXPECT_EQ(s1
, "b to a");
17 // Error: mixing automatic and manual indexing
18 EXPECT_THROW(string s2
= format("{0} to {}", "a", "b"), std::format_error
);
19 // Error: mixing automatic and manual indexing
20 EXPECT_THROW(string s3
= format("{} to {1}", "a", "b"), std::format_error
);
23 TEST(std_format_test
, alignment
) {
26 string s0
= format("{:6}", 42); // s0 == " 42"
27 string s1
= format("{:6}", 'x'); // s1 == "x "
28 string s2
= format("{:*<6}", 'x'); // s2 == "x*****"
29 string s3
= format("{:*>6}", 'x'); // s3 == "*****x"
30 string s4
= format("{:*^6}", 'x'); // s4 == "**x***"
31 // Error: '=' with charT and no integer presentation type
32 EXPECT_THROW(string s5
= format("{:=6}", 'x'), std::format_error
);
33 string s6
= format("{:6d}", c
); // s6 == " 120"
34 string s7
= format("{:6}", true); // s9 == "true "
37 EXPECT_EQ(s2
, "x*****");
38 EXPECT_EQ(s3
, "*****x");
39 EXPECT_EQ(s4
, "**x***");
40 EXPECT_EQ(s6
, " 120");
41 EXPECT_EQ(s7
, "true ");
44 TEST(std_format_test
, float) {
46 double inf
= numeric_limits
<double>::infinity();
47 double nan
= numeric_limits
<double>::quiet_NaN();
48 string s0
= format("{0:} {0:+} {0:-} {0: }", 1); // s0 == "1 +1 1 1"
49 string s1
= format("{0:} {0:+} {0:-} {0: }", -1); // s1 == "-1 -1 -1 -1"
51 format("{0:} {0:+} {0:-} {0: }", inf
); // s2 == "inf +inf inf inf"
53 format("{0:} {0:+} {0:-} {0: }", nan
); // s3 == "nan +nan nan nan"
54 EXPECT_EQ(s0
, "1 +1 1 1");
55 EXPECT_EQ(s1
, "-1 -1 -1 -1");
56 EXPECT_EQ(s2
, "inf +inf inf inf");
57 EXPECT_EQ(s3
, "nan +nan nan nan");
60 TEST(std_format_test
, int) {
62 string s0
= format("{}", 42); // s0 == "42"
63 string s1
= format("{0:b} {0:d} {0:o} {0:x}", 42); // s1 == "101010 42 52 2a"
64 string s2
= format("{0:#x} {0:#X}", 42); // s2 == "0x2a 0X2A"
65 string s3
= format("{:L}", 1234); // s3 == "1234" (depends on the locale)
67 EXPECT_EQ(s1
, "101010 42 52 2a");
68 EXPECT_EQ(s2
, "0x2a 0X2A");
69 EXPECT_EQ(s3
, "1234");
74 enum color
{ red
, green
, blue
};
76 const char* color_names
[] = {"red", "green", "blue"};
78 template <> struct std::formatter
<color
> : std::formatter
<const char*> {
79 auto format(color c
, format_context
& ctx
) {
80 return formatter
<const char*>::format(color_names
[c
], ctx
);
86 TEST(std_format_test
, formatter
) {
87 std::string s0
= std::format("{}", 42); // OK: library-provided formatter
88 // std::string s1 = std::format("{}", L"foo"); // Ill-formed: disabled
90 std::string s2
= std::format("{}", red
); // OK: user-provided formatter
91 // std::string s3 = std::format("{}", err{}); // Ill-formed: disabled
101 template <> struct std::formatter
<S
> {
102 size_t width_arg_id
= 0;
104 // Parses a width argument id in the format { <digit> }.
105 constexpr auto parse(format_parse_context
& ctx
) {
106 constexpr auto is_ascii_digit
= [](const char c
) {
107 return c
>= '0' && c
<= '9';
110 auto iter
= ctx
.begin();
111 // auto get_char = [&]() { return iter != ctx.end() ? *iter : 0; };
112 auto get_char
= [&]() { return iter
!= ctx
.end() ? *iter
: '\0'; };
113 if (get_char() != '{') return iter
;
116 if (!is_ascii_digit(c
) || (++iter
, get_char()) != '}')
117 throw format_error("invalid format");
118 width_arg_id
= fmt::detail::to_unsigned(c
- '0');
119 ctx
.check_arg_id(width_arg_id
);
123 // Formats S with width given by the argument width_arg_id.
124 auto format(S s
, format_context
& ctx
) {
125 int width
= visit_format_arg(
126 [](auto value
) -> int {
127 using type
= decltype(value
);
128 if constexpr (!is_integral_v
<type
> || is_same_v
<type
, bool>)
129 throw format_error("width is not integral");
130 // else if (value < 0 || value > numeric_limits<int>::max())
131 else if (fmt::detail::is_negative(value
) ||
132 value
> numeric_limits
<int>::max())
133 throw format_error("invalid width");
135 return static_cast<int>(value
);
137 ctx
.arg(width_arg_id
));
138 return format_to(ctx
.out(), "{0:{1}}", s
.value
, width
);
142 TEST(std_format_test
, parsing
) {
143 std::string s
= std::format("{0:{1}}", S
{42}, 10); // s == " 42"
148 template <> struct std::formatter
<__int128_t
> : std::formatter
<long long> {
149 auto format(__int128_t n
, format_context
& ctx
) {
150 // Format as a long long since we only want to check if it is possible to
151 // specialize formatter for __int128_t.
152 return formatter
<long long>::format(static_cast<long long>(n
), ctx
);
156 TEST(std_format_test
, int128
) {
158 auto s
= std::format("{}", n
);
161 #endif // FMT_USE_INT128