xref: /llvm-project-15.0.7/libcxx/include/format (revision 787ccd34)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_FORMAT
11#define _LIBCPP_FORMAT
12
13/*
14
15namespace std {
16  // [format.context], class template basic_format_context
17  template<class Out, class charT>
18  class basic_format_context {
19    basic_format_args<basic_format_context> args_;      // exposition only
20    Out out_;                                           // exposition only
21
22  public:
23    using iterator = Out;
24    using char_type = charT;
25    template<class T> using formatter_type = formatter<T, charT>;
26
27    basic_format_arg<basic_format_context> arg(size_t id) const;
28    std::locale locale();
29
30    iterator out();
31    void advance_to(iterator it);
32  };
33  using format_context = basic_format_context<unspecified, char>;
34  using wformat_context = basic_format_context<unspecified, wchar_t>;
35
36  // [format.args], class template basic_format_args
37  template<class Context>
38  class basic_format_args {
39    size_t size_;                               // exposition only
40    const basic_format_arg<Context>* data_;     // exposition only
41
42  public:
43    basic_format_args() noexcept;
44
45    template<class... Args>
46      basic_format_args(const format-arg-store<Context, Args...>& store) noexcept;
47
48    basic_format_arg<Context> get(size_t i) const noexcept;
49  };
50  using format_args = basic_format_args<format_context>;
51  using wformat_args = basic_format_args<wformat_context>;
52
53
54  // [format.functions], formatting functions
55  template<class... Args>
56    string format(string_view fmt, const Args&... args);
57  template<class... Args>
58    wstring format(wstring_view fmt, const Args&... args);
59  template<class... Args>
60    string format(const locale& loc, string_view fmt, const Args&... args);
61  template<class... Args>
62    wstring format(const locale& loc, wstring_view fmt, const Args&... args);
63
64  string vformat(string_view fmt, format_args args);
65  wstring vformat(wstring_view fmt, wformat_args args);
66  string vformat(const locale& loc, string_view fmt, format_args args);
67  wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
68
69  template<class Out, class... Args>
70    Out format_to(Out out, string_view fmt, const Args&... args);
71  template<class Out, class... Args>
72    Out format_to(Out out, wstring_view fmt, const Args&... args);
73  template<class Out, class... Args>
74    Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
75  template<class Out, class... Args>
76    Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
77
78  template<class Out>
79    Out vformat_to(Out out, string_view fmt, format_args args);
80  template<class Out>
81    Out vformat_to(Out out, wstring_view fmt, wformat_args args);
82  template<class Out>
83    Out vformat_to(Out out, const locale& loc, string_view fmt,
84                   format_args char> args);
85  template<class Out>
86    Out vformat_to(Out out, const locale& loc, wstring_view fmt,
87                   wformat_args args);
88
89  template<class Out> struct format_to_n_result {
90    Out out;
91    iter_difference_t<Out> size;
92  };
93
94 template<class Out, class... Args>
95    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
96                                        string_view fmt, const Args&... args);
97  template<class Out, class... Args>
98    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
99                                        wstring_view fmt, const Args&... args);
100  template<class Out, class... Args>
101    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
102                                        const locale& loc, string_view fmt,
103                                        const Args&... args);
104  template<class Out, class... Args>
105    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
106                                        const locale& loc, wstring_view fmt,
107                                        const Args&... args);
108
109  template<class... Args>
110    size_t formatted_size(string_view fmt, const Args&... args);
111  template<class... Args>
112    size_t formatted_size(wstring_view fmt, const Args&... args);
113  template<class... Args>
114    size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
115  template<class... Args>
116    size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
117
118  // [format.formatter], formatter
119  template<> struct formatter<char, char>;
120  template<> struct formatter<char, wchar_t>;
121  template<> struct formatter<wchar_t, wchar_t>;
122
123  template<> struct formatter<charT*, charT>;
124  template<> struct formatter<const charT*, charT>;
125  template<size_t N> struct formatter<const charT[N], charT>;
126  template<class traits, class Allocator>
127    struct formatter<basic_string<charT, traits, Allocator>, charT>;
128  template<class traits>
129    struct formatter<basic_string_view<charT, traits>, charT>;
130
131  // [format.parse.ctx], class template basic_format_parse_context
132  template<class charT>
133  class basic_format_parse_context {
134  public:
135    using char_type = charT;
136    using const_iterator = typename basic_string_view<charT>::const_iterator;
137    using iterator = const_iterator;
138
139  private:
140    iterator begin_;                                    // exposition only
141    iterator end_;                                      // exposition only
142    enum indexing { unknown, manual, automatic };       // exposition only
143    indexing indexing_;                                 // exposition only
144    size_t next_arg_id_;                                // exposition only
145    size_t num_args_;                                   // exposition only
146
147  public:
148    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
149                                                  size_t num_args = 0) noexcept;
150    basic_format_parse_context(const basic_format_parse_context&) = delete;
151    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
152
153    constexpr const_iterator begin() const noexcept;
154    constexpr const_iterator end() const noexcept;
155    constexpr void advance_to(const_iterator it);
156
157    constexpr size_t next_arg_id();
158    constexpr void check_arg_id(size_t id);
159  };
160  using format_parse_context = basic_format_parse_context<char>;
161  using wformat_parse_context = basic_format_parse_context<wchar_t>;
162
163  // [format.arguments], arguments
164  // [format.arg], class template basic_format_arg
165  template<class Context>
166  class basic_format_arg {
167  public:
168    class handle;
169
170  private:
171    using char_type = typename Context::char_type;                              // exposition only
172
173    variant<monostate, bool, char_type,
174            int, unsigned int, long long int, unsigned long long int,
175            float, double, long double,
176            const char_type*, basic_string_view<char_type>,
177            const void*, handle> value;                                         // exposition only
178
179    template<class T> explicit basic_format_arg(const T& v) noexcept;           // exposition only
180    explicit basic_format_arg(float n) noexcept;                                // exposition only
181    explicit basic_format_arg(double n) noexcept;                               // exposition only
182    explicit basic_format_arg(long double n) noexcept;                          // exposition only
183    explicit basic_format_arg(const char_type* s);                              // exposition only
184
185    template<class traits>
186      explicit basic_format_arg(
187        basic_string_view<char_type, traits> s) noexcept;                       // exposition only
188
189    template<class traits, class Allocator>
190      explicit basic_format_arg(
191        const basic_string<char_type, traits, Allocator>& s) noexcept;          // exposition only
192
193    explicit basic_format_arg(nullptr_t) noexcept;                              // exposition only
194
195    template<class T>
196      explicit basic_format_arg(const T* p) noexcept;                           // exposition only
197
198  public:
199    basic_format_arg() noexcept;
200
201    explicit operator bool() const noexcept;
202  };
203
204  template<class Visitor, class Context>
205    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
206
207  // [format.arg.store], class template format-arg-store
208  template<class Context, class... Args>
209  struct format-arg-store {      // exposition only
210    array<basic_format_arg<Context>, sizeof...(Args)> args;
211  };
212
213  template<class Context = format_context, class... Args>
214    format-arg-store<Context, Args...>
215      make_format_args(const Args&... args);
216  template<class... Args>
217    format-arg-store<wformat_context, Args...>
218      make_wformat_args(const Args&... args);
219
220  // [format.error], class format_error
221  class format_error : public runtime_error {
222  public:
223    explicit format_error(const string& what_arg);
224    explicit format_error(const char* what_arg);
225  };
226
227  // [format.parse.ctx], class template basic_format_parse_context
228  template<class charT>
229  class basic_format_parse_context {
230  public:
231    using char_type = charT;
232    using const_iterator = typename basic_string_view<charT>::const_iterator;
233    using iterator = const_iterator;
234
235  private:
236    iterator begin_;                                    // exposition only
237    iterator end_;                                      // exposition only
238    enum indexing { unknown, manual, automatic };       // exposition only
239    indexing indexing_;                                 // exposition only
240    size_t next_arg_id_;                                // exposition only
241    size_t num_args_;                                   // exposition only
242
243  public:
244    constexpr explicit basic_format_parse_context(basic_string_view<charT> fmt,
245                                                  size_t num_args = 0) noexcept;
246    basic_format_parse_context(const basic_format_parse_context&) = delete;
247    basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
248
249    constexpr const_iterator begin() const noexcept;
250    constexpr const_iterator end() const noexcept;
251    constexpr void advance_to(const_iterator it);
252
253    constexpr size_t next_arg_id();
254    constexpr void check_arg_id(size_t id);
255  };
256  using format_parse_context = basic_format_parse_context<char>;
257  using wformat_parse_context = basic_format_parse_context<wchar_t>;
258}
259
260*/
261
262// Make sure all feature-test macros are available.
263#include <version>
264// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
265#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
266
267#include <__config>
268#include <__debug>
269#include <__format/format_arg.h>
270#include <__format/format_args.h>
271#include <__format/format_context.h>
272#include <__format/format_error.h>
273#include <__format/format_fwd.h>
274#include <__format/format_parse_context.h>
275#include <__format/format_string.h>
276#include <__format/format_to_n_result.h>
277#include <__format/formatter.h>
278#include <__format/formatter_bool.h>
279#include <__format/formatter_char.h>
280#include <__format/formatter_floating_point.h>
281#include <__format/formatter_integer.h>
282#include <__format/formatter_pointer.h>
283#include <__format/formatter_string.h>
284#include <__format/parser_std_format_spec.h>
285#include <__variant/monostate.h>
286#include <array>
287#include <concepts>
288#include <string>
289#include <string_view>
290#include <type_traits>
291
292#ifndef _LIBCPP_HAS_NO_LOCALIZATION
293#include <locale>
294#endif
295
296#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
297#pragma GCC system_header
298#endif
299
300_LIBCPP_PUSH_MACROS
301#include <__undef_macros>
302
303_LIBCPP_BEGIN_NAMESPACE_STD
304
305#if _LIBCPP_STD_VER > 17
306
307// TODO FMT Remove this once we require compilers with proper C++20 support.
308// If the compiler has no concepts support, the format header will be disabled.
309// Without concepts support enable_if needs to be used and that too much effort
310// to support compilers with partial C++20 support.
311#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
312
313// TODO FMT Move the implementation in this file to its own granular headers.
314
315// TODO FMT Evaluate which templates should be external templates. This
316// improves the efficiency of the header. However since the header is still
317// under heavy development and not all classes are stable it makes no sense
318// to do this optimization now.
319
320using format_args = basic_format_args<format_context>;
321#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
322using wformat_args = basic_format_args<wformat_context>;
323#endif
324
325template <class _Context, class... _Args>
326struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
327  // TODO FMT Use a built-in array.
328  array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
329};
330
331template <class _Context = format_context, class... _Args>
332_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
333make_format_args(const _Args&... __args) {
334  return {basic_format_arg<_Context>(__args)...};
335}
336
337#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
338template <class... _Args>
339_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
340make_wformat_args(const _Args&... __args) {
341  return _VSTD::make_format_args<wformat_context>(__args...);
342}
343#endif
344
345namespace __format {
346
347template <class _CharT, class _ParseCtx, class _Ctx>
348_LIBCPP_HIDE_FROM_ABI const _CharT*
349__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
350                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
351  __format::__parse_number_result __r =
352      __format::__parse_arg_id(__begin, __end, __parse_ctx);
353
354  switch (*__r.__ptr) {
355  case _CharT(':'):
356    // The arg-id has a format-specifier, advance the input to the format-spec.
357    __parse_ctx.advance_to(__r.__ptr + 1);
358    break;
359  case _CharT('}'):
360    // The arg-id has no format-specifier.
361    __parse_ctx.advance_to(__r.__ptr);
362    break;
363  default:
364    __throw_format_error(
365        "The replacement field arg-id should terminate at a ':' or '}'");
366  }
367
368  _VSTD::visit_format_arg(
369      [&](auto __arg) {
370        if constexpr (same_as<decltype(__arg), monostate>)
371          __throw_format_error("Argument index out of bounds");
372        else {
373          formatter<decltype(__arg), _CharT> __formatter;
374          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
375          __ctx.advance_to(__formatter.format(__arg, __ctx));
376        }
377      },
378      __ctx.arg(__r.__value));
379
380  __begin = __parse_ctx.begin();
381  if (__begin == __end || *__begin != _CharT('}'))
382    __throw_format_error("The replacement field misses a terminating '}'");
383
384  return ++__begin;
385}
386
387template <class _ParseCtx, class _Ctx>
388_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
389__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
390  using _CharT = typename _ParseCtx::char_type;
391  static_assert(same_as<typename _Ctx::char_type, _CharT>);
392
393  const _CharT* __begin = __parse_ctx.begin();
394  const _CharT* __end = __parse_ctx.end();
395  typename _Ctx::iterator __out_it = __ctx.out();
396  while (__begin != __end) {
397    switch (*__begin) {
398    case _CharT('{'):
399      ++__begin;
400      if (__begin == __end)
401        __throw_format_error("The format string terminates at a '{'");
402
403      if (*__begin != _CharT('{')) [[likely]] {
404        __ctx.advance_to(_VSTD::move(__out_it));
405        __begin =
406            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
407        __out_it = __ctx.out();
408
409        // The output is written and __begin points to the next character. So
410        // start the next iteration.
411        continue;
412      }
413      // The string is an escape character.
414      break;
415
416    case _CharT('}'):
417      ++__begin;
418      if (__begin == __end || *__begin != _CharT('}'))
419        __throw_format_error(
420            "The format string contains an invalid escape sequence");
421
422      break;
423    }
424
425    // Copy the character to the output verbatim.
426    *__out_it++ = *__begin++;
427  }
428  return __out_it;
429}
430
431} // namespace __format
432
433template <class _OutIt, class _CharT, class _FormatOutIt>
434requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
435    __vformat_to(
436        _OutIt __out_it, basic_string_view<_CharT> __fmt,
437        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
438  if constexpr (same_as<_OutIt, _FormatOutIt>)
439    return _VSTD::__format::__vformat_to(
440        basic_format_parse_context{__fmt, __args.__size()},
441        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
442  else {
443    basic_string<_CharT> __str;
444    _VSTD::__format::__vformat_to(
445        basic_format_parse_context{__fmt, __args.__size()},
446        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args));
447    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
448  }
449}
450
451template <output_iterator<const char&> _OutIt>
452_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
453vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
454  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
455}
456
457#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
458template <output_iterator<const wchar_t&> _OutIt>
459_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
460vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
461  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
462}
463#endif
464
465template <output_iterator<const char&> _OutIt, class... _Args>
466_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
467format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
468  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
469                           _VSTD::make_format_args(__args...));
470}
471
472#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
473template <output_iterator<const wchar_t&> _OutIt, class... _Args>
474_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
475format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
476  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
477                           _VSTD::make_wformat_args(__args...));
478}
479#endif
480
481_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
482vformat(string_view __fmt, format_args __args) {
483  string __res;
484  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
485  return __res;
486}
487
488#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
489_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
490vformat(wstring_view __fmt, wformat_args __args) {
491  wstring __res;
492  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
493  return __res;
494}
495#endif
496
497template <class... _Args>
498_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
499format(string_view __fmt, const _Args&... __args) {
500  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
501}
502
503#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
504template <class... _Args>
505_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
506format(wstring_view __fmt, const _Args&... __args) {
507  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
508}
509#endif
510
511template <output_iterator<const char&> _OutIt, class... _Args>
512_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
513format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
514            const _Args&... __args) {
515  // TODO FMT Improve PoC: using std::string is inefficient.
516  string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
517  iter_difference_t<_OutIt> __s = __str.size();
518  iter_difference_t<_OutIt> __m =
519      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
520  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
521  return {_VSTD::move(__out_it), __s};
522}
523
524#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
525template <output_iterator<const wchar_t&> _OutIt, class... _Args>
526_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
527format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
528            const _Args&... __args) {
529  // TODO FMT Improve PoC: using std::string is inefficient.
530  wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
531  iter_difference_t<_OutIt> __s = __str.size();
532  iter_difference_t<_OutIt> __m =
533      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
534  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
535  return {_VSTD::move(__out_it), __s};
536}
537#endif
538
539template <class... _Args>
540_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
541formatted_size(string_view __fmt, const _Args&... __args) {
542  // TODO FMT Improve PoC: using std::string is inefficient.
543  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
544}
545
546#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
547template <class... _Args>
548_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
549formatted_size(wstring_view __fmt, const _Args&... __args) {
550  // TODO FMT Improve PoC: using std::string is inefficient.
551  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
552}
553#endif
554
555#ifndef _LIBCPP_HAS_NO_LOCALIZATION
556
557template <class _OutIt, class _CharT, class _FormatOutIt>
558requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
559    __vformat_to(
560        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
561        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
562  if constexpr (same_as<_OutIt, _FormatOutIt>)
563    return _VSTD::__format::__vformat_to(
564        basic_format_parse_context{__fmt, __args.__size()},
565        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
566                                       _VSTD::move(__loc)));
567  else {
568    basic_string<_CharT> __str;
569    _VSTD::__format::__vformat_to(
570        basic_format_parse_context{__fmt, __args.__size()},
571        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args,
572                                       _VSTD::move(__loc)));
573    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
574  }
575}
576
577template <output_iterator<const char&> _OutIt>
578_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
579    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
580  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
581                             __args);
582}
583
584#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
585template <output_iterator<const wchar_t&> _OutIt>
586_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
587    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
588  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
589                             __args);
590}
591#endif
592
593template <output_iterator<const char&> _OutIt, class... _Args>
594_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
595    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
596  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
597                           _VSTD::make_format_args(__args...));
598}
599
600#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
601template <output_iterator<const wchar_t&> _OutIt, class... _Args>
602_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
603    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
604  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
605                           _VSTD::make_wformat_args(__args...));
606}
607#endif
608
609_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
610vformat(locale __loc, string_view __fmt, format_args __args) {
611  string __res;
612  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
613                    __args);
614  return __res;
615}
616
617#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
618_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
619vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
620  wstring __res;
621  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
622                    __args);
623  return __res;
624}
625#endif
626
627template <class... _Args>
628_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
629format(locale __loc, string_view __fmt, const _Args&... __args) {
630  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
631                        _VSTD::make_format_args(__args...));
632}
633
634#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
635template <class... _Args>
636_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
637format(locale __loc, wstring_view __fmt, const _Args&... __args) {
638  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
639                        _VSTD::make_wformat_args(__args...));
640}
641#endif
642
643template <output_iterator<const char&> _OutIt, class... _Args>
644_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
645format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
646            string_view __fmt, const _Args&... __args) {
647  // TODO FMT Improve PoC: using std::string is inefficient.
648  string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
649                                _VSTD::make_format_args(__args...));
650  iter_difference_t<_OutIt> __s = __str.size();
651  iter_difference_t<_OutIt> __m =
652      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
653  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
654  return {_VSTD::move(__out_it), __s};
655}
656
657#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
658template <output_iterator<const wchar_t&> _OutIt, class... _Args>
659_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
660format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
661            wstring_view __fmt, const _Args&... __args) {
662  // TODO FMT Improve PoC: using std::string is inefficient.
663  wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
664                                 _VSTD::make_wformat_args(__args...));
665  iter_difference_t<_OutIt> __s = __str.size();
666  iter_difference_t<_OutIt> __m =
667      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
668  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
669  return {_VSTD::move(__out_it), __s};
670}
671#endif
672
673template <class... _Args>
674_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
675formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
676  // TODO FMT Improve PoC: using std::string is inefficient.
677  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
678                        _VSTD::make_format_args(__args...))
679      .size();
680}
681
682#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
683template <class... _Args>
684_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
685formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
686  // TODO FMT Improve PoC: using std::string is inefficient.
687  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
688                        _VSTD::make_wformat_args(__args...))
689      .size();
690}
691#endif
692
693#endif // _LIBCPP_HAS_NO_LOCALIZATION
694
695#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
696#endif //_LIBCPP_STD_VER > 17
697
698_LIBCPP_END_NAMESPACE_STD
699
700_LIBCPP_POP_MACROS
701
702#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
703
704#endif // _LIBCPP_FORMAT
705