| //===----------------------------------------------------------------------===// |
| // 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 |
| // ADDITIONAL_COMPILE_FLAGS: -fsigned-char |
| |
| // <format> |
| |
| // C++23 the formatter is a debug-enabled specialization. |
| // [format.formatter.spec]: |
| // Each header that declares the template `formatter` provides the following |
| // enabled specializations: |
| // template<> struct formatter<char, char>; |
| // template<> struct formatter<char, wchar_t>; |
| // template<> struct formatter<wchar_t, wchar_t>; |
| |
| // P2909R4 "Fix formatting of code units as integers (Dude, where’s my char?)" |
| // changed the behaviour of char (and wchar_t) when their underlying type is signed. |
| |
| #include <format> |
| #include <cassert> |
| #include <concepts> |
| #include <iterator> |
| #include <type_traits> |
| |
| #include "test_format_context.h" |
| #include "test_macros.h" |
| #include "make_string.h" |
| #include "assert_macros.h" |
| #include "concat_macros.h" |
| |
| #define STR(S) MAKE_STRING(CharT, S) |
| #define SV(S) MAKE_STRING_VIEW(CharT, S) |
| |
| template <class StringT, class StringViewT, class ArgumentT> |
| void test(StringT expected, StringViewT fmt, ArgumentT arg) { |
| using CharT = typename StringT::value_type; |
| auto parse_ctx = std::basic_format_parse_context<CharT>(fmt); |
| std::formatter<ArgumentT, CharT> formatter; |
| static_assert(std::semiregular<decltype(formatter)>); |
| |
| formatter.parse(parse_ctx); |
| |
| StringT result; |
| auto out = std::back_inserter(result); |
| using FormatCtxT = std::basic_format_context<decltype(out), CharT>; |
| |
| FormatCtxT format_ctx = test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg)); |
| formatter.format(arg, format_ctx); |
| TEST_REQUIRE(result == expected, |
| TEST_WRITE_CONCATENATED( |
| "\nFormat string ", fmt, "\nExpected output ", expected, "\nActual output ", result, '\n')); |
| } |
| |
| template <class CharT> |
| void test() { |
| test(STR("\x00"), STR("}"), '\x00'); |
| test(STR("a"), STR("}"), 'a'); |
| test(STR("\x80"), STR("}"), '\x80'); |
| test(STR("\xff"), STR("}"), '\xff'); |
| |
| test(STR("\x00"), STR("c}"), '\x00'); |
| test(STR("a"), STR("c}"), 'a'); |
| test(STR("\x80"), STR("c}"), '\x80'); |
| test(STR("\xff"), STR("c}"), '\xff'); |
| |
| #if TEST_STD_VER > 20 |
| test(STR(R"('\u{0}')"), STR("?}"), '\x00'); |
| test(STR("'a'"), STR("?}"), 'a'); |
| if constexpr (std::same_as<CharT, char>) { |
| test(STR(R"('\x{80}')"), STR("?}"), '\x80'); |
| test(STR(R"('\x{ff}')"), STR("?}"), '\xff'); |
| } |
| # ifndef TEST_HAS_NO_WIDE_CHARACTERS |
| else { |
| test(STR(R"('\u{80}')"), STR("?}"), '\x80'); |
| test(STR("'\u00ff'"), STR("?}"), '\xff'); |
| } |
| # endif // TEST_HAS_NO_WIDE_CHARACTERS |
| #endif // TEST_STD_VER > 20 |
| |
| test(STR("10000000"), STR("b}"), char(-128)); |
| test(STR("11111111"), STR("b}"), char(-1)); |
| test(STR("0"), STR("b}"), char(0)); |
| test(STR("1"), STR("b}"), char(1)); |
| test(STR("1111111"), STR("b}"), char(127)); |
| |
| test(STR("10000000"), STR("B}"), char(-128)); |
| test(STR("11111111"), STR("B}"), char(-1)); |
| test(STR("0"), STR("B}"), char(0)); |
| test(STR("1"), STR("B}"), char(1)); |
| test(STR("1111111"), STR("B}"), char(127)); |
| |
| test(STR("128"), STR("d}"), char(-128)); |
| test(STR("255"), STR("d}"), char(-1)); |
| test(STR("0"), STR("d}"), char(0)); |
| test(STR("1"), STR("d}"), char(1)); |
| test(STR("127"), STR("d}"), char(127)); |
| |
| test(STR("200"), STR("o}"), char(-128)); |
| test(STR("377"), STR("o}"), char(-1)); |
| test(STR("0"), STR("o}"), char(0)); |
| test(STR("1"), STR("o}"), char(1)); |
| test(STR("177"), STR("o}"), char(127)); |
| |
| test(STR("80"), STR("x}"), char(-128)); |
| test(STR("ff"), STR("x}"), char(-1)); |
| test(STR("0"), STR("x}"), char(0)); |
| test(STR("1"), STR("x}"), char(1)); |
| test(STR("7f"), STR("x}"), char(127)); |
| |
| test(STR("80"), STR("X}"), char(-128)); |
| test(STR("FF"), STR("X}"), char(-1)); |
| test(STR("0"), STR("X}"), char(0)); |
| test(STR("1"), STR("X}"), char(1)); |
| test(STR("7F"), STR("X}"), char(127)); |
| } |
| |
| int main(int, char**) { |
| test<char>(); |
| #ifndef TEST_HAS_NO_WIDE_CHARACTERS |
| test<wchar_t>(); |
| #endif |
| |
| return 0; |
| } |