1 //===----------------------------------------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 // UNSUPPORTED: c++03, c++11, c++14, c++17
9 // UNSUPPORTED: no-localization
10 // UNSUPPORTED: libcpp-has-no-incomplete-format
11 // TODO FMT Evaluate gcc-12 status
12 // UNSUPPORTED: gcc-12
13 // TODO FMT Investigate AppleClang ICE
14 // UNSUPPORTED: apple-clang-13
15
16 // <format>
17
18 // template<class Out>
19 // Out vformat_to(Out out, const locale& loc, string_view fmt,
20 // format_args args);
21 // template<class Out>
22 // Out vformat_to(Out out, const locale& loc, wstring_view fmt,
23 // wformat_args args);
24
25 #include <format>
26 #include <algorithm>
27 #include <cassert>
28 #include <list>
29 #include <vector>
30
31 #include "test_macros.h"
32 #include "format_tests.h"
33 #include "string_literal.h"
34
35 auto test = []<string_literal fmt, class CharT, class... Args>(std::basic_string_view<CharT> expected,
36 const Args&... args) constexpr {
37 {
38 std::basic_string<CharT> out(expected.size(), CharT(' '));
39 auto it = std::vformat_to(out.begin(), std::locale(), fmt.template sv<CharT>(),
40 std::make_format_args<context_t<CharT>>(args...));
41 assert(it == out.end());
42 assert(out == expected);
43 }
44 {
45 std::list<CharT> out;
46 std::vformat_to(std::back_inserter(out), std::locale(), fmt.template sv<CharT>(),
47 std::make_format_args<context_t<CharT>>(args...));
48 assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
49 }
50 {
51 std::vector<CharT> out;
52 std::vformat_to(std::back_inserter(out), std::locale(), fmt.template sv<CharT>(),
53 std::make_format_args<context_t<CharT>>(args...));
54 assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
55 }
56 {
57 assert(expected.size() < 4096 && "Update the size of the buffer.");
58 CharT out[4096];
59 CharT* it =
60 std::vformat_to(out, std::locale(), fmt.template sv<CharT>(), std::make_format_args<context_t<CharT>>(args...));
61 assert(std::distance(out, it) == int(expected.size()));
62 // Convert to std::string since output contains '\0' for boolean tests.
63 assert(std::basic_string<CharT>(out, it) == expected);
64 }
65 };
66
67 auto test_exception = []<class CharT, class... Args>(std::string_view what, std::basic_string_view<CharT> fmt,
68 const Args&... args) {
69 #ifndef TEST_HAS_NO_EXCEPTIONS
70 try {
71 std::basic_string<CharT> out;
72 std::vformat_to(std::back_inserter(out), std::locale(), fmt, std::make_format_args<context_t<CharT>>(args...));
73 assert(false);
74 } catch ([[maybe_unused]] const std::format_error& e) {
75 LIBCPP_ASSERT(e.what() == what);
76 return;
77 }
78 assert(false);
79 #endif
80 (void)what;
81 (void)fmt;
82 (void)sizeof...(args);
83 };
84
main(int,char **)85 int main(int, char**) {
86 format_tests<char>(test, test_exception);
87
88 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
89 format_tests_char_to_wchar_t(test);
90 format_tests<wchar_t>(test, test_exception);
91 #endif
92
93 return 0;
94 }
95