1 //===----------------------------------------------------------------------===// 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 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 10 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME 11 12 // This version runs the test when the platform has Unicode support. 13 // UNSUPPORTED: libcpp-has-no-unicode 14 15 // TODO FMT This test should not require std::to_chars(floating-point) 16 // XFAIL: availability-fp_to_chars-missing 17 18 // <format> 19 20 // This test the debug string type for the formatter specializations for char 21 // and string types. This tests Unicode strings. 22 23 #include <format> 24 25 #include <cassert> 26 #include <concepts> 27 #include <cstdint> 28 #include <iterator> 29 #include <list> 30 #include <vector> 31 32 #include "test_macros.h" 33 #include "make_string.h" 34 #include "test_format_string.h" 35 #include "assert_macros.h" 36 #include "concat_macros.h" 37 38 #ifndef TEST_HAS_NO_LOCALIZATION 39 # include <iostream> 40 #endif 41 42 #define SV(S) MAKE_STRING_VIEW(CharT, S) 43 44 auto test_format = []<class CharT, class... Args>( 45 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) { 46 { 47 std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...); 48 TEST_REQUIRE(out == expected, 49 TEST_WRITE_CONCATENATED( 50 "\nFormat string ", fmt.get(), "\nExpected output ", expected, "\nActual output ", out, '\n')); 51 } 52 #ifndef TEST_HAS_NO_LOCALIZATION 53 { 54 std::basic_string<CharT> out = std::format(std::locale(), fmt, std::forward<Args>(args)...); 55 assert(out == expected); 56 } 57 #endif // TEST_HAS_NO_LOCALIZATION 58 }; 59 60 auto test_format_to = 61 []<class CharT, class... Args>( 62 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) { 63 { 64 std::basic_string<CharT> out(expected.size(), CharT(' ')); 65 auto it = std::format_to(out.begin(), fmt, std::forward<Args>(args)...); 66 assert(it == out.end()); 67 assert(out == expected); 68 } 69 #ifndef TEST_HAS_NO_LOCALIZATION 70 { 71 std::basic_string<CharT> out(expected.size(), CharT(' ')); 72 auto it = std::format_to(out.begin(), std::locale(), fmt, std::forward<Args>(args)...); 73 assert(it == out.end()); 74 assert(out == expected); 75 } 76 #endif // TEST_HAS_NO_LOCALIZATION 77 { 78 std::list<CharT> out; 79 std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...); 80 assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end())); 81 } 82 { 83 std::vector<CharT> out; 84 std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...); 85 assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end())); 86 } 87 { 88 assert(expected.size() < 4096 && "Update the size of the buffer."); 89 CharT out[4096]; 90 CharT* it = std::format_to(out, fmt, std::forward<Args>(args)...); 91 assert(std::distance(out, it) == int(expected.size())); 92 // Convert to std::string since output contains '\0' for boolean tests. 93 assert(std::basic_string<CharT>(out, it) == expected); 94 } 95 }; 96 97 auto test_formatted_size = 98 []<class CharT, class... Args>( 99 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) { 100 { 101 std::size_t size = std::formatted_size(fmt, std::forward<Args>(args)...); 102 assert(size == expected.size()); 103 } 104 #ifndef TEST_HAS_NO_LOCALIZATION 105 { 106 std::size_t size = std::formatted_size(std::locale(), fmt, std::forward<Args>(args)...); 107 assert(size == expected.size()); 108 } 109 #endif // TEST_HAS_NO_LOCALIZATION 110 }; 111 112 auto test_format_to_n = 113 []<class CharT, class... Args>( 114 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) { 115 { 116 std::size_t n = expected.size(); 117 std::basic_string<CharT> out(n, CharT(' ')); 118 std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...); 119 assert(result.size == static_cast<std::ptrdiff_t>(expected.size())); 120 assert(result.out == out.end()); 121 assert(out == expected); 122 } 123 #ifndef TEST_HAS_NO_LOCALIZATION 124 { 125 std::size_t n = expected.size(); 126 std::basic_string<CharT> out(n, CharT(' ')); 127 std::format_to_n_result result = 128 std::format_to_n(out.begin(), n, std::locale(), fmt, std::forward<Args>(args)...); 129 assert(result.size == static_cast<std::ptrdiff_t>(expected.size())); 130 assert(result.out == out.end()); 131 assert(out == expected); 132 } 133 #endif // TEST_HAS_NO_LOCALIZATION 134 { 135 std::ptrdiff_t n = 0; 136 std::basic_string<CharT> out; 137 std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...); 138 assert(result.size == static_cast<std::ptrdiff_t>(expected.size())); 139 assert(result.out == out.end()); 140 assert(out.empty()); 141 } 142 { 143 std::ptrdiff_t n = expected.size() / 2; 144 std::basic_string<CharT> out(n, CharT(' ')); 145 std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...); 146 assert(result.size == static_cast<std::ptrdiff_t>(expected.size())); 147 assert(result.out == out.end()); 148 assert(out == expected.substr(0, n)); 149 } 150 }; 151 152 template <class CharT> 153 void test_char() { 154 // *** P2286 examples *** 155 test_format(SV("['\\'', '\"']"), SV("[{:?}, {:?}]"), CharT('\''), CharT('"')); 156 157 // *** Special cases *** 158 test_format(SV("'\\t'"), SV("{:?}"), CharT('\t')); 159 test_format(SV("'\\n'"), SV("{:?}"), CharT('\n')); 160 test_format(SV("'\\r'"), SV("{:?}"), CharT('\r')); 161 test_format(SV("'\\\\'"), SV("{:?}"), CharT('\\')); 162 163 test_format(SV("'\\\''"), SV("{:?}"), CharT('\'')); 164 test_format(SV("'\"'"), SV("{:?}"), CharT('"')); // only special for string 165 166 test_format(SV("' '"), SV("{:?}"), CharT(' ')); 167 168 // *** Printable *** 169 test_format(SV("'a'"), SV("{:?}"), CharT('a')); 170 test_format(SV("'b'"), SV("{:?}"), CharT('b')); 171 test_format(SV("'c'"), SV("{:?}"), CharT('c')); 172 173 // *** Non-printable *** 174 175 // Control 176 test_format(SV("'\\u{0}'"), SV("{:?}"), CharT('\0')); 177 test_format(SV("'\\u{1f}'"), SV("{:?}"), CharT('\x1f')); 178 179 // Ill-formed 180 if constexpr (sizeof(CharT) == 1) 181 test_format(SV("'\\x{80}'"), SV("{:?}"), CharT('\x80')); 182 183 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 184 if constexpr (sizeof(CharT) > 1) { 185 using V = std::basic_string_view<CharT>; 186 187 // Unicode fitting in a 16-bit wchar_t 188 189 // *** Non-printable *** 190 191 // Space_Separator 192 test_format(V{L"'\\u{a0}'"}, L"{:?}", L'\xa0'); // NO-BREAK SPACE 193 test_format(V{L"'\\u{3000}'"}, L"{:?}", L'\x3000'); // IDEOGRAPHIC SPACE 194 195 // Line_Separator 196 test_format(V{L"'\\u{2028}'"}, L"{:?}", L'\x2028'); // LINE SEPARATOR 197 198 // Paragraph_Separator 199 test_format(V{L"'\\u{2029}'"}, L"{:?}", L'\x2029'); // PARAGRAPH SEPARATOR 200 201 // Format 202 test_format(V{L"'\\u{ad}'"}, L"{:?}", L'\xad'); // SOFT HYPHEN 203 test_format(V{L"'\\u{600}'"}, L"{:?}", L'\x600'); // ARABIC NUMBER SIGN 204 test_format(V{L"'\\u{feff}'"}, L"{:?}", L'\xfeff'); // ZERO WIDTH NO-BREAK SPACE 205 206 // Incomplete surrogate pair in UTF-16 207 test_format(V{L"'\\x{d800}'"}, L"{:?}", L'\xd800'); // <surrogate-D800> 208 test_format(V{L"'\\x{dfff}'"}, L"{:?}", L'\xdfff'); // <surrogate-DFFF> 209 210 // Private_Use 211 test_format(V{L"'\\u{e000}'"}, L"{:?}", L'\xe000'); // <private-use-E000> 212 test_format(V{L"'\\u{f8ff}'"}, L"{:?}", L'\xf8ff'); // <private-use-F8FF> 213 214 // Unassigned 215 test_format(V{L"'\\u{378}'"}, L"{:?}", L'\x378'); // <reserved-0378> 216 test_format(V{L"'\\u{1774}'"}, L"{:?}", L'\x1774'); // <reserved-1774> 217 test_format(V{L"'\\u{ffff}'"}, L"{:?}", L'\xffff'); // <noncharacter-FFFF> 218 219 // Grapheme Extended 220 test_format(V{L"'\\u{300}'"}, L"{:?}", L'\x300'); // COMBINING GRAVE ACCENT 221 test_format(V{L"'\\u{fe20}'"}, L"{:?}", L'\xfe20'); // VARIATION SELECTOR-1 222 } 223 # ifndef TEST_SHORT_WCHAR 224 if constexpr (sizeof(CharT) > 2) { 225 static_assert(sizeof(CharT) == 4, "add support for unexpected size"); 226 // Unicode fitting in a 32-bit wchar_t 227 228 constexpr wchar_t x = 0x1ffff; 229 constexpr std::uint32_t y = 0x1ffff; 230 static_assert(x == y); 231 232 using V = std::basic_string_view<CharT>; 233 234 // *** Non-printable *** 235 // Format 236 test_format(V{L"'\\u{110bd}'"}, L"{:?}", L'\x110bd'); // KAITHI NUMBER SIGN 237 test_format(V{L"'\\u{e007f}'"}, L"{:?}", L'\xe007f'); // CANCEL TAG 238 239 // Private_Use 240 test_format(V{L"'\\u{f0000}'"}, L"{:?}", L'\xf0000'); // <private-use-F0000> 241 test_format(V{L"'\\u{ffffd}'"}, L"{:?}", L'\xffffd'); // <private-use-FFFFD> 242 243 test_format(V{L"'\\u{100000}'"}, L"{:?}", L'\x100000'); // <private-use-100000> 244 test_format(V{L"'\\u{10fffd}'"}, L"{:?}", L'\x10fffd'); // <private-use-10FFFD> 245 246 // Unassigned 247 test_format(V{L"'\\u{1000c}'"}, L"{:?}", L'\x1000c'); // <reserved-1000c> 248 test_format(V{L"'\\u{fffff}'"}, L"{:?}", L'\xfffff'); // <noncharacter-FFFFF> 249 test_format(V{L"'\\u{10fffe}'"}, L"{:?}", L'\x10fffe'); // <noncharacter-10FFFE> 250 251 // Grapheme Extended 252 test_format(V{L"'\\u{101fd}'"}, L"{:?}", L'\x101fd'); // COMBINING OLD PERMIC LETTER AN 253 test_format(V{L"'\\u{e0100}'"}, L"{:?}", L'\xe0100'); // VARIATION SELECTOR-17 254 255 // Ill-formed 256 test_format(V{L"'\\x{110000}'"}, L"{:?}", L'\x110000'); 257 test_format(V{L"'\\x{ffffffff}'"}, L"{:?}", L'\xffffffff'); 258 } 259 # endif // TEST_SHORT_WCHAR 260 #endif // TEST_HAS_NO_WIDE_CHARACTERS 261 } 262 263 template <class CharT> 264 void test_string() { 265 // *** P2286 examples *** 266 test_format(SV("[h\tllo]"), SV("[{}]"), SV("h\tllo")); 267 test_format(SV(R"(["h\tllo"])"), SV("[{:?}]"), SV("h\tllo")); 268 test_format(SV(R"(["Спасибо, Виктор ♥!"])"), SV("[{:?}]"), SV("Спасибо, Виктор ♥!")); 269 270 test_format(SV(R"(["\u{0} \n \t \u{2} \u{1b}"])"), SV("[{:?}]"), SV("\0 \n \t \x02 \x1b")); 271 272 if constexpr (sizeof(CharT) == 1) { 273 // Ill-formend UTF-8 274 test_format(SV(R"(["\x{c3}"])"), SV("[{:?}]"), "\xc3"); 275 test_format(SV(R"(["\x{c3}("])"), SV("[{:?}]"), "\xc3\x28"); 276 277 /* U+0000..U+0007F 1 code unit range, encoded in 2 code units. */ 278 test_format(SV(R"(["\x{c0}\x{80}"])"), SV("[{:?}]"), "\xc0\x80"); // U+0000 279 test_format(SV(R"(["\x{c1}\x{bf}"])"), SV("[{:?}]"), "\xc1\xbf"); // U+007F 280 test_format(SV(R"(["\u{80}"])"), SV("[{:?}]"), "\xc2\x80"); // U+0080 first valid (General_Category=Control) 281 282 /* U+0000..U+07FFF 1 and 2 code unit range, encoded in 3 code units. */ 283 test_format(SV(R"(["\x{e0}\x{80}\x{80}"])"), SV("[{:?}]"), "\xe0\x80\x80"); // U+0000 284 test_format(SV(R"(["\x{e0}\x{81}\x{bf}"])"), SV("[{:?}]"), "\xe0\x81\xbf"); // U+007F 285 test_format(SV(R"(["\x{e0}\x{82}\x{80}"])"), SV("[{:?}]"), "\xe0\x82\x80"); // U+0080 286 test_format(SV(R"(["\x{e0}\x{9f}\x{bf}"])"), SV("[{:?}]"), "\xe0\x9f\xbf"); // U+07FF 287 test_format(SV("[\"\u0800\"]"), SV("[{:?}]"), "\xe0\xa0\x80"); // U+0800 first valid 288 289 #if 0 290 // This code point is in the Hangul Jamo Extended-B block and at the time of writing 291 // it's unassigned. When it comes defined, this branch might become true. 292 test_format(SV("[\"\ud7ff\"]"), SV("[{:?}]"), "\xed\x9f\xbf"); // U+D7FF last valid 293 #else 294 /* U+D800..D+DFFFF surrogate range */ 295 test_format(SV(R"(["\u{d7ff}"])"), SV("[{:?}]"), "\xed\x9f\xbf"); // U+D7FF last valid 296 #endif 297 test_format(SV(R"(["\x{ed}\x{a0}\x{80}"])"), SV("[{:?}]"), "\xed\xa0\x80"); // U+D800 298 test_format(SV(R"(["\x{ed}\x{af}\x{bf}"])"), SV("[{:?}]"), "\xed\xaf\xbf"); // U+DBFF 299 test_format(SV(R"(["\x{ed}\x{bf}\x{80}"])"), SV("[{:?}]"), "\xed\xbf\x80"); // U+DC00 300 test_format(SV(R"(["\x{ed}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xed\xbf\xbf"); // U+DFFF 301 test_format(SV(R"(["\u{e000}"])"), SV("[{:?}]"), "\xee\x80\x80"); // U+E000 first valid 302 // (in the Private Use Area block) 303 304 /* U+0000..U+FFFF 1, 2, and 3 code unit range */ 305 test_format(SV(R"(["\x{f0}\x{80}\x{80}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\x80\x80"); // U+0000 306 test_format(SV(R"(["\x{f0}\x{80}\x{81}\x{bf}"])"), SV("[{:?}]"), "\xf0\x80\x81\xbf"); // U+007F 307 test_format(SV(R"(["\x{f0}\x{80}\x{82}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\x82\x80"); // U+0080 308 test_format(SV(R"(["\x{f0}\x{80}\x{9f}\x{bf}"])"), SV("[{:?}]"), "\xf0\x80\x9f\xbf"); // U+07FF 309 test_format(SV(R"(["\x{f0}\x{80}\x{a0}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\xa0\x80"); // U+0800 310 test_format(SV(R"(["\x{f0}\x{8f}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xf0\x8f\xbf\xbf"); // U+FFFF 311 test_format(SV("[\"\U00010000\"]"), SV("[{:?}]"), "\xf0\x90\x80\x80"); // U+10000 first valid 312 313 /* U+10FFFF..U+1FFFFF invalid range */ 314 test_format(SV(R"(["\u{10ffff}"])"), SV("[{:?}]"), "\xf4\x8f\xbf\xbf"); // U+10FFFF last valid 315 // (in Supplementary Private Use Area-B) 316 test_format(SV(R"(["\x{f4}\x{90}\x{80}\x{80}"])"), SV("[{:?}]"), "\xf4\x90\x80\x80"); // U+110000 317 test_format(SV(R"(["\x{f4}\x{bf}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xf4\xbf\xbf\xbf"); // U+11FFFF 318 } else { 319 // Valid UTF-16 and UTF-32 320 test_format(SV("[\"\u00c3\"]"), SV("[{:?}]"), L"\xc3"); // LATIN CAPITAL LETTER A WITH TILDE 321 test_format(SV("[\"\u00c3(\"]"), SV("[{:?}]"), L"\xc3\x28"); 322 } 323 324 // LWG-3965 325 test_format(SV(R"(["\u{200d}♂️"])"), SV("[{:?}]"), SV("♂️")); 326 327 // *** Special cases *** 328 test_format(SV(R"("\t\n\r\\'\" ")"), SV("{:?}"), SV("\t\n\r\\'\" ")); 329 330 // *** Printable *** 331 test_format(SV(R"("abcdefg")"), SV("{:?}"), SV("abcdefg")); 332 333 // *** Non-printable *** 334 335 // Control 336 test_format(SV(R"("\u{0}\u{1f}")"), SV("{:?}"), SV("\0\x1f")); 337 338 // Ill-formed 339 if constexpr (sizeof(CharT) == 1) 340 test_format(SV(R"("\x{80}")"), SV("{:?}"), SV("\x80")); 341 342 // *** P2713R1 examples *** 343 test_format(SV(R"(["\u{301}"])"), SV("[{:?}]"), SV("\u0301")); 344 test_format(SV(R"(["\\\u{301}"])"), SV("[{:?}]"), SV("\\\u0301")); 345 test_format(SV(R"(["ẹ́"])"), SV("[{:?}]"), SV("e\u0301\u0323")); 346 347 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 348 if constexpr (sizeof(CharT) > 1) { 349 using V = std::basic_string_view<CharT>; 350 351 // Unicode fitting in a 16-bit wchar_t 352 353 // *** Non-printable *** 354 355 // Space_Separator 356 test_format(V{LR"("\u{a0}\u{3000}")"}, L"{:?}", L"\xa0\x3000"); 357 358 // Line_Separator 359 test_format(V{LR"("\u{2028}")"}, L"{:?}", L"\x2028"); // LINE SEPARATOR 360 361 // Paragraph_Separator 362 test_format(V{LR"("\u{2029}")"}, L"{:?}", L"\x2029"); // PARAGRAPH SEPARATOR 363 364 // Format 365 test_format(V{LR"("\u{ad}\u{600}\u{feff}")"}, L"{:?}", L"\xad\x600\xfeff"); 366 367 // Incomplete surrogate pair in UTF-16 368 test_format(V{LR"("\x{d800}")"}, L"{:?}", L"\xd800"); 369 370 // Private_Use 371 test_format(V{LR"("\u{e000}\u{f8ff}")"}, L"{:?}", L"\xe000\xf8ff"); 372 373 // Unassigned 374 test_format(V{LR"("\u{378}\u{1774}\u{ffff}")"}, L"{:?}", L"\x378\x1774\xffff"); 375 376 // Grapheme Extended 377 test_format(V{LR"("\u{300}\u{fe20}")"}, L"{:?}", L"\x300\xfe20"); 378 } 379 # ifndef TEST_SHORT_WCHAR 380 if constexpr (sizeof(CharT) > 2) { 381 static_assert(sizeof(CharT) == 4, "add support for unexpected size"); 382 // Unicode fitting in a 32-bit wchar_t 383 384 constexpr wchar_t x = 0x1ffff; 385 constexpr std::uint32_t y = 0x1ffff; 386 static_assert(x == y); 387 388 using V = std::basic_string_view<CharT>; 389 390 // *** Non-printable *** 391 // Format 392 test_format(V{LR"("\u{110bd}\u{e007f}")"}, L"{:?}", L"\x110bd\xe007f"); 393 394 // Private_Use 395 test_format(V{LR"("\u{f0000}\u{ffffd}\u{100000}\u{10fffd}")"}, L"{:?}", L"\xf0000\xffffd\x100000\x10fffd"); 396 397 // Unassigned 398 test_format(V{LR"("\u{1000c}\u{fffff}\u{10fffe}")"}, L"{:?}", L"\x1000c\xfffff\x10fffe"); 399 400 // Grapheme Extended 401 test_format(V{LR"("\u{101fd}\u{e0100}")"}, L"{:?}", L"\x101fd\xe0100"); 402 403 // Ill-formed 404 test_format(V{LR"("\x{110000}\x{ffffffff}")"}, L"{:?}", L"\x110000\xffffffff"); 405 } 406 # endif // TEST_SHORT_WCHAR 407 #endif // TEST_HAS_NO_WIDE_CHARACTERS 408 } 409 410 template <class CharT, class TestFunction> 411 void test_format_functions(TestFunction check) { 412 // *** align-fill & width *** 413 check(SV(R"(***"hellö")"), SV("{:*>10?}"), SV("hellö")); // ö is LATIN SMALL LETTER O WITH DIAERESIS 414 check(SV(R"(*"hellö"**)"), SV("{:*^10?}"), SV("hellö")); 415 check(SV(R"("hellö"***)"), SV("{:*<10?}"), SV("hellö")); 416 417 check(SV(R"(***"hellö")"), SV("{:*>10?}"), SV("hello\u0308")); 418 check(SV(R"(*"hellö"**)"), SV("{:*^10?}"), SV("hello\u0308")); 419 check(SV(R"("hellö"***)"), SV("{:*<10?}"), SV("hello\u0308")); 420 421 check(SV(R"(***"hello \u{200d}♂️")"), SV("{:*>22?}"), SV("hello ♂️")); 422 check(SV(R"(*"hello \u{200d}♂️"**)"), SV("{:*^22?}"), SV("hello ♂️")); 423 check(SV(R"("hello \u{200d}♂️"***)"), SV("{:*<22?}"), SV("hello ♂️")); 424 425 // *** width *** 426 check(SV(R"("hellö" )"), SV("{:10?}"), SV("hellö")); 427 check(SV(R"("hellö" )"), SV("{:10?}"), SV("hello\u0308")); 428 check(SV(R"("hello \u{200d}♂️" )"), SV("{:22?}"), SV("hello ♂️")); 429 430 // *** precision *** 431 check(SV(R"("hell)"), SV("{:.5?}"), SV("hellö")); 432 check(SV(R"("hellö)"), SV("{:.6?}"), SV("hellö")); 433 check(SV(R"("hellö")"), SV("{:.7?}"), SV("hellö")); 434 435 check(SV(R"("hello )"), SV("{:.7?}"), SV("hello ♂️")); 436 check(SV(R"("hello )"), SV("{:.8?}"), SV("hello ♂️")); // shrug is two columns 437 check(SV(R"("hello )"), SV("{:.9?}"), SV("hello ♂️")); 438 check(SV(R"("hello \)"), SV("{:.10?}"), SV("hello ♂️")); 439 check(SV(R"("hello \u{200d})"), SV("{:.17?}"), SV("hello ♂️")); 440 check(SV(R"("hello \u{200d}♂️)"), SV("{:.18?}"), SV("hello ♂️")); 441 check(SV(R"("hello \u{200d}♂️")"), SV("{:.19?}"), SV("hello ♂️")); 442 443 // *** width & precision *** 444 check(SV(R"("hell#########################)"), SV("{:#<30.5?}"), SV("hellö")); 445 check(SV(R"("hellö########################)"), SV("{:#<30.6?}"), SV("hellö")); 446 check(SV(R"("hellö"#######################)"), SV("{:#<30.7?}"), SV("hellö")); 447 448 check(SV(R"("hello #######################)"), SV("{:#<30.7?}"), SV("hello ♂️")); 449 check(SV(R"("hello #######################)"), SV("{:#<30.8?}"), SV("hello ♂️")); 450 check(SV(R"("hello #####################)"), SV("{:#<30.9?}"), SV("hello ♂️")); 451 check(SV(R"("hello \####################)"), SV("{:#<30.10?}"), SV("hello ♂️")); 452 check(SV(R"("hello \u{200d}#############)"), SV("{:#<30.17?}"), SV("hello ♂️")); 453 check(SV(R"("hello \u{200d}♂️############)"), SV("{:#<30.18?}"), SV("hello ♂️")); 454 check(SV(R"("hello \u{200d}♂️"###########)"), SV("{:#<30.19?}"), SV("hello ♂️")); 455 } 456 457 template <class CharT> 458 void test() { 459 test_char<CharT>(); 460 test_string<CharT>(); 461 462 test_format_functions<CharT>(test_format); 463 test_format_functions<CharT>(test_format_to); 464 test_format_functions<CharT>(test_formatted_size); 465 test_format_functions<CharT>(test_format_to_n); 466 } 467 468 static void test_ill_formed_utf8() { 469 using namespace std::literals; 470 471 // Too few code units 472 test_format(R"("\x{df}")"sv, "{:?}", "\xdf"); 473 test_format(R"("\x{ef}")"sv, "{:?}", "\xef"); 474 test_format(R"("\x{ef}\x{bf}")"sv, "{:?}", "\xef\xbf"); 475 test_format(R"("\x{f7}")"sv, "{:?}", "\xf7"); 476 test_format(R"("\x{f7}\x{bf}")"sv, "{:?}", "\xf7\xbf"); 477 test_format(R"("\x{f7}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf"); 478 479 // Invalid continuation byte 480 test_format(R"("\x{df}a")"sv, 481 "{:?}", 482 "\xdf" 483 "a"); 484 test_format(R"("\x{ef}a")"sv, 485 "{:?}", 486 "\xef" 487 "a"); 488 test_format(R"("\x{ef}\x{bf}a")"sv, 489 "{:?}", 490 "\xef\xbf" 491 "a"); 492 test_format(R"("\x{f7}a")"sv, 493 "{:?}", 494 "\xf7" 495 "a"); 496 test_format(R"("\x{f7}\x{bf}a")"sv, 497 "{:?}", 498 "\xf7\xbf" 499 "a"); 500 test_format(R"("\x{f7}\x{bf}\x{bf}a")"sv, 501 "{:?}", 502 "\xf7\xbf\xbf" 503 "a"); 504 505 test_format(R"("a\x{f1}\x{80}\x{80}\x{e1}\x{80}\x{c2}b")"sv, 506 "{:?}", 507 "a" 508 "\xf1\x80\x80\xe1\x80\xc2" 509 "b"); 510 511 // Code unit out of range 512 test_format(R"("\u{10ffff}")"sv, "{:?}", "\xf4\x8f\xbf\xbf"); // last valid code point 513 test_format(R"("\x{f4}\x{90}\x{80}\x{80}")"sv, "{:?}", "\xf4\x90\x80\x80"); // first invalid code point 514 test_format(R"("\x{f5}\x{b1}\x{b2}\x{b3}")"sv, "{:?}", "\xf5\xb1\xb2\xb3"); 515 test_format(R"("\x{f7}\x{bf}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf\xbf"); // largest encoded code point 516 } 517 518 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 519 # ifdef TEST_SHORT_WCHAR 520 static void test_ill_formed_utf16() { 521 using namespace std::literals; 522 523 // Too few code units 524 test_format(LR"("\x{d800}")"sv, L"{:?}", L"\xd800"); 525 test_format(LR"("\x{dbff}")"sv, L"{:?}", L"\xdbff"); 526 527 // Start with low surrogate pair 528 test_format(LR"("\x{dc00}a")"sv, 529 L"{:?}", 530 L"\xdc00" 531 "a"); 532 test_format(LR"("\x{dfff}a")"sv, 533 L"{:?}", 534 L"\xdfff" 535 "a"); 536 537 // Only high surrogate pair 538 test_format(LR"("\x{d800}a")"sv, 539 L"{:?}", 540 L"\xd800" 541 "a"); 542 test_format(LR"("\x{dbff}a")"sv, 543 L"{:?}", 544 L"\xdbff" 545 "a"); 546 } 547 # else // TEST_SHORT_WCHAR 548 static void test_ill_formed_utf32() { 549 using namespace std::literals; 550 551 test_format(LR"("\u{10ffff}")"sv, L"{:?}", L"\x10ffff"); // last valid code point 552 test_format(LR"("\x{110000}")"sv, L"{:?}", L"\x110000"); // first invalid code point 553 test_format(LR"("\x{ffffffff}")"sv, L"{:?}", L"\xffffffff"); // largest encoded code point 554 } 555 556 # endif // TEST_SHORT_WCHAR 557 #endif // TEST_HAS_NO_WIDE_CHARACTERS 558 559 int main(int, char**) { 560 test<char>(); 561 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 562 test<wchar_t>(); 563 #endif 564 565 test_ill_formed_utf8(); 566 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 567 # ifdef TEST_SHORT_WCHAR 568 test_ill_formed_utf16(); 569 # else // TEST_SHORT_WCHAR 570 test_ill_formed_utf32(); 571 # endif // TEST_SHORT_WCHAR 572 #endif // TEST_HAS_NO_WIDE_CHARACTERS 573 574 return 0; 575 } 576