File: fill.unicode.pass.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,998,492 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (139 lines) | stat: -rw-r--r-- 6,359 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//===----------------------------------------------------------------------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME

// This version runs the test when the platform has Unicode support.
// UNSUPPORTED: libcpp-has-no-unicode

// XFAIL: availability-fp_to_chars-missing

// <format>

// The paper
//   P2572R1 std::format fill character allowances
// adds support for Unicode Scalar Values as fill character.

#include <format>

#include "assert_macros.h"
#include "concat_macros.h"
#include "format.functions.common.h"
#include "make_string.h"
#include "string_literal.h"
#include "test_format_string.h"
#include "test_macros.h"

#define SV(S) MAKE_STRING_VIEW(CharT, S)

auto check = []<class CharT, class... Args>(
                 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
  std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...);
  TEST_REQUIRE(out == expected,
               TEST_WRITE_CONCATENATED(
                   "\nFormat string   ", fmt.get(), "\nExpected output ", expected, "\nActual output   ", out, '\n'));
};

auto check_exception =
    []<class CharT, class... Args>(
        [[maybe_unused]] std::string_view what,
        [[maybe_unused]] std::basic_string_view<CharT> fmt,
        [[maybe_unused]] Args&&... args) {
      TEST_VALIDATE_EXCEPTION(
          std::format_error,
          [&]([[maybe_unused]] const std::format_error& e) {
            TEST_LIBCPP_REQUIRE(
                e.what() == what,
                TEST_WRITE_CONCATENATED(
                    "\nFormat string   ", fmt, "\nExpected exception ", what, "\nActual exception   ", e.what(), '\n'));
          },
          TEST_IGNORE_NODISCARD std::vformat(fmt, std::make_format_args<context_t<CharT>>(args...)));
    };

template <class CharT>
void test() {
  // 1, 2, 3, 4 code unit UTF-8 transitions
  check(SV("\u000042\u0000"), SV("{:\u0000^4}"), 42);
  check(SV("\u007f42\u007f"), SV("{:\u007f^4}"), 42);
  check(SV("\u008042\u0080"), SV("{:\u0080^4}"), 42);
  check(SV("\u07ff42\u07ff"), SV("{:\u07ff^4}"), 42);
  check(SV("\u080042\u0800"), SV("{:\u0800^4}"), 42);
  check(SV("\uffff42\uffff"), SV("{:\uffff^4}"), 42);
  check(SV("\U0010000042\U00100000"), SV("{:\U00100000^4}"), 42);
  check(SV("\U0010ffff42\U0010ffff"), SV("{:\U0010ffff^4}"), 42);

  // Examples of P2572R1
  check(SV("🤡🤡x🤡🤡🤡"), SV("{:🤡^6}"), SV("x"));
  check(SV("🤡🤡🤡"), SV("{:*^6}"), SV("🤡🤡🤡"));
  check(SV("12345678"), SV("{:*>6}"), SV("12345678"));

  // Invalid Unicode Scalar Values
  if constexpr (std::same_as<CharT, char>) {
    check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xa0\x80^}"), 42); // U+D800
    check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xa0\xbf^}"), 42); // U+DBFF
    check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xbf\x80^}"), 42); // U+DC00
    check_exception("The format specifier contains malformed Unicode characters", SV("{:\xed\xbf\xbf^}"), 42); // U+DFFF

    check_exception(
        "The format specifier contains malformed Unicode characters", SV("{:\xf4\x90\x80\x80^}"), 42); // U+110000
    check_exception(
        "The format specifier contains malformed Unicode characters", SV("{:\xf4\x90\xbf\xbf^}"), 42); // U+11FFFF

    check_exception("The format specifier contains malformed Unicode characters",
                    SV("{:\x80^}"),
                    42); // Trailing code unit with no leading one.
    check_exception("The format specifier contains malformed Unicode characters",
                    SV("{:\xc0^}"),
                    42); // Missing trailing code unit.
    check_exception("The format specifier contains malformed Unicode characters",
                    SV("{:\xe0\x80^}"),
                    42); // Missing trailing code unit.
    check_exception("The format specifier contains malformed Unicode characters",
                    SV("{:\xf0\x80^}"),
                    42); // Missing two trailing code units.
    check_exception("The format specifier contains malformed Unicode characters",
                    SV("{:\xf0\x80\x80^}"),
                    42); // Missing trailing code unit.

#ifndef TEST_HAS_NO_WIDE_CHARACTERS
  } else {
#  ifdef TEST_SHORT_WCHAR
    check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xd800^}"}, 42);
    check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdbff^}"}, 42);
    check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdc00^}"}, 42);
    check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xddff^}"}, 42);

    check_exception("The format specifier contains malformed Unicode characters",
                    std::wstring_view{L"{:\xdc00\xd800^}"},
                    42); // Reverted surrogates.

#  else  // TEST_SHORT_WCHAR
    check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xd800^}"}, 42);
    check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdbff^}"}, 42);
    check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdc00^}"}, 42);
    check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xddff^}"}, 42);

    check_exception(
        "The format specifier should consume the input or end with a '}'", std::wstring_view{L"{:\xdc00\xd800^}"}, 42);

    check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x00110000^}"}, 42);
    check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x0011ffff^}"}, 42);
#  endif // TEST_SHORT_WCHAR
#endif   // TEST_HAS_NO_WIDE_CHARACTERS
  }
}

int main(int, char**) {
  test<char>();

#ifndef TEST_HAS_NO_WIDE_CHARACTERS
  test<wchar_t>();
#endif

  return 0;
}