1*5c90c05cSAndroid Build Coastguard Worker // Formatting library for C++ - formatting library implementation tests
2*5c90c05cSAndroid Build Coastguard Worker //
3*5c90c05cSAndroid Build Coastguard Worker // Copyright (c) 2012 - present, Victor Zverovich
4*5c90c05cSAndroid Build Coastguard Worker // All rights reserved.
5*5c90c05cSAndroid Build Coastguard Worker //
6*5c90c05cSAndroid Build Coastguard Worker // For the license information refer to format.h.
7*5c90c05cSAndroid Build Coastguard Worker
8*5c90c05cSAndroid Build Coastguard Worker #include <algorithm>
9*5c90c05cSAndroid Build Coastguard Worker #include <cstring>
10*5c90c05cSAndroid Build Coastguard Worker
11*5c90c05cSAndroid Build Coastguard Worker // clang-format off
12*5c90c05cSAndroid Build Coastguard Worker #include "test-assert.h"
13*5c90c05cSAndroid Build Coastguard Worker // clang-format on
14*5c90c05cSAndroid Build Coastguard Worker
15*5c90c05cSAndroid Build Coastguard Worker #include "fmt/format.h"
16*5c90c05cSAndroid Build Coastguard Worker #include "gmock/gmock.h"
17*5c90c05cSAndroid Build Coastguard Worker #include "util.h"
18*5c90c05cSAndroid Build Coastguard Worker
19*5c90c05cSAndroid Build Coastguard Worker using fmt::detail::bigint;
20*5c90c05cSAndroid Build Coastguard Worker using fmt::detail::fp;
21*5c90c05cSAndroid Build Coastguard Worker using fmt::detail::max_value;
22*5c90c05cSAndroid Build Coastguard Worker
23*5c90c05cSAndroid Build Coastguard Worker static_assert(!std::is_copy_constructible<bigint>::value, "");
24*5c90c05cSAndroid Build Coastguard Worker static_assert(!std::is_copy_assignable<bigint>::value, "");
25*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,construct)26*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, construct) {
27*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(bigint()), "");
28*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(bigint(0x42)), "42");
29*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(bigint(0x123456789abcedf0)), "123456789abcedf0");
30*5c90c05cSAndroid Build Coastguard Worker }
31*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,compare)32*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, compare) {
33*5c90c05cSAndroid Build Coastguard Worker bigint n1(42);
34*5c90c05cSAndroid Build Coastguard Worker bigint n2(42);
35*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(compare(n1, n2), 0);
36*5c90c05cSAndroid Build Coastguard Worker n2 <<= 32;
37*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(compare(n1, n2), 0);
38*5c90c05cSAndroid Build Coastguard Worker bigint n3(43);
39*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(compare(n1, n3), 0);
40*5c90c05cSAndroid Build Coastguard Worker EXPECT_GT(compare(n3, n1), 0);
41*5c90c05cSAndroid Build Coastguard Worker bigint n4(42 * 0x100000001);
42*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(compare(n2, n4), 0);
43*5c90c05cSAndroid Build Coastguard Worker EXPECT_GT(compare(n4, n2), 0);
44*5c90c05cSAndroid Build Coastguard Worker }
45*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,add_compare)46*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, add_compare) {
47*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(
48*5c90c05cSAndroid Build Coastguard Worker add_compare(bigint(0xffffffff), bigint(0xffffffff), bigint(1) <<= 64), 0);
49*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(add_compare(bigint(1) <<= 32, bigint(1), bigint(1) <<= 96), 0);
50*5c90c05cSAndroid Build Coastguard Worker EXPECT_GT(add_compare(bigint(1) <<= 32, bigint(0), bigint(0xffffffff)), 0);
51*5c90c05cSAndroid Build Coastguard Worker EXPECT_GT(add_compare(bigint(0), bigint(1) <<= 32, bigint(0xffffffff)), 0);
52*5c90c05cSAndroid Build Coastguard Worker EXPECT_GT(add_compare(bigint(42), bigint(1), bigint(42)), 0);
53*5c90c05cSAndroid Build Coastguard Worker EXPECT_GT(add_compare(bigint(0xffffffff), bigint(1), bigint(0xffffffff)), 0);
54*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(add_compare(bigint(10), bigint(10), bigint(22)), 0);
55*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(add_compare(bigint(0x100000010), bigint(0x100000010),
56*5c90c05cSAndroid Build Coastguard Worker bigint(0x300000010)),
57*5c90c05cSAndroid Build Coastguard Worker 0);
58*5c90c05cSAndroid Build Coastguard Worker EXPECT_GT(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
59*5c90c05cSAndroid Build Coastguard Worker bigint(0x300000000)),
60*5c90c05cSAndroid Build Coastguard Worker 0);
61*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
62*5c90c05cSAndroid Build Coastguard Worker bigint(0x300000001)),
63*5c90c05cSAndroid Build Coastguard Worker 0);
64*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
65*5c90c05cSAndroid Build Coastguard Worker bigint(0x300000002)),
66*5c90c05cSAndroid Build Coastguard Worker 0);
67*5c90c05cSAndroid Build Coastguard Worker EXPECT_LT(add_compare(bigint(0x1ffffffff), bigint(0x100000002),
68*5c90c05cSAndroid Build Coastguard Worker bigint(0x300000003)),
69*5c90c05cSAndroid Build Coastguard Worker 0);
70*5c90c05cSAndroid Build Coastguard Worker }
71*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,shift_left)72*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, shift_left) {
73*5c90c05cSAndroid Build Coastguard Worker bigint n(0x42);
74*5c90c05cSAndroid Build Coastguard Worker n <<= 0;
75*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n), "42");
76*5c90c05cSAndroid Build Coastguard Worker n <<= 1;
77*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n), "84");
78*5c90c05cSAndroid Build Coastguard Worker n <<= 25;
79*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n), "108000000");
80*5c90c05cSAndroid Build Coastguard Worker }
81*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,multiply)82*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, multiply) {
83*5c90c05cSAndroid Build Coastguard Worker bigint n(0x42);
84*5c90c05cSAndroid Build Coastguard Worker EXPECT_THROW(n *= 0, assertion_failure);
85*5c90c05cSAndroid Build Coastguard Worker n *= 1;
86*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n), "42");
87*5c90c05cSAndroid Build Coastguard Worker
88*5c90c05cSAndroid Build Coastguard Worker n *= 2;
89*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n), "84");
90*5c90c05cSAndroid Build Coastguard Worker n *= 0x12345678;
91*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n), "962fc95e0");
92*5c90c05cSAndroid Build Coastguard Worker
93*5c90c05cSAndroid Build Coastguard Worker bigint bigmax(max_value<uint32_t>());
94*5c90c05cSAndroid Build Coastguard Worker bigmax *= max_value<uint32_t>();
95*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(bigmax), "fffffffe00000001");
96*5c90c05cSAndroid Build Coastguard Worker
97*5c90c05cSAndroid Build Coastguard Worker const auto max64 = max_value<uint64_t>();
98*5c90c05cSAndroid Build Coastguard Worker bigmax = max64;
99*5c90c05cSAndroid Build Coastguard Worker bigmax *= max64;
100*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(bigmax), "fffffffffffffffe0000000000000001");
101*5c90c05cSAndroid Build Coastguard Worker
102*5c90c05cSAndroid Build Coastguard Worker const auto max128 = (fmt::detail::uint128_t(max64) << 64) | max64;
103*5c90c05cSAndroid Build Coastguard Worker bigmax = max128;
104*5c90c05cSAndroid Build Coastguard Worker bigmax *= max128;
105*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(bigmax),
106*5c90c05cSAndroid Build Coastguard Worker "fffffffffffffffffffffffffffffffe00000000000000000000000000000001");
107*5c90c05cSAndroid Build Coastguard Worker }
108*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,square)109*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, square) {
110*5c90c05cSAndroid Build Coastguard Worker bigint n0(0);
111*5c90c05cSAndroid Build Coastguard Worker n0.square();
112*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n0), "0");
113*5c90c05cSAndroid Build Coastguard Worker bigint n1(0x100);
114*5c90c05cSAndroid Build Coastguard Worker n1.square();
115*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n1), "10000");
116*5c90c05cSAndroid Build Coastguard Worker bigint n2(0xfffffffff);
117*5c90c05cSAndroid Build Coastguard Worker n2.square();
118*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n2), "ffffffffe000000001");
119*5c90c05cSAndroid Build Coastguard Worker bigint n3(max_value<uint64_t>());
120*5c90c05cSAndroid Build Coastguard Worker n3.square();
121*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n3), "fffffffffffffffe0000000000000001");
122*5c90c05cSAndroid Build Coastguard Worker bigint n4;
123*5c90c05cSAndroid Build Coastguard Worker n4.assign_pow10(10);
124*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n4), "2540be400");
125*5c90c05cSAndroid Build Coastguard Worker }
126*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,divmod_assign_zero_divisor)127*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, divmod_assign_zero_divisor) {
128*5c90c05cSAndroid Build Coastguard Worker bigint zero(0);
129*5c90c05cSAndroid Build Coastguard Worker EXPECT_THROW(bigint(0).divmod_assign(zero), assertion_failure);
130*5c90c05cSAndroid Build Coastguard Worker EXPECT_THROW(bigint(42).divmod_assign(zero), assertion_failure);
131*5c90c05cSAndroid Build Coastguard Worker }
132*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,divmod_assign_self)133*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, divmod_assign_self) {
134*5c90c05cSAndroid Build Coastguard Worker bigint n(100);
135*5c90c05cSAndroid Build Coastguard Worker EXPECT_THROW(n.divmod_assign(n), assertion_failure);
136*5c90c05cSAndroid Build Coastguard Worker }
137*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,divmod_assign_unaligned)138*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, divmod_assign_unaligned) {
139*5c90c05cSAndroid Build Coastguard Worker // (42 << 340) / pow(10, 100):
140*5c90c05cSAndroid Build Coastguard Worker bigint n1(42);
141*5c90c05cSAndroid Build Coastguard Worker n1 <<= 340;
142*5c90c05cSAndroid Build Coastguard Worker bigint n2;
143*5c90c05cSAndroid Build Coastguard Worker n2.assign_pow10(100);
144*5c90c05cSAndroid Build Coastguard Worker int result = n1.divmod_assign(n2);
145*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(result, 9406);
146*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n1),
147*5c90c05cSAndroid Build Coastguard Worker "10f8353019583bfc29ffc8f564e1b9f9d819dbb4cf783e4507eca1539220p96");
148*5c90c05cSAndroid Build Coastguard Worker }
149*5c90c05cSAndroid Build Coastguard Worker
TEST(bigint_test,divmod_assign)150*5c90c05cSAndroid Build Coastguard Worker TEST(bigint_test, divmod_assign) {
151*5c90c05cSAndroid Build Coastguard Worker // 100 / 10:
152*5c90c05cSAndroid Build Coastguard Worker bigint n1(100);
153*5c90c05cSAndroid Build Coastguard Worker int result = n1.divmod_assign(bigint(10));
154*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(result, 10);
155*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n1), "0");
156*5c90c05cSAndroid Build Coastguard Worker // pow(10, 100) / (42 << 320):
157*5c90c05cSAndroid Build Coastguard Worker n1.assign_pow10(100);
158*5c90c05cSAndroid Build Coastguard Worker result = n1.divmod_assign(bigint(42) <<= 320);
159*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(result, 111);
160*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n1),
161*5c90c05cSAndroid Build Coastguard Worker "13ad2594c37ceb0b2784c4ce0bf38ace408e211a7caab24308a82e8f10p96");
162*5c90c05cSAndroid Build Coastguard Worker // 42 / 100:
163*5c90c05cSAndroid Build Coastguard Worker bigint n2(42);
164*5c90c05cSAndroid Build Coastguard Worker n1.assign_pow10(2);
165*5c90c05cSAndroid Build Coastguard Worker result = n2.divmod_assign(n1);
166*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(result, 0);
167*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::to_string(n2), "2a");
168*5c90c05cSAndroid Build Coastguard Worker }
169*5c90c05cSAndroid Build Coastguard Worker
run_double_tests()170*5c90c05cSAndroid Build Coastguard Worker template <bool is_iec559> void run_double_tests() {
171*5c90c05cSAndroid Build Coastguard Worker fmt::print("warning: double is not IEC559, skipping FP tests\n");
172*5c90c05cSAndroid Build Coastguard Worker }
173*5c90c05cSAndroid Build Coastguard Worker
run_double_tests()174*5c90c05cSAndroid Build Coastguard Worker template <> void run_double_tests<true>() {
175*5c90c05cSAndroid Build Coastguard Worker // Construct from double.
176*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fp(1.23), fp(0x13ae147ae147aeu, -52));
177*5c90c05cSAndroid Build Coastguard Worker }
178*5c90c05cSAndroid Build Coastguard Worker
TEST(fp_test,double_tests)179*5c90c05cSAndroid Build Coastguard Worker TEST(fp_test, double_tests) {
180*5c90c05cSAndroid Build Coastguard Worker run_double_tests<std::numeric_limits<double>::is_iec559>();
181*5c90c05cSAndroid Build Coastguard Worker }
182*5c90c05cSAndroid Build Coastguard Worker
TEST(fp_test,normalize)183*5c90c05cSAndroid Build Coastguard Worker TEST(fp_test, normalize) {
184*5c90c05cSAndroid Build Coastguard Worker const auto v = fp(0xbeef, 42);
185*5c90c05cSAndroid Build Coastguard Worker auto normalized = normalize(v);
186*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(normalized.f, 0xbeef000000000000);
187*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(normalized.e, -6);
188*5c90c05cSAndroid Build Coastguard Worker }
189*5c90c05cSAndroid Build Coastguard Worker
TEST(fp_test,multiply)190*5c90c05cSAndroid Build Coastguard Worker TEST(fp_test, multiply) {
191*5c90c05cSAndroid Build Coastguard Worker auto v = fp(123ULL << 32, 4) * fp(56ULL << 32, 7);
192*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(v.f, 123u * 56u);
193*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(v.e, 4 + 7 + 64);
194*5c90c05cSAndroid Build Coastguard Worker v = fp(123ULL << 32, 4) * fp(567ULL << 31, 8);
195*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(v.f, (123 * 567 + 1u) / 2);
196*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(v.e, 4 + 8 + 64);
197*5c90c05cSAndroid Build Coastguard Worker }
198*5c90c05cSAndroid Build Coastguard Worker
TEST(fp_test,dragonbox_max_k)199*5c90c05cSAndroid Build Coastguard Worker TEST(fp_test, dragonbox_max_k) {
200*5c90c05cSAndroid Build Coastguard Worker using fmt::detail::dragonbox::floor_log10_pow2;
201*5c90c05cSAndroid Build Coastguard Worker using float_info = fmt::detail::dragonbox::float_info<float>;
202*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(
203*5c90c05cSAndroid Build Coastguard Worker fmt::detail::const_check(float_info::max_k),
204*5c90c05cSAndroid Build Coastguard Worker float_info::kappa -
205*5c90c05cSAndroid Build Coastguard Worker floor_log10_pow2(std::numeric_limits<float>::min_exponent -
206*5c90c05cSAndroid Build Coastguard Worker fmt::detail::num_significand_bits<float>() - 1));
207*5c90c05cSAndroid Build Coastguard Worker using double_info = fmt::detail::dragonbox::float_info<double>;
208*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::detail::const_check(double_info::max_k),
209*5c90c05cSAndroid Build Coastguard Worker double_info::kappa -
210*5c90c05cSAndroid Build Coastguard Worker floor_log10_pow2(
211*5c90c05cSAndroid Build Coastguard Worker std::numeric_limits<double>::min_exponent -
212*5c90c05cSAndroid Build Coastguard Worker 2 * fmt::detail::num_significand_bits<double>() - 1));
213*5c90c05cSAndroid Build Coastguard Worker }
214*5c90c05cSAndroid Build Coastguard Worker
TEST(format_impl_test,format_error_code)215*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, format_error_code) {
216*5c90c05cSAndroid Build Coastguard Worker std::string msg = "error 42", sep = ": ";
217*5c90c05cSAndroid Build Coastguard Worker {
218*5c90c05cSAndroid Build Coastguard Worker auto buffer = fmt::memory_buffer();
219*5c90c05cSAndroid Build Coastguard Worker fmt::format_to(fmt::appender(buffer), "garbage");
220*5c90c05cSAndroid Build Coastguard Worker fmt::detail::format_error_code(buffer, 42, "test");
221*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(to_string(buffer), "test: " + msg);
222*5c90c05cSAndroid Build Coastguard Worker }
223*5c90c05cSAndroid Build Coastguard Worker {
224*5c90c05cSAndroid Build Coastguard Worker auto buffer = fmt::memory_buffer();
225*5c90c05cSAndroid Build Coastguard Worker auto prefix =
226*5c90c05cSAndroid Build Coastguard Worker std::string(fmt::inline_buffer_size - msg.size() - sep.size() + 1, 'x');
227*5c90c05cSAndroid Build Coastguard Worker fmt::detail::format_error_code(buffer, 42, prefix);
228*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(msg, to_string(buffer));
229*5c90c05cSAndroid Build Coastguard Worker }
230*5c90c05cSAndroid Build Coastguard Worker int codes[] = {42, -1};
231*5c90c05cSAndroid Build Coastguard Worker for (size_t i = 0, n = sizeof(codes) / sizeof(*codes); i < n; ++i) {
232*5c90c05cSAndroid Build Coastguard Worker // Test maximum buffer size.
233*5c90c05cSAndroid Build Coastguard Worker msg = fmt::format("error {}", codes[i]);
234*5c90c05cSAndroid Build Coastguard Worker fmt::memory_buffer buffer;
235*5c90c05cSAndroid Build Coastguard Worker auto prefix =
236*5c90c05cSAndroid Build Coastguard Worker std::string(fmt::inline_buffer_size - msg.size() - sep.size(), 'x');
237*5c90c05cSAndroid Build Coastguard Worker fmt::detail::format_error_code(buffer, codes[i], prefix);
238*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(prefix + sep + msg, to_string(buffer));
239*5c90c05cSAndroid Build Coastguard Worker size_t size = fmt::inline_buffer_size;
240*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(size, buffer.size());
241*5c90c05cSAndroid Build Coastguard Worker buffer.resize(0);
242*5c90c05cSAndroid Build Coastguard Worker // Test with a message that doesn't fit into the buffer.
243*5c90c05cSAndroid Build Coastguard Worker prefix += 'x';
244*5c90c05cSAndroid Build Coastguard Worker fmt::detail::format_error_code(buffer, codes[i], prefix);
245*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(to_string(buffer), msg);
246*5c90c05cSAndroid Build Coastguard Worker }
247*5c90c05cSAndroid Build Coastguard Worker }
248*5c90c05cSAndroid Build Coastguard Worker
249*5c90c05cSAndroid Build Coastguard Worker // Tests fmt::detail::count_digits for integer type Int.
test_count_digits()250*5c90c05cSAndroid Build Coastguard Worker template <typename Int> void test_count_digits() {
251*5c90c05cSAndroid Build Coastguard Worker for (Int i = 0; i < 10; ++i) EXPECT_EQ(1u, fmt::detail::count_digits(i));
252*5c90c05cSAndroid Build Coastguard Worker for (Int i = 1, n = 1, end = max_value<Int>() / 10; n <= end; ++i) {
253*5c90c05cSAndroid Build Coastguard Worker n *= 10;
254*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::detail::count_digits(n - 1), i);
255*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::detail::count_digits(n), i + 1);
256*5c90c05cSAndroid Build Coastguard Worker }
257*5c90c05cSAndroid Build Coastguard Worker }
258*5c90c05cSAndroid Build Coastguard Worker
TEST(format_impl_test,count_digits)259*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, count_digits) {
260*5c90c05cSAndroid Build Coastguard Worker test_count_digits<uint32_t>();
261*5c90c05cSAndroid Build Coastguard Worker test_count_digits<uint64_t>();
262*5c90c05cSAndroid Build Coastguard Worker }
263*5c90c05cSAndroid Build Coastguard Worker
TEST(format_impl_test,countl_zero)264*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, countl_zero) {
265*5c90c05cSAndroid Build Coastguard Worker constexpr auto num_bits = fmt::detail::num_bits<uint32_t>();
266*5c90c05cSAndroid Build Coastguard Worker uint32_t n = 1u;
267*5c90c05cSAndroid Build Coastguard Worker for (int i = 1; i < num_bits - 1; i++) {
268*5c90c05cSAndroid Build Coastguard Worker n <<= 1;
269*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::detail::countl_zero(n - 1), num_bits - i);
270*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(fmt::detail::countl_zero(n), num_bits - i - 1);
271*5c90c05cSAndroid Build Coastguard Worker }
272*5c90c05cSAndroid Build Coastguard Worker }
273*5c90c05cSAndroid Build Coastguard Worker
274*5c90c05cSAndroid Build Coastguard Worker #if FMT_USE_FLOAT128
TEST(format_impl_test,write_float128)275*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, write_float128) {
276*5c90c05cSAndroid Build Coastguard Worker auto s = std::string();
277*5c90c05cSAndroid Build Coastguard Worker fmt::detail::write<char>(std::back_inserter(s), __float128(42));
278*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(s, "42");
279*5c90c05cSAndroid Build Coastguard Worker }
280*5c90c05cSAndroid Build Coastguard Worker #endif
281*5c90c05cSAndroid Build Coastguard Worker
282*5c90c05cSAndroid Build Coastguard Worker struct double_double {
283*5c90c05cSAndroid Build Coastguard Worker double a;
284*5c90c05cSAndroid Build Coastguard Worker double b;
285*5c90c05cSAndroid Build Coastguard Worker
double_doubledouble_double286*5c90c05cSAndroid Build Coastguard Worker explicit constexpr double_double(double a_val = 0, double b_val = 0)
287*5c90c05cSAndroid Build Coastguard Worker : a(a_val), b(b_val) {}
288*5c90c05cSAndroid Build Coastguard Worker
operator doubledouble_double289*5c90c05cSAndroid Build Coastguard Worker operator double() const { return a + b; }
operator -double_double290*5c90c05cSAndroid Build Coastguard Worker auto operator-() const -> double_double { return double_double(-a, -b); }
291*5c90c05cSAndroid Build Coastguard Worker };
292*5c90c05cSAndroid Build Coastguard Worker
format_as(double_double d)293*5c90c05cSAndroid Build Coastguard Worker auto format_as(double_double d) -> double { return d; }
294*5c90c05cSAndroid Build Coastguard Worker
operator >=(const double_double & lhs,const double_double & rhs)295*5c90c05cSAndroid Build Coastguard Worker bool operator>=(const double_double& lhs, const double_double& rhs) {
296*5c90c05cSAndroid Build Coastguard Worker return lhs.a + lhs.b >= rhs.a + rhs.b;
297*5c90c05cSAndroid Build Coastguard Worker }
298*5c90c05cSAndroid Build Coastguard Worker
299*5c90c05cSAndroid Build Coastguard Worker struct slow_float {
300*5c90c05cSAndroid Build Coastguard Worker float value;
301*5c90c05cSAndroid Build Coastguard Worker
slow_floatslow_float302*5c90c05cSAndroid Build Coastguard Worker explicit constexpr slow_float(float val = 0) : value(val) {}
operator floatslow_float303*5c90c05cSAndroid Build Coastguard Worker operator float() const { return value; }
operator -slow_float304*5c90c05cSAndroid Build Coastguard Worker auto operator-() const -> slow_float { return slow_float(-value); }
305*5c90c05cSAndroid Build Coastguard Worker };
306*5c90c05cSAndroid Build Coastguard Worker
format_as(slow_float f)307*5c90c05cSAndroid Build Coastguard Worker auto format_as(slow_float f) -> float { return f; }
308*5c90c05cSAndroid Build Coastguard Worker
309*5c90c05cSAndroid Build Coastguard Worker namespace std {
310*5c90c05cSAndroid Build Coastguard Worker template <> struct is_floating_point<double_double> : std::true_type {};
311*5c90c05cSAndroid Build Coastguard Worker template <> struct numeric_limits<double_double> {
312*5c90c05cSAndroid Build Coastguard Worker // is_iec559 is true for double-double in libstdc++.
313*5c90c05cSAndroid Build Coastguard Worker static constexpr bool is_iec559 = true;
314*5c90c05cSAndroid Build Coastguard Worker static constexpr int digits = 106;
315*5c90c05cSAndroid Build Coastguard Worker };
316*5c90c05cSAndroid Build Coastguard Worker
317*5c90c05cSAndroid Build Coastguard Worker template <> struct is_floating_point<slow_float> : std::true_type {};
318*5c90c05cSAndroid Build Coastguard Worker template <> struct numeric_limits<slow_float> : numeric_limits<float> {};
319*5c90c05cSAndroid Build Coastguard Worker } // namespace std
320*5c90c05cSAndroid Build Coastguard Worker
321*5c90c05cSAndroid Build Coastguard Worker FMT_BEGIN_NAMESPACE
322*5c90c05cSAndroid Build Coastguard Worker namespace detail {
323*5c90c05cSAndroid Build Coastguard Worker template <> struct is_fast_float<slow_float> : std::false_type {};
324*5c90c05cSAndroid Build Coastguard Worker namespace dragonbox {
325*5c90c05cSAndroid Build Coastguard Worker template <> struct float_info<slow_float> {
326*5c90c05cSAndroid Build Coastguard Worker using carrier_uint = uint32_t;
327*5c90c05cSAndroid Build Coastguard Worker static const int exponent_bits = 8;
328*5c90c05cSAndroid Build Coastguard Worker };
329*5c90c05cSAndroid Build Coastguard Worker } // namespace dragonbox
330*5c90c05cSAndroid Build Coastguard Worker } // namespace detail
331*5c90c05cSAndroid Build Coastguard Worker FMT_END_NAMESPACE
332*5c90c05cSAndroid Build Coastguard Worker
TEST(format_impl_test,write_double_double)333*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, write_double_double) {
334*5c90c05cSAndroid Build Coastguard Worker auto s = std::string();
335*5c90c05cSAndroid Build Coastguard Worker fmt::detail::write<char>(std::back_inserter(s), double_double(42), {});
336*5c90c05cSAndroid Build Coastguard Worker // Specializing is_floating_point is broken in MSVC.
337*5c90c05cSAndroid Build Coastguard Worker if (!FMT_MSC_VERSION) EXPECT_EQ(s, "42");
338*5c90c05cSAndroid Build Coastguard Worker }
339*5c90c05cSAndroid Build Coastguard Worker
TEST(format_impl_test,write_dragon_even)340*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, write_dragon_even) {
341*5c90c05cSAndroid Build Coastguard Worker auto s = std::string();
342*5c90c05cSAndroid Build Coastguard Worker fmt::detail::write<char>(std::back_inserter(s), slow_float(33554450.0f), {});
343*5c90c05cSAndroid Build Coastguard Worker // Specializing is_floating_point is broken in MSVC.
344*5c90c05cSAndroid Build Coastguard Worker if (!FMT_MSC_VERSION) EXPECT_EQ(s, "33554450");
345*5c90c05cSAndroid Build Coastguard Worker }
346*5c90c05cSAndroid Build Coastguard Worker
347*5c90c05cSAndroid Build Coastguard Worker #if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE)
348*5c90c05cSAndroid Build Coastguard Worker # include <windows.h>
349*5c90c05cSAndroid Build Coastguard Worker
TEST(format_impl_test,write_console_signature)350*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, write_console_signature) {
351*5c90c05cSAndroid Build Coastguard Worker decltype(::WriteConsoleW)* p = fmt::detail::WriteConsoleW;
352*5c90c05cSAndroid Build Coastguard Worker (void)p;
353*5c90c05cSAndroid Build Coastguard Worker }
354*5c90c05cSAndroid Build Coastguard Worker #endif
355*5c90c05cSAndroid Build Coastguard Worker
356*5c90c05cSAndroid Build Coastguard Worker // A public domain branchless UTF-8 decoder by Christopher Wellons:
357*5c90c05cSAndroid Build Coastguard Worker // https://github.com/skeeto/branchless-utf8
unicode_is_surrogate(uint32_t c)358*5c90c05cSAndroid Build Coastguard Worker constexpr bool unicode_is_surrogate(uint32_t c) {
359*5c90c05cSAndroid Build Coastguard Worker return c >= 0xD800U && c <= 0xDFFFU;
360*5c90c05cSAndroid Build Coastguard Worker }
361*5c90c05cSAndroid Build Coastguard Worker
utf8_encode(char * s,uint32_t c)362*5c90c05cSAndroid Build Coastguard Worker FMT_CONSTEXPR char* utf8_encode(char* s, uint32_t c) {
363*5c90c05cSAndroid Build Coastguard Worker if (c >= (1UL << 16)) {
364*5c90c05cSAndroid Build Coastguard Worker s[0] = static_cast<char>(0xf0 | (c >> 18));
365*5c90c05cSAndroid Build Coastguard Worker s[1] = static_cast<char>(0x80 | ((c >> 12) & 0x3f));
366*5c90c05cSAndroid Build Coastguard Worker s[2] = static_cast<char>(0x80 | ((c >> 6) & 0x3f));
367*5c90c05cSAndroid Build Coastguard Worker s[3] = static_cast<char>(0x80 | ((c >> 0) & 0x3f));
368*5c90c05cSAndroid Build Coastguard Worker return s + 4;
369*5c90c05cSAndroid Build Coastguard Worker } else if (c >= (1UL << 11)) {
370*5c90c05cSAndroid Build Coastguard Worker s[0] = static_cast<char>(0xe0 | (c >> 12));
371*5c90c05cSAndroid Build Coastguard Worker s[1] = static_cast<char>(0x80 | ((c >> 6) & 0x3f));
372*5c90c05cSAndroid Build Coastguard Worker s[2] = static_cast<char>(0x80 | ((c >> 0) & 0x3f));
373*5c90c05cSAndroid Build Coastguard Worker return s + 3;
374*5c90c05cSAndroid Build Coastguard Worker } else if (c >= (1UL << 7)) {
375*5c90c05cSAndroid Build Coastguard Worker s[0] = static_cast<char>(0xc0 | (c >> 6));
376*5c90c05cSAndroid Build Coastguard Worker s[1] = static_cast<char>(0x80 | ((c >> 0) & 0x3f));
377*5c90c05cSAndroid Build Coastguard Worker return s + 2;
378*5c90c05cSAndroid Build Coastguard Worker } else {
379*5c90c05cSAndroid Build Coastguard Worker s[0] = static_cast<char>(c);
380*5c90c05cSAndroid Build Coastguard Worker return s + 1;
381*5c90c05cSAndroid Build Coastguard Worker }
382*5c90c05cSAndroid Build Coastguard Worker }
383*5c90c05cSAndroid Build Coastguard Worker
384*5c90c05cSAndroid Build Coastguard Worker // Make sure it can decode every character
TEST(format_impl_test,utf8_decode_decode_all)385*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, utf8_decode_decode_all) {
386*5c90c05cSAndroid Build Coastguard Worker for (uint32_t i = 0; i < 0x10ffff; i++) {
387*5c90c05cSAndroid Build Coastguard Worker if (!unicode_is_surrogate(i)) {
388*5c90c05cSAndroid Build Coastguard Worker int e;
389*5c90c05cSAndroid Build Coastguard Worker uint32_t c;
390*5c90c05cSAndroid Build Coastguard Worker char buf[8] = {0};
391*5c90c05cSAndroid Build Coastguard Worker char* end = utf8_encode(buf, i);
392*5c90c05cSAndroid Build Coastguard Worker const char* res = fmt::detail::utf8_decode(buf, &c, &e);
393*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(end, res);
394*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(c, i);
395*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(e, 0);
396*5c90c05cSAndroid Build Coastguard Worker }
397*5c90c05cSAndroid Build Coastguard Worker }
398*5c90c05cSAndroid Build Coastguard Worker }
399*5c90c05cSAndroid Build Coastguard Worker
400*5c90c05cSAndroid Build Coastguard Worker // Reject everything outside of U+0000..U+10FFFF
TEST(format_impl_test,utf8_decode_out_of_range)401*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, utf8_decode_out_of_range) {
402*5c90c05cSAndroid Build Coastguard Worker for (uint32_t i = 0x110000; i < 0x1fffff; i++) {
403*5c90c05cSAndroid Build Coastguard Worker int e;
404*5c90c05cSAndroid Build Coastguard Worker uint32_t c;
405*5c90c05cSAndroid Build Coastguard Worker char buf[8] = {0};
406*5c90c05cSAndroid Build Coastguard Worker utf8_encode(buf, i);
407*5c90c05cSAndroid Build Coastguard Worker const char* end = fmt::detail::utf8_decode(buf, &c, &e);
408*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0);
409*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(end - buf, 4);
410*5c90c05cSAndroid Build Coastguard Worker }
411*5c90c05cSAndroid Build Coastguard Worker }
412*5c90c05cSAndroid Build Coastguard Worker
413*5c90c05cSAndroid Build Coastguard Worker // Does it reject all surrogate halves?
TEST(format_impl_test,utf8_decode_surrogate_halves)414*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, utf8_decode_surrogate_halves) {
415*5c90c05cSAndroid Build Coastguard Worker for (uint32_t i = 0xd800; i <= 0xdfff; i++) {
416*5c90c05cSAndroid Build Coastguard Worker int e;
417*5c90c05cSAndroid Build Coastguard Worker uint32_t c;
418*5c90c05cSAndroid Build Coastguard Worker char buf[8] = {0};
419*5c90c05cSAndroid Build Coastguard Worker utf8_encode(buf, i);
420*5c90c05cSAndroid Build Coastguard Worker fmt::detail::utf8_decode(buf, &c, &e);
421*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0);
422*5c90c05cSAndroid Build Coastguard Worker }
423*5c90c05cSAndroid Build Coastguard Worker }
424*5c90c05cSAndroid Build Coastguard Worker
425*5c90c05cSAndroid Build Coastguard Worker // How about non-canonical encodings?
TEST(format_impl_test,utf8_decode_non_canonical_encodings)426*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, utf8_decode_non_canonical_encodings) {
427*5c90c05cSAndroid Build Coastguard Worker int e;
428*5c90c05cSAndroid Build Coastguard Worker uint32_t c;
429*5c90c05cSAndroid Build Coastguard Worker const char* end;
430*5c90c05cSAndroid Build Coastguard Worker
431*5c90c05cSAndroid Build Coastguard Worker char buf2[8] = {char(0xc0), char(0xA4)};
432*5c90c05cSAndroid Build Coastguard Worker end = fmt::detail::utf8_decode(buf2, &c, &e);
433*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0); // non-canonical len 2
434*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(end, buf2 + 2); // non-canonical recover 2
435*5c90c05cSAndroid Build Coastguard Worker
436*5c90c05cSAndroid Build Coastguard Worker char buf3[8] = {char(0xe0), char(0x80), char(0xA4)};
437*5c90c05cSAndroid Build Coastguard Worker end = fmt::detail::utf8_decode(buf3, &c, &e);
438*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0); // non-canonical len 3
439*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(end, buf3 + 3); // non-canonical recover 3
440*5c90c05cSAndroid Build Coastguard Worker
441*5c90c05cSAndroid Build Coastguard Worker char buf4[8] = {char(0xf0), char(0x80), char(0x80), char(0xA4)};
442*5c90c05cSAndroid Build Coastguard Worker end = fmt::detail::utf8_decode(buf4, &c, &e);
443*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0); // non-canonical encoding len 4
444*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(end, buf4 + 4); // non-canonical recover 4
445*5c90c05cSAndroid Build Coastguard Worker }
446*5c90c05cSAndroid Build Coastguard Worker
447*5c90c05cSAndroid Build Coastguard Worker // Let's try some bogus byte sequences
TEST(format_impl_test,utf8_decode_bogus_byte_sequences)448*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, utf8_decode_bogus_byte_sequences) {
449*5c90c05cSAndroid Build Coastguard Worker int e;
450*5c90c05cSAndroid Build Coastguard Worker uint32_t c;
451*5c90c05cSAndroid Build Coastguard Worker
452*5c90c05cSAndroid Build Coastguard Worker // Invalid first byte
453*5c90c05cSAndroid Build Coastguard Worker char buf0[4] = {char(0xff)};
454*5c90c05cSAndroid Build Coastguard Worker auto len = fmt::detail::utf8_decode(buf0, &c, &e) - buf0;
455*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0); // "bogus [ff] 0x%02x U+%04lx", e, (unsigned long)c);
456*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(len, 1); // "bogus [ff] recovery %d", len);
457*5c90c05cSAndroid Build Coastguard Worker
458*5c90c05cSAndroid Build Coastguard Worker // Invalid first byte
459*5c90c05cSAndroid Build Coastguard Worker char buf1[4] = {char(0x80)};
460*5c90c05cSAndroid Build Coastguard Worker len = fmt::detail::utf8_decode(buf1, &c, &e) - buf1;
461*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0); // "bogus [80] 0x%02x U+%04lx", e, (unsigned long)c);
462*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(len, 1); // "bogus [80] recovery %d", len);
463*5c90c05cSAndroid Build Coastguard Worker
464*5c90c05cSAndroid Build Coastguard Worker // Looks like a two-byte sequence but second byte is wrong
465*5c90c05cSAndroid Build Coastguard Worker char buf2[4] = {char(0xc0), char(0x0a)};
466*5c90c05cSAndroid Build Coastguard Worker len = fmt::detail::utf8_decode(buf2, &c, &e) - buf2;
467*5c90c05cSAndroid Build Coastguard Worker EXPECT_NE(e, 0); // "bogus [c0 0a] 0x%02x U+%04lx", e, (unsigned long)c
468*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(len, 2); // "bogus [c0 0a] recovery %d", len);
469*5c90c05cSAndroid Build Coastguard Worker }
470*5c90c05cSAndroid Build Coastguard Worker
TEST(format_impl_test,to_utf8)471*5c90c05cSAndroid Build Coastguard Worker TEST(format_impl_test, to_utf8) {
472*5c90c05cSAndroid Build Coastguard Worker auto s = std::string("ёжик");
473*5c90c05cSAndroid Build Coastguard Worker auto u = fmt::detail::to_utf8<wchar_t>(L"\x0451\x0436\x0438\x043A");
474*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(s, u.str());
475*5c90c05cSAndroid Build Coastguard Worker EXPECT_EQ(s.size(), u.size());
476*5c90c05cSAndroid Build Coastguard Worker }
477