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
35auto 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
43auto 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
59template <class CharT>
60void 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
132int 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

source code of libcxx/test/std/utilities/format/format.functions/fill.unicode.pass.cpp