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