xref: /llvm-project-15.0.7/libcxx/include/format (revision ade6d0d8)
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 if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
373          __arg.format(__parse_ctx, __ctx);
374        else {
375          formatter<decltype(__arg), _CharT> __formatter;
376          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
377          __ctx.advance_to(__formatter.format(__arg, __ctx));
378        }
379      },
380      __ctx.arg(__r.__value));
381
382  __begin = __parse_ctx.begin();
383  if (__begin == __end || *__begin != _CharT('}'))
384    __throw_format_error("The replacement field misses a terminating '}'");
385
386  return ++__begin;
387}
388
389template <class _ParseCtx, class _Ctx>
390_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
391__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
392  using _CharT = typename _ParseCtx::char_type;
393  static_assert(same_as<typename _Ctx::char_type, _CharT>);
394
395  const _CharT* __begin = __parse_ctx.begin();
396  const _CharT* __end = __parse_ctx.end();
397  typename _Ctx::iterator __out_it = __ctx.out();
398  while (__begin != __end) {
399    switch (*__begin) {
400    case _CharT('{'):
401      ++__begin;
402      if (__begin == __end)
403        __throw_format_error("The format string terminates at a '{'");
404
405      if (*__begin != _CharT('{')) [[likely]] {
406        __ctx.advance_to(_VSTD::move(__out_it));
407        __begin =
408            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
409        __out_it = __ctx.out();
410
411        // The output is written and __begin points to the next character. So
412        // start the next iteration.
413        continue;
414      }
415      // The string is an escape character.
416      break;
417
418    case _CharT('}'):
419      ++__begin;
420      if (__begin == __end || *__begin != _CharT('}'))
421        __throw_format_error(
422            "The format string contains an invalid escape sequence");
423
424      break;
425    }
426
427    // Copy the character to the output verbatim.
428    *__out_it++ = *__begin++;
429  }
430  return __out_it;
431}
432
433} // namespace __format
434
435template <class _OutIt, class _CharT, class _FormatOutIt>
436requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
437    __vformat_to(
438        _OutIt __out_it, basic_string_view<_CharT> __fmt,
439        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
440  if constexpr (same_as<_OutIt, _FormatOutIt>)
441    return _VSTD::__format::__vformat_to(
442        basic_format_parse_context{__fmt, __args.__size()},
443        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
444  else {
445    basic_string<_CharT> __str;
446    _VSTD::__format::__vformat_to(
447        basic_format_parse_context{__fmt, __args.__size()},
448        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args));
449    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
450  }
451}
452
453template <output_iterator<const char&> _OutIt>
454_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
455vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
456  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
457}
458
459#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
460template <output_iterator<const wchar_t&> _OutIt>
461_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
462vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
463  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
464}
465#endif
466
467template <output_iterator<const char&> _OutIt, class... _Args>
468_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
469format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
470  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
471                           _VSTD::make_format_args(__args...));
472}
473
474#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
475template <output_iterator<const wchar_t&> _OutIt, class... _Args>
476_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
477format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
478  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
479                           _VSTD::make_wformat_args(__args...));
480}
481#endif
482
483_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
484vformat(string_view __fmt, format_args __args) {
485  string __res;
486  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
487  return __res;
488}
489
490#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
491_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
492vformat(wstring_view __fmt, wformat_args __args) {
493  wstring __res;
494  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
495  return __res;
496}
497#endif
498
499template <class... _Args>
500_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
501format(string_view __fmt, const _Args&... __args) {
502  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
503}
504
505#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
506template <class... _Args>
507_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
508format(wstring_view __fmt, const _Args&... __args) {
509  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
510}
511#endif
512
513template <output_iterator<const char&> _OutIt, class... _Args>
514_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
515format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
516            const _Args&... __args) {
517  // TODO FMT Improve PoC: using std::string is inefficient.
518  string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
519  iter_difference_t<_OutIt> __s = __str.size();
520  iter_difference_t<_OutIt> __m =
521      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
522  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
523  return {_VSTD::move(__out_it), __s};
524}
525
526#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
527template <output_iterator<const wchar_t&> _OutIt, class... _Args>
528_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
529format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
530            const _Args&... __args) {
531  // TODO FMT Improve PoC: using std::string is inefficient.
532  wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
533  iter_difference_t<_OutIt> __s = __str.size();
534  iter_difference_t<_OutIt> __m =
535      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
536  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
537  return {_VSTD::move(__out_it), __s};
538}
539#endif
540
541template <class... _Args>
542_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
543formatted_size(string_view __fmt, const _Args&... __args) {
544  // TODO FMT Improve PoC: using std::string is inefficient.
545  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
546}
547
548#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
549template <class... _Args>
550_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
551formatted_size(wstring_view __fmt, const _Args&... __args) {
552  // TODO FMT Improve PoC: using std::string is inefficient.
553  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
554}
555#endif
556
557#ifndef _LIBCPP_HAS_NO_LOCALIZATION
558
559template <class _OutIt, class _CharT, class _FormatOutIt>
560requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
561    __vformat_to(
562        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
563        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
564  if constexpr (same_as<_OutIt, _FormatOutIt>)
565    return _VSTD::__format::__vformat_to(
566        basic_format_parse_context{__fmt, __args.__size()},
567        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
568                                       _VSTD::move(__loc)));
569  else {
570    basic_string<_CharT> __str;
571    _VSTD::__format::__vformat_to(
572        basic_format_parse_context{__fmt, __args.__size()},
573        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args,
574                                       _VSTD::move(__loc)));
575    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
576  }
577}
578
579template <output_iterator<const char&> _OutIt>
580_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
581    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
582  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
583                             __args);
584}
585
586#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
587template <output_iterator<const wchar_t&> _OutIt>
588_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
589    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
590  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
591                             __args);
592}
593#endif
594
595template <output_iterator<const char&> _OutIt, class... _Args>
596_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
597    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
598  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
599                           _VSTD::make_format_args(__args...));
600}
601
602#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
603template <output_iterator<const wchar_t&> _OutIt, class... _Args>
604_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
605    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
606  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
607                           _VSTD::make_wformat_args(__args...));
608}
609#endif
610
611_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
612vformat(locale __loc, string_view __fmt, format_args __args) {
613  string __res;
614  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
615                    __args);
616  return __res;
617}
618
619#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
620_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
621vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
622  wstring __res;
623  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
624                    __args);
625  return __res;
626}
627#endif
628
629template <class... _Args>
630_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
631format(locale __loc, string_view __fmt, const _Args&... __args) {
632  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
633                        _VSTD::make_format_args(__args...));
634}
635
636#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
637template <class... _Args>
638_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
639format(locale __loc, wstring_view __fmt, const _Args&... __args) {
640  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
641                        _VSTD::make_wformat_args(__args...));
642}
643#endif
644
645template <output_iterator<const char&> _OutIt, class... _Args>
646_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
647format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
648            string_view __fmt, const _Args&... __args) {
649  // TODO FMT Improve PoC: using std::string is inefficient.
650  string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
651                                _VSTD::make_format_args(__args...));
652  iter_difference_t<_OutIt> __s = __str.size();
653  iter_difference_t<_OutIt> __m =
654      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
655  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
656  return {_VSTD::move(__out_it), __s};
657}
658
659#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
660template <output_iterator<const wchar_t&> _OutIt, class... _Args>
661_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
662format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
663            wstring_view __fmt, const _Args&... __args) {
664  // TODO FMT Improve PoC: using std::string is inefficient.
665  wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
666                                 _VSTD::make_wformat_args(__args...));
667  iter_difference_t<_OutIt> __s = __str.size();
668  iter_difference_t<_OutIt> __m =
669      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
670  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
671  return {_VSTD::move(__out_it), __s};
672}
673#endif
674
675template <class... _Args>
676_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
677formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
678  // TODO FMT Improve PoC: using std::string is inefficient.
679  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
680                        _VSTD::make_format_args(__args...))
681      .size();
682}
683
684#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
685template <class... _Args>
686_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
687formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
688  // TODO FMT Improve PoC: using std::string is inefficient.
689  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
690                        _VSTD::make_wformat_args(__args...))
691      .size();
692}
693#endif
694
695#endif // _LIBCPP_HAS_NO_LOCALIZATION
696
697#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
698#endif //_LIBCPP_STD_VER > 17
699
700_LIBCPP_END_NAMESPACE_STD
701
702_LIBCPP_POP_MACROS
703
704#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
705
706#endif // _LIBCPP_FORMAT
707