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

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