151 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME11 12// This version runs the test when the platform has Unicode support.13// UNSUPPORTED: libcpp-has-no-unicode14 15// XFAIL: availability-fp_to_chars-missing16 17// <format>18 19// The paper20// P2572R1 std::format fill character allowances21// 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 transitions62 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 P2572R172 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 Values77 if constexpr (std::same_as<CharT, char>) {78 check_exception("The format specifier contains malformed Unicode characters",79 std::string_view{"{:\xed\xa0\x80^}"},80 42); // U+D80081 check_exception("The format specifier contains malformed Unicode characters",82 std::string_view{"{:\xed\xa0\xbf^}"},83 42); // U+DBFF84 check_exception("The format specifier contains malformed Unicode characters",85 std::string_view{"{:\xed\xbf\x80^}"},86 42); // U+DC0087 check_exception("The format specifier contains malformed Unicode characters",88 std::string_view{"{:\xed\xbf\xbf^}"},89 42); // U+DFFF90 91 check_exception("The format specifier contains malformed Unicode characters",92 std::string_view{"{:\xf4\x90\x80\x80^}"},93 42); // U+11000094 check_exception("The format specifier contains malformed Unicode characters",95 std::string_view{"{:\xf4\x90\xbf\xbf^}"},96 42); // U+11FFFF97 98 check_exception("The format specifier contains malformed Unicode characters",99 std::string_view{"{:\x80^}"},100 42); // Trailing code unit with no leading one.101 check_exception("The format specifier contains malformed Unicode characters",102 std::string_view{"{:\xc0^}"},103 42); // Missing trailing code unit.104 check_exception("The format specifier contains malformed Unicode characters",105 std::string_view{"{:\xe0\x80^}"},106 42); // Missing trailing code unit.107 check_exception("The format specifier contains malformed Unicode characters",108 std::string_view{"{:\xf0\x80^}"},109 42); // Missing two trailing code units.110 check_exception("The format specifier contains malformed Unicode characters",111 std::string_view{"{:\xf0\x80\x80^}"},112 42); // Missing trailing code unit.113 114#ifndef TEST_HAS_NO_WIDE_CHARACTERS115 } else {116# ifdef TEST_SHORT_WCHAR117 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xd800^}"}, 42);118 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdbff^}"}, 42);119 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xdc00^}"}, 42);120 check_exception("The format specifier contains malformed Unicode characters", std::wstring_view{L"{:\xddff^}"}, 42);121 122 check_exception("The format specifier contains malformed Unicode characters",123 std::wstring_view{L"{:\xdc00\xd800^}"},124 42); // Reverted surrogates.125 126# else // TEST_SHORT_WCHAR127 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xd800^}"}, 42);128 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdbff^}"}, 42);129 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xdc00^}"}, 42);130 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\xddff^}"}, 42);131 132 check_exception(133 "The format specifier should consume the input or end with a '}'", std::wstring_view{L"{:\xdc00\xd800^}"}, 42);134 135 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x00110000^}"}, 42);136 check_exception("The fill option contains an invalid value", std::wstring_view{L"{:\x0011ffff^}"}, 42);137# endif // TEST_SHORT_WCHAR138#endif // TEST_HAS_NO_WIDE_CHARACTERS139 }140}141 142int main(int, char**) {143 test<char>();144 145#ifndef TEST_HAS_NO_WIDE_CHARACTERS146 test<wchar_t>();147#endif148 149 return 0;150}151