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