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 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 // XFAIL: availability-fp_to_chars-missing 16 17 // <format> 18 19 // The paper 20 // P2572R1 std::format fill character allowances 21 // adds support for Unicode Scalar Values as fill character. 22 23 #include <format> 24 25 #include "assert_macros.h" 26 #include "concat_macros.h" 27 #include "format.functions.common.h" 28 #include "make_string.h" 29 #include "string_literal.h" 30 #include "test_format_string.h" 31 #include "test_macros.h" 32 33 #define SV(S) MAKE_STRING_VIEW(CharT, S) 34 35 auto check = []<class CharT, class... Args>( 36 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) { 37 std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...); 38 TEST_REQUIRE(out == expected, 39 TEST_WRITE_CONCATENATED( 40 "\nFormat string ", fmt.get(), "\nExpected output ", expected, "\nActual output ", out, '\n')); 41 }; 42 43 auto check_exception = 44 []<class CharT, class... Args>( 45 [[maybe_unused]] std::string_view what, 46 [[maybe_unused]] std::basic_string_view<CharT> fmt, 47 [[maybe_unused]] Args&&... args) { 48 TEST_VALIDATE_EXCEPTION( 49 std::format_error, 50 [&]([[maybe_unused]] const std::format_error& e) { 51 TEST_LIBCPP_REQUIRE( 52 e.what() == what, 53 TEST_WRITE_CONCATENATED( 54 "\nFormat string ", fmt, "\nExpected exception ", what, "\nActual exception ", e.what(), '\n')); 55 }, 56 TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...))); 57 }; 58 59 template <class CharT> 60 void test() { 61 // 1, 2, 3, 4 code unit UTF-8 transitions 62 check(SV("\u000042\u0000"), SV("{:\u0000^4}"), 42); 63 check(SV("\u007f42\u007f"), SV("{:\u007f^4}"), 42); 64 check(SV("\u008042\u0080"), SV("{:\u0080^4}"), 42); 65 check(SV("\u07ff42\u07ff"), SV("{:\u07ff^4}"), 42); 66 check(SV("\u080042\u0800"), SV("{:\u0800^4}"), 42); 67 check(SV("\uffff42\uffff"), SV("{:\uffff^4}"), 42); 68 check(SV("\U0010000042\U00100000"), SV("{:\U00100000^4}"), 42); 69 check(SV("\U0010ffff42\U0010ffff"), SV("{:\U0010ffff^4}"), 42); 70 71 // Examples of P2572R1 72 check(SV("x"), SV("{:^6}"), SV("x")); 73 check(SV(""), SV("{:*^6}"), SV("")); 74 check(SV("12345678"), SV("{:*>6}"), SV("12345678")); 75 76 // Invalid Unicode Scalar Values 77 if constexpr (std::same_as<CharT, char>) { 78 check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xa0\x80^}"), 42); // U+D800 79 check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xa0\xbf^}"), 42); // U+DBFF 80 check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xbf\x80^}"), 42); // U+DC00 81 check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xbf\xbf^}"), 42); // U+DFFF 82 83 check_exception( 84 "The format specifier contains malformed Unicode characters", SV("{:\xf4\x90\x80\x80^}"), 42); // U+110000 85 check_exception( 86 "The format specifier contains malformed Unicode characters", SV("{:\xf4\x90\xbf\xbf^}"), 42); // U+11FFFF 87 88 check_exception("The format specifier contains malformed Unicode characters", 89 SV("{:\x80^}"), 90 42); // Trailing code unit with no leading one. 91 check_exception("The format specifier contains malformed Unicode characters", 92 SV("{:\xc0^}"), 93 42); // Missing trailing code unit. 94 check_exception("The format specifier contains malformed Unicode characters", 95 SV("{:\xe0\x80^}"), 96 42); // Missing trailing code unit. 97 check_exception("The format specifier contains malformed Unicode characters", 98 SV("{:\xf0\x80^}"), 99 42); // Missing two trailing code units. 100 check_exception("The format specifier contains malformed Unicode characters", 101 SV("{:\xf0\x80\x80^}"), 102 42); // Missing trailing code unit. 103 104 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 105 } else { 106 # ifdef TEST_SHORT_WCHAR 107 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xd800^}"}, 42); 108 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdbff^}"}, 42); 109 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdc00^}"}, 42); 110 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xddff^}"}, 42); 111 112 check_exception("The format specifier contains malformed Unicode characters", 113 std::wstring_view{L"{:\xdc00\xd800^}"}, 114 42); // Reverted surrogates. 115 116 # else // TEST_SHORT_WCHAR 117 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xd800^}"}, 42); 118 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdbff^}"}, 42); 119 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdc00^}"}, 42); 120 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xddff^}"}, 42); 121 122 check_exception( 123 "The format specifier should consume the input or end with a '}'", std::wstring_view{L"{:\xdc00\xd800^}"}, 42); 124 125 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x00110000^}"}, 42); 126 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x0011ffff^}"}, 42); 127 # endif // TEST_SHORT_WCHAR 128 #endif // TEST_HAS_NO_WIDE_CHARACTERS 129 } 130 } 131 132 int main(int, char**) { 133 test<char>(); 134 135 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 136 test<wchar_t>(); 137 #endif 138 139 return 0; 140 } 141