1 | //===-- Unittests for IntegerToString -------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/__support/CPP/limits.h" |
10 | #include "src/__support/CPP/span.h" |
11 | #include "src/__support/CPP/string_view.h" |
12 | #include "src/__support/big_int.h" |
13 | #include "src/__support/integer_literals.h" |
14 | #include "src/__support/integer_to_string.h" |
15 | #include "src/__support/uint128.h" |
16 | |
17 | #include "test/UnitTest/Test.h" |
18 | |
19 | using LIBC_NAMESPACE::BigInt; |
20 | using LIBC_NAMESPACE::IntegerToString; |
21 | using LIBC_NAMESPACE::cpp::span; |
22 | using LIBC_NAMESPACE::cpp::string_view; |
23 | using LIBC_NAMESPACE::radix::Bin; |
24 | using LIBC_NAMESPACE::radix::Custom; |
25 | using LIBC_NAMESPACE::radix::Dec; |
26 | using LIBC_NAMESPACE::radix::Hex; |
27 | using LIBC_NAMESPACE::radix::Oct; |
28 | using LIBC_NAMESPACE::operator""_u128 ; |
29 | using LIBC_NAMESPACE::operator""_u256 ; |
30 | |
31 | #define EXPECT(type, value, string_value) \ |
32 | { \ |
33 | const type buffer(value); \ |
34 | EXPECT_EQ(buffer.view(), string_view(string_value)); \ |
35 | } |
36 | |
37 | TEST(LlvmLibcIntegerToStringTest, UINT8) { |
38 | using type = IntegerToString<uint8_t>; |
39 | EXPECT(type, 0, "0" ); |
40 | EXPECT(type, 1, "1" ); |
41 | EXPECT(type, 12, "12" ); |
42 | EXPECT(type, 123, "123" ); |
43 | EXPECT(type, UINT8_MAX, "255" ); |
44 | EXPECT(type, static_cast<uint8_t>(-1), "255" ); |
45 | } |
46 | |
47 | TEST(LlvmLibcIntegerToStringTest, INT8) { |
48 | using type = IntegerToString<int8_t>; |
49 | EXPECT(type, 0, "0" ); |
50 | EXPECT(type, 1, "1" ); |
51 | EXPECT(type, 12, "12" ); |
52 | EXPECT(type, 123, "123" ); |
53 | EXPECT(type, -12, "-12" ); |
54 | EXPECT(type, -123, "-123" ); |
55 | EXPECT(type, INT8_MAX, "127" ); |
56 | EXPECT(type, INT8_MIN, "-128" ); |
57 | } |
58 | |
59 | TEST(LlvmLibcIntegerToStringTest, UINT16) { |
60 | using type = IntegerToString<uint16_t>; |
61 | EXPECT(type, 0, "0" ); |
62 | EXPECT(type, 1, "1" ); |
63 | EXPECT(type, 12, "12" ); |
64 | EXPECT(type, 123, "123" ); |
65 | EXPECT(type, 1234, "1234" ); |
66 | EXPECT(type, 12345, "12345" ); |
67 | EXPECT(type, UINT16_MAX, "65535" ); |
68 | EXPECT(type, static_cast<uint16_t>(-1), "65535" ); |
69 | } |
70 | |
71 | TEST(LlvmLibcIntegerToStringTest, INT16) { |
72 | using type = IntegerToString<int16_t>; |
73 | EXPECT(type, 0, "0" ); |
74 | EXPECT(type, 1, "1" ); |
75 | EXPECT(type, 12, "12" ); |
76 | EXPECT(type, 123, "123" ); |
77 | EXPECT(type, 1234, "1234" ); |
78 | EXPECT(type, 12345, "12345" ); |
79 | EXPECT(type, -1, "-1" ); |
80 | EXPECT(type, -12, "-12" ); |
81 | EXPECT(type, -123, "-123" ); |
82 | EXPECT(type, -1234, "-1234" ); |
83 | EXPECT(type, -12345, "-12345" ); |
84 | EXPECT(type, INT16_MAX, "32767" ); |
85 | EXPECT(type, INT16_MIN, "-32768" ); |
86 | } |
87 | |
88 | TEST(LlvmLibcIntegerToStringTest, UINT32) { |
89 | using type = IntegerToString<uint32_t>; |
90 | EXPECT(type, 0, "0" ); |
91 | EXPECT(type, 1, "1" ); |
92 | EXPECT(type, 12, "12" ); |
93 | EXPECT(type, 123, "123" ); |
94 | EXPECT(type, 1234, "1234" ); |
95 | EXPECT(type, 12345, "12345" ); |
96 | EXPECT(type, 123456, "123456" ); |
97 | EXPECT(type, 1234567, "1234567" ); |
98 | EXPECT(type, 12345678, "12345678" ); |
99 | EXPECT(type, 123456789, "123456789" ); |
100 | EXPECT(type, 1234567890, "1234567890" ); |
101 | EXPECT(type, UINT32_MAX, "4294967295" ); |
102 | EXPECT(type, static_cast<uint32_t>(-1), "4294967295" ); |
103 | } |
104 | |
105 | TEST(LlvmLibcIntegerToStringTest, INT32) { |
106 | using type = IntegerToString<int32_t>; |
107 | EXPECT(type, 0, "0" ); |
108 | EXPECT(type, 1, "1" ); |
109 | EXPECT(type, 12, "12" ); |
110 | EXPECT(type, 123, "123" ); |
111 | EXPECT(type, 1234, "1234" ); |
112 | EXPECT(type, 12345, "12345" ); |
113 | EXPECT(type, 123456, "123456" ); |
114 | EXPECT(type, 1234567, "1234567" ); |
115 | EXPECT(type, 12345678, "12345678" ); |
116 | EXPECT(type, 123456789, "123456789" ); |
117 | EXPECT(type, 1234567890, "1234567890" ); |
118 | EXPECT(type, -1, "-1" ); |
119 | EXPECT(type, -12, "-12" ); |
120 | EXPECT(type, -123, "-123" ); |
121 | EXPECT(type, -1234, "-1234" ); |
122 | EXPECT(type, -12345, "-12345" ); |
123 | EXPECT(type, -123456, "-123456" ); |
124 | EXPECT(type, -1234567, "-1234567" ); |
125 | EXPECT(type, -12345678, "-12345678" ); |
126 | EXPECT(type, -123456789, "-123456789" ); |
127 | EXPECT(type, -1234567890, "-1234567890" ); |
128 | EXPECT(type, INT32_MAX, "2147483647" ); |
129 | EXPECT(type, INT32_MIN, "-2147483648" ); |
130 | } |
131 | |
132 | TEST(LlvmLibcIntegerToStringTest, UINT64) { |
133 | using type = IntegerToString<uint64_t>; |
134 | EXPECT(type, 0, "0" ); |
135 | EXPECT(type, 1, "1" ); |
136 | EXPECT(type, 12, "12" ); |
137 | EXPECT(type, 123, "123" ); |
138 | EXPECT(type, 1234, "1234" ); |
139 | EXPECT(type, 12345, "12345" ); |
140 | EXPECT(type, 123456, "123456" ); |
141 | EXPECT(type, 1234567, "1234567" ); |
142 | EXPECT(type, 12345678, "12345678" ); |
143 | EXPECT(type, 123456789, "123456789" ); |
144 | EXPECT(type, 1234567890, "1234567890" ); |
145 | EXPECT(type, 1234567890123456789, "1234567890123456789" ); |
146 | EXPECT(type, UINT64_MAX, "18446744073709551615" ); |
147 | EXPECT(type, static_cast<uint64_t>(-1), "18446744073709551615" ); |
148 | } |
149 | |
150 | TEST(LlvmLibcIntegerToStringTest, INT64) { |
151 | using type = IntegerToString<int64_t>; |
152 | EXPECT(type, 0, "0" ); |
153 | EXPECT(type, 1, "1" ); |
154 | EXPECT(type, 12, "12" ); |
155 | EXPECT(type, 123, "123" ); |
156 | EXPECT(type, 1234, "1234" ); |
157 | EXPECT(type, 12345, "12345" ); |
158 | EXPECT(type, 123456, "123456" ); |
159 | EXPECT(type, 1234567, "1234567" ); |
160 | EXPECT(type, 12345678, "12345678" ); |
161 | EXPECT(type, 123456789, "123456789" ); |
162 | EXPECT(type, 1234567890, "1234567890" ); |
163 | EXPECT(type, 1234567890123456789, "1234567890123456789" ); |
164 | EXPECT(type, -1, "-1" ); |
165 | EXPECT(type, -12, "-12" ); |
166 | EXPECT(type, -123, "-123" ); |
167 | EXPECT(type, -1234, "-1234" ); |
168 | EXPECT(type, -12345, "-12345" ); |
169 | EXPECT(type, -123456, "-123456" ); |
170 | EXPECT(type, -1234567, "-1234567" ); |
171 | EXPECT(type, -12345678, "-12345678" ); |
172 | EXPECT(type, -123456789, "-123456789" ); |
173 | EXPECT(type, -1234567890, "-1234567890" ); |
174 | EXPECT(type, -1234567890123456789, "-1234567890123456789" ); |
175 | EXPECT(type, INT64_MAX, "9223372036854775807" ); |
176 | EXPECT(type, INT64_MIN, "-9223372036854775808" ); |
177 | } |
178 | |
179 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_8) { |
180 | using type = IntegerToString<int64_t, Oct>; |
181 | EXPECT(type, 0, "0" ); |
182 | EXPECT(type, 012345, "12345" ); |
183 | EXPECT(type, 0123456701234567012345, "123456701234567012345" ); |
184 | EXPECT(type, static_cast<int64_t>(01777777777777777777777), |
185 | "1777777777777777777777" ); |
186 | } |
187 | |
188 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_16) { |
189 | using type = IntegerToString<uint64_t, Hex>; |
190 | EXPECT(type, 0, "0" ); |
191 | EXPECT(type, 0x12345, "12345" ); |
192 | EXPECT(type, 0x123456789abcdef, "123456789abcdef" ); |
193 | EXPECT(type, 0xffffffffffffffff, "ffffffffffffffff" ); |
194 | using TYPE = IntegerToString<uint64_t, Hex::Uppercase>; |
195 | EXPECT(TYPE, 0x123456789abcdef, "123456789ABCDEF" ); |
196 | } |
197 | |
198 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_2) { |
199 | using type = IntegerToString<uint64_t, Bin>; |
200 | EXPECT(type, 0, "0" ); |
201 | EXPECT(type, 0b111100001100, "111100001100" ); |
202 | EXPECT(type, 0b100100011101010111100, "100100011101010111100" ); |
203 | EXPECT(type, 0xffffffffffffffff, |
204 | "1111111111111111111111111111111111111111111111111111111111111111" ); |
205 | } |
206 | |
207 | TEST(LlvmLibcIntegerToStringTest, UINT128_Base_16) { |
208 | using type = IntegerToString<UInt128, Hex::WithWidth<32>>; |
209 | EXPECT(type, 0, "00000000000000000000000000000000" ); |
210 | EXPECT(type, 0x12345, "00000000000000000000000000012345" ); |
211 | EXPECT(type, 0x12340000'00000000'00000000'00000000_u128, |
212 | "12340000000000000000000000000000" ); |
213 | EXPECT(type, 0x00000000'00000000'12340000'00000000_u128, |
214 | "00000000000000001234000000000000" ); |
215 | EXPECT(type, 0x00000000'00000001'23400000'00000000_u128, |
216 | "00000000000000012340000000000000" ); |
217 | } |
218 | |
219 | TEST(LlvmLibcIntegerToStringTest, UINT64_Base_36) { |
220 | using type = IntegerToString<uint64_t, Custom<36>>; |
221 | EXPECT(type, 0, "0" ); |
222 | EXPECT(type, 12345, "9ix" ); |
223 | EXPECT(type, 1047601316295595, "abcdefghij" ); |
224 | EXPECT(type, 2092218013456445, "klmnopqrst" ); |
225 | EXPECT(type, 0xffffffffffffffff, "3w5e11264sgsf" ); |
226 | |
227 | using TYPE = IntegerToString<uint64_t, Custom<36>::Uppercase>; |
228 | EXPECT(TYPE, 1867590395, "UVWXYZ" ); |
229 | } |
230 | |
231 | TEST(LlvmLibcIntegerToStringTest, UINT256_Base_16) { |
232 | using UInt256 = LIBC_NAMESPACE::UInt<256>; |
233 | using type = IntegerToString<UInt256, Hex::WithWidth<64>>; |
234 | EXPECT( |
235 | type, |
236 | 0x0000000000000000000000000000000000000000000000000000000000000000_u256, |
237 | "0000000000000000000000000000000000000000000000000000000000000000" ); |
238 | EXPECT( |
239 | type, |
240 | 0x0000000000000000000000000000000000000000000000000000000000012345_u256, |
241 | "0000000000000000000000000000000000000000000000000000000000012345" ); |
242 | EXPECT( |
243 | type, |
244 | 0x0000000000000000000000000000000012340000000000000000000000000000_u256, |
245 | "0000000000000000000000000000000012340000000000000000000000000000" ); |
246 | EXPECT( |
247 | type, |
248 | 0x0000000000000000000000000000000123400000000000000000000000000000_u256, |
249 | "0000000000000000000000000000000123400000000000000000000000000000" ); |
250 | EXPECT( |
251 | type, |
252 | 0x1234000000000000000000000000000000000000000000000000000000000000_u256, |
253 | "1234000000000000000000000000000000000000000000000000000000000000" ); |
254 | } |
255 | |
256 | TEST(LlvmLibcIntegerToStringTest, NegativeInterpretedAsPositive) { |
257 | using BIN = IntegerToString<int8_t, Bin>; |
258 | using OCT = IntegerToString<int8_t, Oct>; |
259 | using DEC = IntegerToString<int8_t, Dec>; |
260 | using HEX = IntegerToString<int8_t, Hex>; |
261 | EXPECT(BIN, -1, "11111111" ); |
262 | EXPECT(OCT, -1, "377" ); |
263 | EXPECT(DEC, -1, "-1" ); // Only DEC format negative values |
264 | EXPECT(HEX, -1, "ff" ); |
265 | } |
266 | |
267 | TEST(LlvmLibcIntegerToStringTest, Width) { |
268 | using BIN = IntegerToString<uint8_t, Bin::WithWidth<4>>; |
269 | using OCT = IntegerToString<uint8_t, Oct::WithWidth<4>>; |
270 | using DEC = IntegerToString<uint8_t, Dec::WithWidth<4>>; |
271 | using HEX = IntegerToString<uint8_t, Hex::WithWidth<4>>; |
272 | EXPECT(BIN, 1, "0001" ); |
273 | EXPECT(HEX, 1, "0001" ); |
274 | EXPECT(OCT, 1, "0001" ); |
275 | EXPECT(DEC, 1, "0001" ); |
276 | } |
277 | |
278 | TEST(LlvmLibcIntegerToStringTest, Prefix) { |
279 | // WithPrefix is not supported for Decimal |
280 | using BIN = IntegerToString<uint8_t, Bin::WithPrefix>; |
281 | using OCT = IntegerToString<uint8_t, Oct::WithPrefix>; |
282 | using HEX = IntegerToString<uint8_t, Hex::WithPrefix>; |
283 | EXPECT(BIN, 1, "0b1" ); |
284 | EXPECT(HEX, 1, "0x1" ); |
285 | EXPECT(OCT, 1, "01" ); |
286 | EXPECT(OCT, 0, "0" ); // Zero is not prefixed for octal |
287 | } |
288 | |
289 | TEST(LlvmLibcIntegerToStringTest, Uppercase) { |
290 | using HEX = IntegerToString<uint64_t, Hex::Uppercase>; |
291 | EXPECT(HEX, 0xDEADC0DE, "DEADC0DE" ); |
292 | } |
293 | |
294 | TEST(LlvmLibcIntegerToStringTest, Sign) { |
295 | // WithSign only compiles with DEC |
296 | using DEC = IntegerToString<int8_t, Dec::WithSign>; |
297 | EXPECT(DEC, -1, "-1" ); |
298 | EXPECT(DEC, 0, "+0" ); |
299 | EXPECT(DEC, 1, "+1" ); |
300 | } |
301 | |
302 | TEST(LlvmLibcIntegerToStringTest, BigInt_Base_10) { |
303 | uint64_t int256_max_w64[4] = { |
304 | 0xFFFFFFFFFFFFFFFF, |
305 | 0xFFFFFFFFFFFFFFFF, |
306 | 0xFFFFFFFFFFFFFFFF, |
307 | 0x7FFFFFFFFFFFFFFF, |
308 | }; |
309 | uint64_t int256_min_w64[4] = { |
310 | 0, |
311 | 0, |
312 | 0, |
313 | 0x8000000000000000, |
314 | }; |
315 | uint32_t int256_max_w32[8] = { |
316 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
317 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, |
318 | }; |
319 | uint32_t int256_min_w32[8] = { |
320 | 0, 0, 0, 0, 0, 0, 0, 0x80000000, |
321 | }; |
322 | uint16_t int256_max_w16[16] = { |
323 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
324 | 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x7FFF, |
325 | }; |
326 | uint16_t int256_min_w16[16] = { |
327 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x8000, |
328 | }; |
329 | |
330 | using unsigned_type_w64 = IntegerToString<BigInt<256, false, uint64_t>, Dec>; |
331 | EXPECT(unsigned_type_w64, 0, "0" ); |
332 | EXPECT(unsigned_type_w64, 1, "1" ); |
333 | EXPECT(unsigned_type_w64, -1, |
334 | "115792089237316195423570985008687907853269984665640564039457584007913" |
335 | "129639935" ); |
336 | EXPECT(unsigned_type_w64, int256_max_w64, |
337 | "578960446186580977117854925043439539266349923328202820197287920039565" |
338 | "64819967" ); |
339 | EXPECT(unsigned_type_w64, int256_min_w64, |
340 | "578960446186580977117854925043439539266349923328202820197287920039565" |
341 | "64819968" ); |
342 | |
343 | using unsigned_type_w32 = IntegerToString<BigInt<256, false, uint32_t>, Dec>; |
344 | EXPECT(unsigned_type_w32, 0, "0" ); |
345 | EXPECT(unsigned_type_w32, 1, "1" ); |
346 | EXPECT(unsigned_type_w32, -1, |
347 | "115792089237316195423570985008687907853269984665640564039457584007913" |
348 | "129639935" ); |
349 | EXPECT(unsigned_type_w32, int256_max_w32, |
350 | "578960446186580977117854925043439539266349923328202820197287920039565" |
351 | "64819967" ); |
352 | EXPECT(unsigned_type_w32, int256_min_w32, |
353 | "578960446186580977117854925043439539266349923328202820197287920039565" |
354 | "64819968" ); |
355 | |
356 | using unsigned_type_w16 = IntegerToString<BigInt<256, false, uint16_t>, Dec>; |
357 | EXPECT(unsigned_type_w16, 0, "0" ); |
358 | EXPECT(unsigned_type_w16, 1, "1" ); |
359 | EXPECT(unsigned_type_w16, -1, |
360 | "115792089237316195423570985008687907853269984665640564039457584007913" |
361 | "129639935" ); |
362 | EXPECT(unsigned_type_w16, int256_max_w16, |
363 | "578960446186580977117854925043439539266349923328202820197287920039565" |
364 | "64819967" ); |
365 | EXPECT(unsigned_type_w16, int256_min_w16, |
366 | "578960446186580977117854925043439539266349923328202820197287920039565" |
367 | "64819968" ); |
368 | |
369 | using signed_type_w64 = IntegerToString<BigInt<256, true, uint64_t>, Dec>; |
370 | EXPECT(signed_type_w64, 0, "0" ); |
371 | EXPECT(signed_type_w64, 1, "1" ); |
372 | EXPECT(signed_type_w64, -1, "-1" ); |
373 | EXPECT(signed_type_w64, int256_max_w64, |
374 | "578960446186580977117854925043439539266349923328202820197287920039565" |
375 | "64819967" ); |
376 | EXPECT(signed_type_w64, int256_min_w64, |
377 | "-57896044618658097711785492504343953926634992332820282019728792003956" |
378 | "564819968" ); |
379 | |
380 | using signed_type_w32 = IntegerToString<BigInt<256, true, uint32_t>, Dec>; |
381 | EXPECT(signed_type_w32, 0, "0" ); |
382 | EXPECT(signed_type_w32, 1, "1" ); |
383 | EXPECT(signed_type_w32, -1, "-1" ); |
384 | EXPECT(signed_type_w32, int256_max_w32, |
385 | "578960446186580977117854925043439539266349923328202820197287920039565" |
386 | "64819967" ); |
387 | EXPECT(signed_type_w32, int256_min_w32, |
388 | "-57896044618658097711785492504343953926634992332820282019728792003956" |
389 | "564819968" ); |
390 | |
391 | using signed_type_w16 = IntegerToString<BigInt<256, true, uint16_t>, Dec>; |
392 | EXPECT(signed_type_w16, 0, "0" ); |
393 | EXPECT(signed_type_w16, 1, "1" ); |
394 | EXPECT(signed_type_w16, -1, "-1" ); |
395 | EXPECT(signed_type_w16, int256_max_w16, |
396 | "578960446186580977117854925043439539266349923328202820197287920039565" |
397 | "64819967" ); |
398 | EXPECT(signed_type_w16, int256_min_w16, |
399 | "-57896044618658097711785492504343953926634992332820282019728792003956" |
400 | "564819968" ); |
401 | } |
402 | |
403 | TEST(LlvmLibcIntegerToStringTest, BufferOverrun) { |
404 | { // Writing '0' in an empty buffer requiring zero digits : works |
405 | const auto view = |
406 | IntegerToString<int, Dec::WithWidth<0>>::format_to(span<char>(), 0); |
407 | ASSERT_TRUE(view.has_value()); |
408 | ASSERT_EQ(*view, string_view("" )); |
409 | } |
410 | char buffer[1]; |
411 | { // Writing '1' in a buffer of one char : works |
412 | const auto view = IntegerToString<int>::format_to(buffer, 1); |
413 | ASSERT_TRUE(view.has_value()); |
414 | ASSERT_EQ(*view, string_view("1" )); |
415 | } |
416 | { // Writing '11' in a buffer of one char : fails |
417 | const auto view = IntegerToString<int>::format_to(buffer, 11); |
418 | ASSERT_FALSE(view.has_value()); |
419 | } |
420 | } |
421 | |