xref: /freebsd/contrib/llvm-project/libcxx/include/format (revision 4824e7fd18a1223177218d4aec1b3c6c5c4a444e)
1fe6060f1SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric//
4fe6060f1SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric//
8fe6060f1SDimitry Andric//===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric
10fe6060f1SDimitry Andric#ifndef _LIBCPP_FORMAT
11fe6060f1SDimitry Andric#define _LIBCPP_FORMAT
12fe6060f1SDimitry Andric
13fe6060f1SDimitry Andric/*
14fe6060f1SDimitry Andric
15fe6060f1SDimitry Andricnamespace std {
16349cc55cSDimitry Andric  // [format.context], class template basic_format_context
17349cc55cSDimitry Andric  template<class Out, class charT>
18349cc55cSDimitry Andric  class basic_format_context {
19349cc55cSDimitry Andric    basic_format_args<basic_format_context> args_;      // exposition only
20349cc55cSDimitry Andric    Out out_;                                           // exposition only
21349cc55cSDimitry Andric
22349cc55cSDimitry Andric  public:
23349cc55cSDimitry Andric    using iterator = Out;
24349cc55cSDimitry Andric    using char_type = charT;
25349cc55cSDimitry Andric    template<class T> using formatter_type = formatter<T, charT>;
26349cc55cSDimitry Andric
27349cc55cSDimitry Andric    basic_format_arg<basic_format_context> arg(size_t id) const;
28349cc55cSDimitry Andric    std::locale locale();
29349cc55cSDimitry Andric
30349cc55cSDimitry Andric    iterator out();
31349cc55cSDimitry Andric    void advance_to(iterator it);
32349cc55cSDimitry Andric  };
33349cc55cSDimitry Andric  using format_context = basic_format_context<unspecified, char>;
34349cc55cSDimitry Andric  using wformat_context = basic_format_context<unspecified, wchar_t>;
35349cc55cSDimitry Andric
36349cc55cSDimitry Andric  // [format.args], class template basic_format_args
37349cc55cSDimitry Andric  template<class Context>
38349cc55cSDimitry Andric  class basic_format_args {
39349cc55cSDimitry Andric    size_t size_;                               // exposition only
40349cc55cSDimitry Andric    const basic_format_arg<Context>* data_;     // exposition only
41349cc55cSDimitry Andric
42349cc55cSDimitry Andric  public:
43349cc55cSDimitry Andric    basic_format_args() noexcept;
44349cc55cSDimitry Andric
45349cc55cSDimitry Andric    template<class... Args>
46349cc55cSDimitry Andric      basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
47349cc55cSDimitry Andric
48349cc55cSDimitry Andric    basic_format_arg<Context> get(size_t i) const noexcept;
49349cc55cSDimitry Andric  };
50349cc55cSDimitry Andric  using format_args = basic_format_args<format_context>;
51349cc55cSDimitry Andric  using wformat_args = basic_format_args<wformat_context>;
52349cc55cSDimitry Andric
53349cc55cSDimitry Andric
54349cc55cSDimitry Andric  // [format.functions], formatting functions
55349cc55cSDimitry Andric  template<class... Args>
56349cc55cSDimitry Andric    string format(string_view fmt, const Args&... args);
57349cc55cSDimitry Andric  template<class... Args>
58349cc55cSDimitry Andric    wstring format(wstring_view fmt, const Args&... args);
59349cc55cSDimitry Andric  template<class... Args>
60349cc55cSDimitry Andric    string format(const locale& loc, string_view fmt, const Args&... args);
61349cc55cSDimitry Andric  template<class... Args>
62349cc55cSDimitry Andric    wstring format(const locale& loc, wstring_view fmt, const Args&... args);
63349cc55cSDimitry Andric
64349cc55cSDimitry Andric  string vformat(string_view fmt, format_args args);
65349cc55cSDimitry Andric  wstring vformat(wstring_view fmt, wformat_args args);
66349cc55cSDimitry Andric  string vformat(const locale& loc, string_view fmt, format_args args);
67349cc55cSDimitry Andric  wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
68349cc55cSDimitry Andric
69349cc55cSDimitry Andric  template<class Out, class... Args>
70349cc55cSDimitry Andric    Out format_to(Out out, string_view fmt, const Args&... args);
71349cc55cSDimitry Andric  template<class Out, class... Args>
72349cc55cSDimitry Andric    Out format_to(Out out, wstring_view fmt, const Args&... args);
73349cc55cSDimitry Andric  template<class Out, class... Args>
74349cc55cSDimitry Andric    Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
75349cc55cSDimitry Andric  template<class Out, class... Args>
76349cc55cSDimitry Andric    Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
77349cc55cSDimitry Andric
78349cc55cSDimitry Andric  template<class Out>
79*4824e7fdSDimitry Andric    Out vformat_to(Out out, string_view fmt, format_args args);
80349cc55cSDimitry Andric  template<class Out>
81*4824e7fdSDimitry Andric    Out vformat_to(Out out, wstring_view fmt, wformat_args args);
82349cc55cSDimitry Andric  template<class Out>
83349cc55cSDimitry Andric    Out vformat_to(Out out, const locale& loc, string_view fmt,
84*4824e7fdSDimitry Andric                   format_args char> args);
85349cc55cSDimitry Andric  template<class Out>
86349cc55cSDimitry Andric    Out vformat_to(Out out, const locale& loc, wstring_view fmt,
87*4824e7fdSDimitry Andric                   wformat_args args);
88349cc55cSDimitry Andric
89349cc55cSDimitry Andric  template<class Out> struct format_to_n_result {
90349cc55cSDimitry Andric    Out out;
91349cc55cSDimitry Andric    iter_difference_t<Out> size;
92349cc55cSDimitry Andric  };
93349cc55cSDimitry Andric
94349cc55cSDimitry Andric template<class Out, class... Args>
95349cc55cSDimitry Andric    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
96349cc55cSDimitry Andric                                        string_view fmt, const Args&... args);
97349cc55cSDimitry Andric  template<class Out, class... Args>
98349cc55cSDimitry Andric    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
99349cc55cSDimitry Andric                                        wstring_view fmt, const Args&... args);
100349cc55cSDimitry Andric  template<class Out, class... Args>
101349cc55cSDimitry Andric    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
102349cc55cSDimitry Andric                                        const locale& loc, string_view fmt,
103349cc55cSDimitry Andric                                        const Args&... args);
104349cc55cSDimitry Andric  template<class Out, class... Args>
105349cc55cSDimitry Andric    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
106349cc55cSDimitry Andric                                        const locale& loc, wstring_view fmt,
107349cc55cSDimitry Andric                                        const Args&... args);
108349cc55cSDimitry Andric
109349cc55cSDimitry Andric  template<class... Args>
110349cc55cSDimitry Andric    size_t formatted_size(string_view fmt, const Args&... args);
111349cc55cSDimitry Andric  template<class... Args>
112349cc55cSDimitry Andric    size_t formatted_size(wstring_view fmt, const Args&... args);
113349cc55cSDimitry Andric  template<class... Args>
114349cc55cSDimitry Andric    size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
115349cc55cSDimitry Andric  template<class... Args>
116349cc55cSDimitry Andric    size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
117349cc55cSDimitry Andric
118349cc55cSDimitry Andric  // [format.formatter], formatter
119349cc55cSDimitry Andric  template<> struct formatter<char, char>;
120349cc55cSDimitry Andric  template<> struct formatter<char, wchar_t>;
121349cc55cSDimitry Andric  template<> struct formatter<wchar_t, wchar_t>;
122349cc55cSDimitry Andric
123349cc55cSDimitry Andric  template<> struct formatter<charT*, charT>;
124349cc55cSDimitry Andric  template<> struct formatter<const charT*, charT>;
125349cc55cSDimitry Andric  template<size_t N> struct formatter<const charT[N], charT>;
126349cc55cSDimitry Andric  template<class traits, class Allocator>
127349cc55cSDimitry Andric    struct formatter<basic_string<charT, traits, Allocator>, charT>;
128349cc55cSDimitry Andric  template<class traits>
129349cc55cSDimitry Andric    struct formatter<basic_string_view<charT, traits>, charT>;
130349cc55cSDimitry Andric
131349cc55cSDimitry Andric  // [format.parse.ctx], class template basic_format_parse_context
132349cc55cSDimitry Andric  template<class charT>
133349cc55cSDimitry Andric  class basic_format_parse_context {
134349cc55cSDimitry Andric  public:
135349cc55cSDimitry Andric    using char_type = charT;
136349cc55cSDimitry Andric    using const_iterator = typename basic_string_view<charT>::const_iterator;
137349cc55cSDimitry Andric    using iterator = const_iterator;
138349cc55cSDimitry Andric
139349cc55cSDimitry Andric  private:
140349cc55cSDimitry Andric    iterator begin_;                                    // exposition only
141349cc55cSDimitry Andric    iterator end_;                                      // exposition only
142349cc55cSDimitry Andric    enum indexing { unknown, manual, automatic };       // exposition only
143349cc55cSDimitry Andric    indexing indexing_;                                 // exposition only
144349cc55cSDimitry Andric    size_t next_arg_id_;                                // exposition only
145349cc55cSDimitry Andric    size_t num_args_;                                   // exposition only
146349cc55cSDimitry Andric
147349cc55cSDimitry Andric  public:
148349cc55cSDimitry Andric    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
149349cc55cSDimitry Andric                                                  size_t num_args = 0) noexcept;
150349cc55cSDimitry Andric    basic_format_parse_context(const basic_format_parse_context&) = delete;
151349cc55cSDimitry Andric    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
152349cc55cSDimitry Andric
153349cc55cSDimitry Andric    constexpr const_iterator begin() const noexcept;
154349cc55cSDimitry Andric    constexpr const_iterator end() const noexcept;
155349cc55cSDimitry Andric    constexpr void advance_to(const_iterator it);
156349cc55cSDimitry Andric
157349cc55cSDimitry Andric    constexpr size_t next_arg_id();
158349cc55cSDimitry Andric    constexpr void check_arg_id(size_t id);
159349cc55cSDimitry Andric  };
160349cc55cSDimitry Andric  using format_parse_context = basic_format_parse_context<char>;
161349cc55cSDimitry Andric  using wformat_parse_context = basic_format_parse_context<wchar_t>;
162349cc55cSDimitry Andric
163349cc55cSDimitry Andric  // [format.arguments], arguments
164349cc55cSDimitry Andric  // [format.arg], class template basic_format_arg
165349cc55cSDimitry Andric  template<class Context>
166349cc55cSDimitry Andric  class basic_format_arg {
167349cc55cSDimitry Andric  public:
168349cc55cSDimitry Andric    class handle;
169349cc55cSDimitry Andric
170349cc55cSDimitry Andric  private:
171349cc55cSDimitry Andric    using char_type = typename Context::char_type;                              // exposition only
172349cc55cSDimitry Andric
173349cc55cSDimitry Andric    variant<monostate, bool, char_type,
174349cc55cSDimitry Andric            int, unsigned int, long long int, unsigned long long int,
175349cc55cSDimitry Andric            float, double, long double,
176349cc55cSDimitry Andric            const char_type*, basic_string_view<char_type>,
177349cc55cSDimitry Andric            const void*, handle> value;                                         // exposition only
178349cc55cSDimitry Andric
179349cc55cSDimitry Andric    template<class T> explicit basic_format_arg(const T& v) noexcept;           // exposition only
180349cc55cSDimitry Andric    explicit basic_format_arg(float n) noexcept;                                // exposition only
181349cc55cSDimitry Andric    explicit basic_format_arg(double n) noexcept;                               // exposition only
182349cc55cSDimitry Andric    explicit basic_format_arg(long double n) noexcept;                          // exposition only
183349cc55cSDimitry Andric    explicit basic_format_arg(const char_type* s);                              // exposition only
184349cc55cSDimitry Andric
185349cc55cSDimitry Andric    template<class traits>
186349cc55cSDimitry Andric      explicit basic_format_arg(
187349cc55cSDimitry Andric        basic_string_view<char_type, traits> s) noexcept;                       // exposition only
188349cc55cSDimitry Andric
189349cc55cSDimitry Andric    template<class traits, class Allocator>
190349cc55cSDimitry Andric      explicit basic_format_arg(
191349cc55cSDimitry Andric        const basic_string<char_type, traits, Allocator>& s) noexcept;          // exposition only
192349cc55cSDimitry Andric
193349cc55cSDimitry Andric    explicit basic_format_arg(nullptr_t) noexcept;                              // exposition only
194349cc55cSDimitry Andric
195349cc55cSDimitry Andric    template<class T>
196349cc55cSDimitry Andric      explicit basic_format_arg(const T* p) noexcept;                           // exposition only
197349cc55cSDimitry Andric
198349cc55cSDimitry Andric  public:
199349cc55cSDimitry Andric    basic_format_arg() noexcept;
200349cc55cSDimitry Andric
201349cc55cSDimitry Andric    explicit operator bool() const noexcept;
202349cc55cSDimitry Andric  };
203349cc55cSDimitry Andric
204349cc55cSDimitry Andric  template<class Visitor, class Context>
205349cc55cSDimitry Andric    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
206349cc55cSDimitry Andric
207349cc55cSDimitry Andric  // [format.arg.store], class template format-arg-store
208349cc55cSDimitry Andric  template<class Context, class... Args>
209349cc55cSDimitry Andric  struct format-arg-store {      // exposition only
210349cc55cSDimitry Andric    array<basic_format_arg<Context>, sizeof...(Args)> args;
211349cc55cSDimitry Andric  };
212349cc55cSDimitry Andric
213349cc55cSDimitry Andric  template<class Context = format_context, class... Args>
214349cc55cSDimitry Andric    format-arg-store<Context, Args...>
215349cc55cSDimitry Andric      make_format_args(const Args&... args);
216349cc55cSDimitry Andric  template<class... Args>
217349cc55cSDimitry Andric    format-arg-store<wformat_context, Args...>
218349cc55cSDimitry Andric      make_wformat_args(const Args&... args);
219349cc55cSDimitry Andric
220fe6060f1SDimitry Andric  // [format.error], class format_error
221fe6060f1SDimitry Andric  class format_error : public runtime_error {
222fe6060f1SDimitry Andric  public:
223fe6060f1SDimitry Andric    explicit format_error(const string& what_arg);
224fe6060f1SDimitry Andric    explicit format_error(const char* what_arg);
225fe6060f1SDimitry Andric  };
226fe6060f1SDimitry Andric
227fe6060f1SDimitry Andric  // [format.parse.ctx], class template basic_format_parse_context
228fe6060f1SDimitry Andric  template<class charT>
229fe6060f1SDimitry Andric  class basic_format_parse_context {
230fe6060f1SDimitry Andric  public:
231fe6060f1SDimitry Andric    using char_type = charT;
232fe6060f1SDimitry Andric    using const_iterator = typename basic_string_view<charT>::const_iterator;
233fe6060f1SDimitry Andric    using iterator = const_iterator;
234fe6060f1SDimitry Andric
235fe6060f1SDimitry Andric  private:
236fe6060f1SDimitry Andric    iterator begin_;                                    // exposition only
237fe6060f1SDimitry Andric    iterator end_;                                      // exposition only
238fe6060f1SDimitry Andric    enum indexing { unknown, manual, automatic };       // exposition only
239fe6060f1SDimitry Andric    indexing indexing_;                                 // exposition only
240fe6060f1SDimitry Andric    size_t next_arg_id_;                                // exposition only
241fe6060f1SDimitry Andric    size_t num_args_;                                   // exposition only
242fe6060f1SDimitry Andric
243fe6060f1SDimitry Andric  public:
244fe6060f1SDimitry Andric    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
245fe6060f1SDimitry Andric                                                  size_t num_args = 0) noexcept;
246fe6060f1SDimitry Andric    basic_format_parse_context(const basic_format_parse_context&) = delete;
247fe6060f1SDimitry Andric    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
248fe6060f1SDimitry Andric
249fe6060f1SDimitry Andric    constexpr const_iterator begin() const noexcept;
250fe6060f1SDimitry Andric    constexpr const_iterator end() const noexcept;
251fe6060f1SDimitry Andric    constexpr void advance_to(const_iterator it);
252fe6060f1SDimitry Andric
253fe6060f1SDimitry Andric    constexpr size_t next_arg_id();
254fe6060f1SDimitry Andric    constexpr void check_arg_id(size_t id);
255fe6060f1SDimitry Andric  };
256fe6060f1SDimitry Andric  using format_parse_context = basic_format_parse_context<char>;
257fe6060f1SDimitry Andric  using wformat_parse_context = basic_format_parse_context<wchar_t>;
258fe6060f1SDimitry Andric}
259fe6060f1SDimitry Andric
260fe6060f1SDimitry Andric*/
261fe6060f1SDimitry Andric
262349cc55cSDimitry Andric// Make sure all feature-test macros are available.
2636e75b2fbSDimitry Andric#include <version>
264349cc55cSDimitry Andric// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
2656e75b2fbSDimitry Andric#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
2666e75b2fbSDimitry Andric
267fe6060f1SDimitry Andric#include <__config>
268349cc55cSDimitry Andric#include <__debug>
269349cc55cSDimitry Andric#include <__format/format_arg.h>
270349cc55cSDimitry Andric#include <__format/format_args.h>
271349cc55cSDimitry Andric#include <__format/format_context.h>
272fe6060f1SDimitry Andric#include <__format/format_error.h>
273349cc55cSDimitry Andric#include <__format/format_fwd.h>
274fe6060f1SDimitry Andric#include <__format/format_parse_context.h>
275349cc55cSDimitry Andric#include <__format/format_string.h>
276349cc55cSDimitry Andric#include <__format/format_to_n_result.h>
277349cc55cSDimitry Andric#include <__format/formatter.h>
278349cc55cSDimitry Andric#include <__format/formatter_bool.h>
279349cc55cSDimitry Andric#include <__format/formatter_char.h>
280349cc55cSDimitry Andric#include <__format/formatter_integer.h>
281349cc55cSDimitry Andric#include <__format/formatter_string.h>
282349cc55cSDimitry Andric#include <__format/parser_std_format_spec.h>
283349cc55cSDimitry Andric#include <__variant/monostate.h>
284349cc55cSDimitry Andric#include <array>
285349cc55cSDimitry Andric#include <concepts>
286349cc55cSDimitry Andric#include <string>
287349cc55cSDimitry Andric#include <string_view>
288349cc55cSDimitry Andric#include <type_traits>
289349cc55cSDimitry Andric
290349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION
291349cc55cSDimitry Andric#include <locale>
292349cc55cSDimitry Andric#endif
293fe6060f1SDimitry Andric
294fe6060f1SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
295fe6060f1SDimitry Andric#pragma GCC system_header
296fe6060f1SDimitry Andric#endif
297fe6060f1SDimitry Andric
298fe6060f1SDimitry Andric_LIBCPP_PUSH_MACROS
299fe6060f1SDimitry Andric#include <__undef_macros>
300fe6060f1SDimitry Andric
301fe6060f1SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
302fe6060f1SDimitry Andric
303fe6060f1SDimitry Andric#if _LIBCPP_STD_VER > 17
304fe6060f1SDimitry Andric
305349cc55cSDimitry Andric// TODO FMT Remove this once we require compilers with proper C++20 support.
306349cc55cSDimitry Andric// If the compiler has no concepts support, the format header will be disabled.
307349cc55cSDimitry Andric// Without concepts support enable_if needs to be used and that too much effort
308349cc55cSDimitry Andric// to support compilers with partial C++20 support.
309349cc55cSDimitry Andric#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
310349cc55cSDimitry Andric
311349cc55cSDimitry Andric// TODO FMT Move the implementation in this file to its own granular headers.
312349cc55cSDimitry Andric
313349cc55cSDimitry Andric// TODO FMT Evaluate which templates should be external templates. This
314349cc55cSDimitry Andric// improves the efficiency of the header. However since the header is still
315349cc55cSDimitry Andric// under heavy development and not all classes are stable it makes no sense
316349cc55cSDimitry Andric// to do this optimization now.
317349cc55cSDimitry Andric
318349cc55cSDimitry Andricusing format_args = basic_format_args<format_context>;
319349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
320349cc55cSDimitry Andricusing wformat_args = basic_format_args<wformat_context>;
321349cc55cSDimitry Andric#endif
322349cc55cSDimitry Andric
323349cc55cSDimitry Andrictemplate <class _Context, class... _Args>
324349cc55cSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS __format_arg_store {
325349cc55cSDimitry Andric  // TODO FMT Use a built-in array.
326349cc55cSDimitry Andric  array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
327349cc55cSDimitry Andric};
328349cc55cSDimitry Andric
329349cc55cSDimitry Andrictemplate <class _Context = format_context, class... _Args>
330349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
331349cc55cSDimitry Andricmake_format_args(const _Args&... __args) {
332349cc55cSDimitry Andric  return {basic_format_arg<_Context>(__args)...};
333349cc55cSDimitry Andric}
334349cc55cSDimitry Andric
335349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
336349cc55cSDimitry Andrictemplate <class... _Args>
337349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
338349cc55cSDimitry Andricmake_wformat_args(const _Args&... __args) {
339349cc55cSDimitry Andric  return _VSTD::make_format_args<wformat_context>(__args...);
340349cc55cSDimitry Andric}
341349cc55cSDimitry Andric#endif
342349cc55cSDimitry Andric
343349cc55cSDimitry Andricnamespace __format {
344349cc55cSDimitry Andric
345349cc55cSDimitry Andrictemplate <class _CharT, class _ParseCtx, class _Ctx>
346349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI const _CharT*
347349cc55cSDimitry Andric__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
348349cc55cSDimitry Andric                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
349349cc55cSDimitry Andric  __format::__parse_number_result __r =
350349cc55cSDimitry Andric      __format::__parse_arg_id(__begin, __end, __parse_ctx);
351349cc55cSDimitry Andric
352349cc55cSDimitry Andric  switch (*__r.__ptr) {
353349cc55cSDimitry Andric  case _CharT(':'):
354349cc55cSDimitry Andric    // The arg-id has a format-specifier, advance the input to the format-spec.
355349cc55cSDimitry Andric    __parse_ctx.advance_to(__r.__ptr + 1);
356349cc55cSDimitry Andric    break;
357349cc55cSDimitry Andric  case _CharT('}'):
358349cc55cSDimitry Andric    // The arg-id has no format-specifier.
359349cc55cSDimitry Andric    __parse_ctx.advance_to(__r.__ptr);
360349cc55cSDimitry Andric    break;
361349cc55cSDimitry Andric  default:
362349cc55cSDimitry Andric    __throw_format_error(
363349cc55cSDimitry Andric        "The replacement field arg-id should terminate at a ':' or '}'");
364349cc55cSDimitry Andric  }
365349cc55cSDimitry Andric
366349cc55cSDimitry Andric  _VSTD::visit_format_arg(
367349cc55cSDimitry Andric      [&](auto __arg) {
368349cc55cSDimitry Andric        if constexpr (same_as<decltype(__arg), monostate>)
369349cc55cSDimitry Andric          __throw_format_error("Argument index out of bounds");
370349cc55cSDimitry Andric        else {
371349cc55cSDimitry Andric          formatter<decltype(__arg), _CharT> __formatter;
372349cc55cSDimitry Andric          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
373349cc55cSDimitry Andric          __ctx.advance_to(__formatter.format(__arg, __ctx));
374349cc55cSDimitry Andric        }
375349cc55cSDimitry Andric      },
376349cc55cSDimitry Andric      __ctx.arg(__r.__value));
377349cc55cSDimitry Andric
378349cc55cSDimitry Andric  __begin = __parse_ctx.begin();
379349cc55cSDimitry Andric  if (__begin == __end || *__begin != _CharT('}'))
380349cc55cSDimitry Andric    __throw_format_error("The replacement field misses a terminating '}'");
381349cc55cSDimitry Andric
382349cc55cSDimitry Andric  return ++__begin;
383349cc55cSDimitry Andric}
384349cc55cSDimitry Andric
385349cc55cSDimitry Andrictemplate <class _ParseCtx, class _Ctx>
386349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
387349cc55cSDimitry Andric__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
388349cc55cSDimitry Andric  using _CharT = typename _ParseCtx::char_type;
389349cc55cSDimitry Andric  static_assert(same_as<typename _Ctx::char_type, _CharT>);
390349cc55cSDimitry Andric
391349cc55cSDimitry Andric  const _CharT* __begin = __parse_ctx.begin();
392349cc55cSDimitry Andric  const _CharT* __end = __parse_ctx.end();
393349cc55cSDimitry Andric  typename _Ctx::iterator __out_it = __ctx.out();
394349cc55cSDimitry Andric  while (__begin != __end) {
395349cc55cSDimitry Andric    switch (*__begin) {
396349cc55cSDimitry Andric    case _CharT('{'):
397349cc55cSDimitry Andric      ++__begin;
398349cc55cSDimitry Andric      if (__begin == __end)
399349cc55cSDimitry Andric        __throw_format_error("The format string terminates at a '{'");
400349cc55cSDimitry Andric
401349cc55cSDimitry Andric      if (*__begin != _CharT('{')) [[likely]] {
402349cc55cSDimitry Andric        __ctx.advance_to(_VSTD::move(__out_it));
403349cc55cSDimitry Andric        __begin =
404349cc55cSDimitry Andric            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
405349cc55cSDimitry Andric        __out_it = __ctx.out();
406349cc55cSDimitry Andric
407349cc55cSDimitry Andric        // The output is written and __begin points to the next character. So
408349cc55cSDimitry Andric        // start the next iteration.
409349cc55cSDimitry Andric        continue;
410349cc55cSDimitry Andric      }
411349cc55cSDimitry Andric      // The string is an escape character.
412349cc55cSDimitry Andric      break;
413349cc55cSDimitry Andric
414349cc55cSDimitry Andric    case _CharT('}'):
415349cc55cSDimitry Andric      ++__begin;
416349cc55cSDimitry Andric      if (__begin == __end || *__begin != _CharT('}'))
417349cc55cSDimitry Andric        __throw_format_error(
418349cc55cSDimitry Andric            "The format string contains an invalid escape sequence");
419349cc55cSDimitry Andric
420349cc55cSDimitry Andric      break;
421349cc55cSDimitry Andric    }
422349cc55cSDimitry Andric
423349cc55cSDimitry Andric    // Copy the character to the output verbatim.
424349cc55cSDimitry Andric    *__out_it++ = *__begin++;
425349cc55cSDimitry Andric  }
426349cc55cSDimitry Andric  return __out_it;
427349cc55cSDimitry Andric}
428349cc55cSDimitry Andric
429349cc55cSDimitry Andric} // namespace __format
430349cc55cSDimitry Andric
431*4824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt>
432349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
433*4824e7fdSDimitry Andric    __vformat_to(
434*4824e7fdSDimitry Andric        _OutIt __out_it, basic_string_view<_CharT> __fmt,
435*4824e7fdSDimitry Andric        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
436*4824e7fdSDimitry Andric  if constexpr (same_as<_OutIt, _FormatOutIt>)
437*4824e7fdSDimitry Andric    return _VSTD::__format::__vformat_to(
438349cc55cSDimitry Andric        basic_format_parse_context{__fmt, __args.__size()},
439349cc55cSDimitry Andric        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
440*4824e7fdSDimitry Andric  else {
441*4824e7fdSDimitry Andric    basic_string<_CharT> __str;
442*4824e7fdSDimitry Andric    _VSTD::__format::__vformat_to(
443*4824e7fdSDimitry Andric        basic_format_parse_context{__fmt, __args.__size()},
444*4824e7fdSDimitry Andric        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args));
445*4824e7fdSDimitry Andric    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
446*4824e7fdSDimitry Andric  }
447349cc55cSDimitry Andric}
448349cc55cSDimitry Andric
449349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt>
450*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
451*4824e7fdSDimitry Andricvformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
452349cc55cSDimitry Andric  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
453349cc55cSDimitry Andric}
454349cc55cSDimitry Andric
455349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
456349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt>
457*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
458*4824e7fdSDimitry Andricvformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
459349cc55cSDimitry Andric  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
460349cc55cSDimitry Andric}
461349cc55cSDimitry Andric#endif
462349cc55cSDimitry Andric
463349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args>
464*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
465349cc55cSDimitry Andricformat_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
466*4824e7fdSDimitry Andric  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
467*4824e7fdSDimitry Andric                           _VSTD::make_format_args(__args...));
468349cc55cSDimitry Andric}
469349cc55cSDimitry Andric
470349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
471349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args>
472*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
473349cc55cSDimitry Andricformat_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
474*4824e7fdSDimitry Andric  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
475*4824e7fdSDimitry Andric                           _VSTD::make_wformat_args(__args...));
476349cc55cSDimitry Andric}
477349cc55cSDimitry Andric#endif
478349cc55cSDimitry Andric
479*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
480349cc55cSDimitry Andricvformat(string_view __fmt, format_args __args) {
481349cc55cSDimitry Andric  string __res;
482349cc55cSDimitry Andric  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
483349cc55cSDimitry Andric  return __res;
484349cc55cSDimitry Andric}
485349cc55cSDimitry Andric
486349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
487*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
488349cc55cSDimitry Andricvformat(wstring_view __fmt, wformat_args __args) {
489349cc55cSDimitry Andric  wstring __res;
490349cc55cSDimitry Andric  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
491349cc55cSDimitry Andric  return __res;
492349cc55cSDimitry Andric}
493349cc55cSDimitry Andric#endif
494349cc55cSDimitry Andric
495349cc55cSDimitry Andrictemplate <class... _Args>
496*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
497349cc55cSDimitry Andricformat(string_view __fmt, const _Args&... __args) {
498349cc55cSDimitry Andric  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
499349cc55cSDimitry Andric}
500349cc55cSDimitry Andric
501349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
502349cc55cSDimitry Andrictemplate <class... _Args>
503*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
504349cc55cSDimitry Andricformat(wstring_view __fmt, const _Args&... __args) {
505349cc55cSDimitry Andric  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
506349cc55cSDimitry Andric}
507349cc55cSDimitry Andric#endif
508349cc55cSDimitry Andric
509349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args>
510349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
511349cc55cSDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
512349cc55cSDimitry Andric            const _Args&... __args) {
513349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
514349cc55cSDimitry Andric  string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
515349cc55cSDimitry Andric  iter_difference_t<_OutIt> __s = __str.size();
516349cc55cSDimitry Andric  iter_difference_t<_OutIt> __m =
517349cc55cSDimitry Andric      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
518349cc55cSDimitry Andric  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
519349cc55cSDimitry Andric  return {_VSTD::move(__out_it), __s};
520349cc55cSDimitry Andric}
521349cc55cSDimitry Andric
522349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
523349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args>
524349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
525349cc55cSDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
526349cc55cSDimitry Andric            const _Args&... __args) {
527349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
528349cc55cSDimitry Andric  wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
529349cc55cSDimitry Andric  iter_difference_t<_OutIt> __s = __str.size();
530349cc55cSDimitry Andric  iter_difference_t<_OutIt> __m =
531349cc55cSDimitry Andric      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
532349cc55cSDimitry Andric  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
533349cc55cSDimitry Andric  return {_VSTD::move(__out_it), __s};
534349cc55cSDimitry Andric}
535349cc55cSDimitry Andric#endif
536349cc55cSDimitry Andric
537349cc55cSDimitry Andrictemplate <class... _Args>
538349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
539349cc55cSDimitry Andricformatted_size(string_view __fmt, const _Args&... __args) {
540349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
541349cc55cSDimitry Andric  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
542349cc55cSDimitry Andric}
543349cc55cSDimitry Andric
544349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
545349cc55cSDimitry Andrictemplate <class... _Args>
546349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
547349cc55cSDimitry Andricformatted_size(wstring_view __fmt, const _Args&... __args) {
548349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
549349cc55cSDimitry Andric  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
550349cc55cSDimitry Andric}
551349cc55cSDimitry Andric#endif
552349cc55cSDimitry Andric
553349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_LOCALIZATION
554349cc55cSDimitry Andric
555*4824e7fdSDimitry Andrictemplate <class _OutIt, class _CharT, class _FormatOutIt>
556349cc55cSDimitry Andricrequires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
557*4824e7fdSDimitry Andric    __vformat_to(
558*4824e7fdSDimitry Andric        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
559*4824e7fdSDimitry Andric        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
560*4824e7fdSDimitry Andric  if constexpr (same_as<_OutIt, _FormatOutIt>)
561*4824e7fdSDimitry Andric    return _VSTD::__format::__vformat_to(
562349cc55cSDimitry Andric        basic_format_parse_context{__fmt, __args.__size()},
563349cc55cSDimitry Andric        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
564349cc55cSDimitry Andric                                       _VSTD::move(__loc)));
565*4824e7fdSDimitry Andric  else {
566*4824e7fdSDimitry Andric    basic_string<_CharT> __str;
567*4824e7fdSDimitry Andric    _VSTD::__format::__vformat_to(
568*4824e7fdSDimitry Andric        basic_format_parse_context{__fmt, __args.__size()},
569*4824e7fdSDimitry Andric        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args,
570*4824e7fdSDimitry Andric                                       _VSTD::move(__loc)));
571*4824e7fdSDimitry Andric    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
572*4824e7fdSDimitry Andric  }
573349cc55cSDimitry Andric}
574349cc55cSDimitry Andric
575349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt>
576*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
577*4824e7fdSDimitry Andric    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
578349cc55cSDimitry Andric  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
579349cc55cSDimitry Andric                             __args);
580349cc55cSDimitry Andric}
581349cc55cSDimitry Andric
582349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
583349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt>
584*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
585*4824e7fdSDimitry Andric    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
586349cc55cSDimitry Andric  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
587349cc55cSDimitry Andric                             __args);
588349cc55cSDimitry Andric}
589349cc55cSDimitry Andric#endif
590349cc55cSDimitry Andric
591349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args>
592*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
593349cc55cSDimitry Andric    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
594*4824e7fdSDimitry Andric  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
595*4824e7fdSDimitry Andric                           _VSTD::make_format_args(__args...));
596349cc55cSDimitry Andric}
597349cc55cSDimitry Andric
598349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
599349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args>
600*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
601349cc55cSDimitry Andric    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
602*4824e7fdSDimitry Andric  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
603*4824e7fdSDimitry Andric                           _VSTD::make_wformat_args(__args...));
604349cc55cSDimitry Andric}
605349cc55cSDimitry Andric#endif
606349cc55cSDimitry Andric
607*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
608349cc55cSDimitry Andricvformat(locale __loc, string_view __fmt, format_args __args) {
609349cc55cSDimitry Andric  string __res;
610349cc55cSDimitry Andric  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
611349cc55cSDimitry Andric                    __args);
612349cc55cSDimitry Andric  return __res;
613349cc55cSDimitry Andric}
614349cc55cSDimitry Andric
615349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
616*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
617349cc55cSDimitry Andricvformat(locale __loc, wstring_view __fmt, wformat_args __args) {
618349cc55cSDimitry Andric  wstring __res;
619349cc55cSDimitry Andric  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
620349cc55cSDimitry Andric                    __args);
621349cc55cSDimitry Andric  return __res;
622349cc55cSDimitry Andric}
623349cc55cSDimitry Andric#endif
624349cc55cSDimitry Andric
625349cc55cSDimitry Andrictemplate <class... _Args>
626*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
627349cc55cSDimitry Andricformat(locale __loc, string_view __fmt, const _Args&... __args) {
628349cc55cSDimitry Andric  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
629349cc55cSDimitry Andric                        _VSTD::make_format_args(__args...));
630349cc55cSDimitry Andric}
631349cc55cSDimitry Andric
632349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
633349cc55cSDimitry Andrictemplate <class... _Args>
634*4824e7fdSDimitry Andric_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
635349cc55cSDimitry Andricformat(locale __loc, wstring_view __fmt, const _Args&... __args) {
636349cc55cSDimitry Andric  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
637349cc55cSDimitry Andric                        _VSTD::make_wformat_args(__args...));
638349cc55cSDimitry Andric}
639349cc55cSDimitry Andric#endif
640349cc55cSDimitry Andric
641349cc55cSDimitry Andrictemplate <output_iterator<const char&> _OutIt, class... _Args>
642349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
643349cc55cSDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
644349cc55cSDimitry Andric            string_view __fmt, const _Args&... __args) {
645349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
646349cc55cSDimitry Andric  string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
647349cc55cSDimitry Andric                                _VSTD::make_format_args(__args...));
648349cc55cSDimitry Andric  iter_difference_t<_OutIt> __s = __str.size();
649349cc55cSDimitry Andric  iter_difference_t<_OutIt> __m =
650349cc55cSDimitry Andric      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
651349cc55cSDimitry Andric  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
652349cc55cSDimitry Andric  return {_VSTD::move(__out_it), __s};
653349cc55cSDimitry Andric}
654349cc55cSDimitry Andric
655349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
656349cc55cSDimitry Andrictemplate <output_iterator<const wchar_t&> _OutIt, class... _Args>
657349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
658349cc55cSDimitry Andricformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
659349cc55cSDimitry Andric            wstring_view __fmt, const _Args&... __args) {
660349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
661349cc55cSDimitry Andric  wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
662349cc55cSDimitry Andric                                 _VSTD::make_wformat_args(__args...));
663349cc55cSDimitry Andric  iter_difference_t<_OutIt> __s = __str.size();
664349cc55cSDimitry Andric  iter_difference_t<_OutIt> __m =
665349cc55cSDimitry Andric      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
666349cc55cSDimitry Andric  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
667349cc55cSDimitry Andric  return {_VSTD::move(__out_it), __s};
668349cc55cSDimitry Andric}
669349cc55cSDimitry Andric#endif
670349cc55cSDimitry Andric
671349cc55cSDimitry Andrictemplate <class... _Args>
672349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
673349cc55cSDimitry Andricformatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
674349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
675349cc55cSDimitry Andric  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
676349cc55cSDimitry Andric                        _VSTD::make_format_args(__args...))
677349cc55cSDimitry Andric      .size();
678349cc55cSDimitry Andric}
679349cc55cSDimitry Andric
680349cc55cSDimitry Andric#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
681349cc55cSDimitry Andrictemplate <class... _Args>
682349cc55cSDimitry Andric_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
683349cc55cSDimitry Andricformatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
684349cc55cSDimitry Andric  // TODO FMT Improve PoC: using std::string is inefficient.
685349cc55cSDimitry Andric  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
686349cc55cSDimitry Andric                        _VSTD::make_wformat_args(__args...))
687349cc55cSDimitry Andric      .size();
688349cc55cSDimitry Andric}
689349cc55cSDimitry Andric#endif
690349cc55cSDimitry Andric
691349cc55cSDimitry Andric#endif // _LIBCPP_HAS_NO_LOCALIZATION
692349cc55cSDimitry Andric
693349cc55cSDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
694fe6060f1SDimitry Andric#endif //_LIBCPP_STD_VER > 17
695fe6060f1SDimitry Andric
696fe6060f1SDimitry Andric_LIBCPP_END_NAMESPACE_STD
697fe6060f1SDimitry Andric
698fe6060f1SDimitry Andric_LIBCPP_POP_MACROS
699fe6060f1SDimitry Andric
7006e75b2fbSDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
7016e75b2fbSDimitry Andric
702fe6060f1SDimitry Andric#endif // _LIBCPP_FORMAT
703