
The main change is to allow a UCS scalar value as fill character. Especially for char based formatting this increase the number of valid characters. Originally this was to be expected ABI breaking, however the current change does not seem to break the ABI. Implements - P2572 std::format() fill character allowances Depends on D144499 Reviewed By: ldionne, tahonermann, #libc Differential Revision: https://reviews.llvm.org/D144742
139 lines
6.1 KiB
C++
139 lines
6.1 KiB
C++
//===----------------------------------------------------------------------===//
|
|
// 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: libcpp-has-no-incomplete-format
|
|
// TODO FMT Evaluate gcc-12 status
|
|
|
|
// 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-spec contains malformed Unicode characters", SV("{:\xed\xa0\x80^}"), 42); // U+D800
|
|
check_exception("The format-spec contains malformed Unicode characters", SV("{:\xed\xa0\xbf^}"), 42); // U+DBFF
|
|
check_exception("The format-spec contains malformed Unicode characters", SV("{:\xed\xbf\x80^}"), 42); // U+DC00
|
|
check_exception("The format-spec contains malformed Unicode characters", SV("{:\xed\xbf\xbf^}"), 42); // U+DFFF
|
|
|
|
check_exception(
|
|
"The format-spec contains malformed Unicode characters", SV("{:\xf4\x90\x80\x80^}"), 42); // U+110000
|
|
check_exception(
|
|
"The format-spec contains malformed Unicode characters", SV("{:\xf4\x90\xbf\xbf^}"), 42); // U+11FFFF
|
|
|
|
check_exception("The format-spec contains malformed Unicode characters",
|
|
SV("{:\x80^}"),
|
|
42); // Trailing code unit with no leading one.
|
|
check_exception(
|
|
"The format-spec contains malformed Unicode characters", SV("{:\xc0^}"), 42); // Missing trailing code unit.
|
|
check_exception(
|
|
"The format-spec contains malformed Unicode characters", SV("{:\xe0\x80^}"), 42); // Missing trailing code unit.
|
|
check_exception("The format-spec contains malformed Unicode characters",
|
|
SV("{:\xf0\x80^}"),
|
|
42); // Missing two trailing code units.
|
|
check_exception("The format-spec 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-spec contains malformed Unicode characters", std::wstring_view{L"{:\xd800^}"}, 42);
|
|
check_exception("The format-spec contains malformed Unicode characters", std::wstring_view{L"{:\xdbff^}"}, 42);
|
|
check_exception("The format-spec contains malformed Unicode characters", std::wstring_view{L"{:\xdc00^}"}, 42);
|
|
check_exception("The format-spec contains malformed Unicode characters", std::wstring_view{L"{:\xddff^}"}, 42);
|
|
|
|
check_exception("The format-spec contains malformed Unicode characters",
|
|
std::wstring_view{L"{:\xdc00\xd800^}"},
|
|
42); // Reverted surrogates.
|
|
|
|
# else // TEST_SHORT_WCHAR
|
|
check_exception("The fill character contains an invalid value", std::wstring_view{L"{:\xd800^}"}, 42);
|
|
check_exception("The fill character contains an invalid value", std::wstring_view{L"{:\xdbff^}"}, 42);
|
|
check_exception("The fill character contains an invalid value", std::wstring_view{L"{:\xdc00^}"}, 42);
|
|
check_exception("The fill character contains an invalid value", std::wstring_view{L"{:\xddff^}"}, 42);
|
|
|
|
check_exception(
|
|
"The format-spec should consume the input or end with a '}'", std::wstring_view{L"{:\xdc00\xd800^}"}, 42);
|
|
|
|
check_exception("The fill character contains an invalid value", std::wstring_view{L"{:\x00110000^}"}, 42);
|
|
check_exception("The fill character 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;
|
|
}
|