xref: /llvm-project/libcxx/test/std/utilities/format/format.functions/fill.unicode.pass.cpp (revision 6a54dfbfe534276d644d7f9c027f0deeb748dd53)
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