15db033e2SMark de Wever //===----------------------------------------------------------------------===// 2*6a54dfbfSLouis Dionne // 35db033e2SMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45db033e2SMark de Wever // See https://llvm.org/LICENSE.txt for license information. 55db033e2SMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65db033e2SMark de Wever // 75db033e2SMark de Wever //===----------------------------------------------------------------------===// 85db033e2SMark de Wever 95db033e2SMark de Wever // UNSUPPORTED: c++03, c++11, c++14, c++17 10520c7fbbSLouis Dionne // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME 115db033e2SMark de Wever 125db033e2SMark de Wever // This version runs the test when the platform has Unicode support. 135db033e2SMark de Wever // UNSUPPORTED: libcpp-has-no-unicode 145db033e2SMark de Wever 155db033e2SMark de Wever // XFAIL: availability-fp_to_chars-missing 165db033e2SMark de Wever 175db033e2SMark de Wever // <format> 185db033e2SMark de Wever 195db033e2SMark de Wever // The paper 205db033e2SMark de Wever // P2572R1 std::format fill character allowances 215db033e2SMark de Wever // adds support for Unicode Scalar Values as fill character. 225db033e2SMark de Wever 235db033e2SMark de Wever #include <format> 245db033e2SMark de Wever 255db033e2SMark de Wever #include "assert_macros.h" 265db033e2SMark de Wever #include "concat_macros.h" 275db033e2SMark de Wever #include "format.functions.common.h" 285db033e2SMark de Wever #include "make_string.h" 295db033e2SMark de Wever #include "string_literal.h" 305db033e2SMark de Wever #include "test_format_string.h" 315db033e2SMark de Wever #include "test_macros.h" 325db033e2SMark de Wever 335db033e2SMark de Wever #define SV(S) MAKE_STRING_VIEW(CharT, S) 345db033e2SMark de Wever 355db033e2SMark de Wever auto check = []<class CharT, class... Args>( 365db033e2SMark de Wever std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) { 375db033e2SMark de Wever std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...); 385db033e2SMark de Wever TEST_REQUIRE(out == expected, 395db033e2SMark de Wever TEST_WRITE_CONCATENATED( 405db033e2SMark de Wever "\nFormat string ", fmt.get(), "\nExpected output ", expected, "\nActual output ", out, '\n')); 415db033e2SMark de Wever }; 425db033e2SMark de Wever 435db033e2SMark de Wever auto check_exception = 445db033e2SMark de Wever []<class CharT, class... Args>( 455db033e2SMark de Wever [[maybe_unused]] std::string_view what, 465db033e2SMark de Wever [[maybe_unused]] std::basic_string_view<CharT> fmt, 475db033e2SMark de Wever [[maybe_unused]] Args&&... args) { 485db033e2SMark de Wever TEST_VALIDATE_EXCEPTION( 495db033e2SMark de Wever std::format_error, 505db033e2SMark de Wever [&]([[maybe_unused]] const std::format_error& e) { 515db033e2SMark de Wever TEST_LIBCPP_REQUIRE( 525db033e2SMark de Wever e.what() == what, 535db033e2SMark de Wever TEST_WRITE_CONCATENATED( 545db033e2SMark de Wever "\nFormat string ", fmt, "\nExpected exception ", what, "\nActual exception ", e.what(), '\n')); 555db033e2SMark de Wever }, 565db033e2SMark de Wever TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...))); 575db033e2SMark de Wever }; 585db033e2SMark de Wever 595db033e2SMark de Wever template <class CharT> 605db033e2SMark de Wever void test() { 615db033e2SMark de Wever // 1, 2, 3, 4 code unit UTF-8 transitions 625db033e2SMark de Wever check(SV("\u000042\u0000"), SV("{:\u0000^4}"), 42); 635db033e2SMark de Wever check(SV("\u007f42\u007f"), SV("{:\u007f^4}"), 42); 645db033e2SMark de Wever check(SV("\u008042\u0080"), SV("{:\u0080^4}"), 42); 655db033e2SMark de Wever check(SV("\u07ff42\u07ff"), SV("{:\u07ff^4}"), 42); 665db033e2SMark de Wever check(SV("\u080042\u0800"), SV("{:\u0800^4}"), 42); 675db033e2SMark de Wever check(SV("\uffff42\uffff"), SV("{:\uffff^4}"), 42); 685db033e2SMark de Wever check(SV("\U0010000042\U00100000"), SV("{:\U00100000^4}"), 42); 695db033e2SMark de Wever check(SV("\U0010ffff42\U0010ffff"), SV("{:\U0010ffff^4}"), 42); 705db033e2SMark de Wever 715db033e2SMark de Wever // Examples of P2572R1 725db033e2SMark de Wever check(SV("x"), SV("{:^6}"), SV("x")); 735db033e2SMark de Wever check(SV(""), SV("{:*^6}"), SV("")); 745db033e2SMark de Wever check(SV("12345678"), SV("{:*>6}"), SV("12345678")); 755db033e2SMark de Wever 765db033e2SMark de Wever // Invalid Unicode Scalar Values 775db033e2SMark de Wever if constexpr (std::same_as<CharT, char>) { 78402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xa0\x80^}"), 42); // U+D800 79402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xa0\xbf^}"), 42); // U+DBFF 80402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xbf\x80^}"), 42); // U+DC00 81402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xbf\xbf^}"), 42); // U+DFFF 825db033e2SMark de Wever 835db033e2SMark de Wever check_exception( 84402eb2efSMark de Wever "The format specifier contains malformed Unicode characters", SV("{:\xf4\x90\x80\x80^}"), 42); // U+110000 855db033e2SMark de Wever check_exception( 86402eb2efSMark de Wever "The format specifier contains malformed Unicode characters", SV("{:\xf4\x90\xbf\xbf^}"), 42); // U+11FFFF 875db033e2SMark de Wever 88402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", 895db033e2SMark de Wever SV("{:\x80^}"), 905db033e2SMark de Wever 42); // Trailing code unit with no leading one. 91402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", 92402eb2efSMark de Wever SV("{:\xc0^}"), 93402eb2efSMark de Wever 42); // Missing trailing code unit. 94402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", 95402eb2efSMark de Wever SV("{:\xe0\x80^}"), 96402eb2efSMark de Wever 42); // Missing trailing code unit. 97402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", 985db033e2SMark de Wever SV("{:\xf0\x80^}"), 995db033e2SMark de Wever 42); // Missing two trailing code units. 100402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", 1015db033e2SMark de Wever SV("{:\xf0\x80\x80^}"), 1025db033e2SMark de Wever 42); // Missing trailing code unit. 1035db033e2SMark de Wever 1045db033e2SMark de Wever #ifndef TEST_HAS_NO_WIDE_CHARACTERS 1055db033e2SMark de Wever } else { 1065db033e2SMark de Wever # ifdef TEST_SHORT_WCHAR 107402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xd800^}"}, 42); 108402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdbff^}"}, 42); 109402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdc00^}"}, 42); 110402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xddff^}"}, 42); 1115db033e2SMark de Wever 112402eb2efSMark de Wever check_exception("The format specifier contains malformed Unicode characters", 1135db033e2SMark de Wever std::wstring_view{L"{:\xdc00\xd800^}"}, 1145db033e2SMark de Wever 42); // Reverted surrogates. 1155db033e2SMark de Wever 1165db033e2SMark de Wever # else // TEST_SHORT_WCHAR 117402eb2efSMark de Wever check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xd800^}"}, 42); 118402eb2efSMark de Wever check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdbff^}"}, 42); 119402eb2efSMark de Wever check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdc00^}"}, 42); 120402eb2efSMark de Wever check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xddff^}"}, 42); 1215db033e2SMark de Wever 1225db033e2SMark de Wever check_exception( 123a0ffecccSMark de Wever "The format specifier should consume the input or end with a '}'", std::wstring_view{L"{:\xdc00\xd800^}"}, 42); 1245db033e2SMark de Wever 125402eb2efSMark de Wever check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x00110000^}"}, 42); 126402eb2efSMark de Wever check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x0011ffff^}"}, 42); 1275db033e2SMark de Wever # endif // TEST_SHORT_WCHAR 1285db033e2SMark de Wever #endif // TEST_HAS_NO_WIDE_CHARACTERS 1295db033e2SMark de Wever } 1305db033e2SMark de Wever } 1315db033e2SMark de Wever 1325db033e2SMark de Wever int main(int, char**) { 1335db033e2SMark de Wever test<char>(); 1345db033e2SMark de Wever 1355db033e2SMark de Wever #ifndef TEST_HAS_NO_WIDE_CHARACTERS 1365db033e2SMark de Wever test<wchar_t>(); 1375db033e2SMark de Wever #endif 1385db033e2SMark de Wever 1395db033e2SMark de Wever return 0; 1405db033e2SMark de Wever } 141