xref: /llvm-project-15.0.7/libcxx/include/format (revision db2944e3)
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_string.h>
283#include <__format/parser_std_format_spec.h>
284#include <__variant/monostate.h>
285#include <array>
286#include <concepts>
287#include <string>
288#include <string_view>
289#include <type_traits>
290
291#ifndef _LIBCPP_HAS_NO_LOCALIZATION
292#include <locale>
293#endif
294
295#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
296#pragma GCC system_header
297#endif
298
299_LIBCPP_PUSH_MACROS
300#include <__undef_macros>
301
302_LIBCPP_BEGIN_NAMESPACE_STD
303
304#if _LIBCPP_STD_VER > 17
305
306// TODO FMT Remove this once we require compilers with proper C++20 support.
307// If the compiler has no concepts support, the format header will be disabled.
308// Without concepts support enable_if needs to be used and that too much effort
309// to support compilers with partial C++20 support.
310#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
311
312// TODO FMT Move the implementation in this file to its own granular headers.
313
314// TODO FMT Evaluate which templates should be external templates. This
315// improves the efficiency of the header. However since the header is still
316// under heavy development and not all classes are stable it makes no sense
317// to do this optimization now.
318
319using format_args = basic_format_args<format_context>;
320#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
321using wformat_args = basic_format_args<wformat_context>;
322#endif
323
324template <class _Context, class... _Args>
325struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
326  // TODO FMT Use a built-in array.
327  array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
328};
329
330template <class _Context = format_context, class... _Args>
331_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
332make_format_args(const _Args&... __args) {
333  return {basic_format_arg<_Context>(__args)...};
334}
335
336#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
337template <class... _Args>
338_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
339make_wformat_args(const _Args&... __args) {
340  return _VSTD::make_format_args<wformat_context>(__args...);
341}
342#endif
343
344namespace __format {
345
346template <class _CharT, class _ParseCtx, class _Ctx>
347_LIBCPP_HIDE_FROM_ABI const _CharT*
348__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
349                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
350  __format::__parse_number_result __r =
351      __format::__parse_arg_id(__begin, __end, __parse_ctx);
352
353  switch (*__r.__ptr) {
354  case _CharT(':'):
355    // The arg-id has a format-specifier, advance the input to the format-spec.
356    __parse_ctx.advance_to(__r.__ptr + 1);
357    break;
358  case _CharT('}'):
359    // The arg-id has no format-specifier.
360    __parse_ctx.advance_to(__r.__ptr);
361    break;
362  default:
363    __throw_format_error(
364        "The replacement field arg-id should terminate at a ':' or '}'");
365  }
366
367  _VSTD::visit_format_arg(
368      [&](auto __arg) {
369        if constexpr (same_as<decltype(__arg), monostate>)
370          __throw_format_error("Argument index out of bounds");
371        else {
372          formatter<decltype(__arg), _CharT> __formatter;
373          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
374          __ctx.advance_to(__formatter.format(__arg, __ctx));
375        }
376      },
377      __ctx.arg(__r.__value));
378
379  __begin = __parse_ctx.begin();
380  if (__begin == __end || *__begin != _CharT('}'))
381    __throw_format_error("The replacement field misses a terminating '}'");
382
383  return ++__begin;
384}
385
386template <class _ParseCtx, class _Ctx>
387_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
388__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
389  using _CharT = typename _ParseCtx::char_type;
390  static_assert(same_as<typename _Ctx::char_type, _CharT>);
391
392  const _CharT* __begin = __parse_ctx.begin();
393  const _CharT* __end = __parse_ctx.end();
394  typename _Ctx::iterator __out_it = __ctx.out();
395  while (__begin != __end) {
396    switch (*__begin) {
397    case _CharT('{'):
398      ++__begin;
399      if (__begin == __end)
400        __throw_format_error("The format string terminates at a '{'");
401
402      if (*__begin != _CharT('{')) [[likely]] {
403        __ctx.advance_to(_VSTD::move(__out_it));
404        __begin =
405            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
406        __out_it = __ctx.out();
407
408        // The output is written and __begin points to the next character. So
409        // start the next iteration.
410        continue;
411      }
412      // The string is an escape character.
413      break;
414
415    case _CharT('}'):
416      ++__begin;
417      if (__begin == __end || *__begin != _CharT('}'))
418        __throw_format_error(
419            "The format string contains an invalid escape sequence");
420
421      break;
422    }
423
424    // Copy the character to the output verbatim.
425    *__out_it++ = *__begin++;
426  }
427  return __out_it;
428}
429
430} // namespace __format
431
432template <class _OutIt, class _CharT, class _FormatOutIt>
433requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
434    __vformat_to(
435        _OutIt __out_it, basic_string_view<_CharT> __fmt,
436        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
437  if constexpr (same_as<_OutIt, _FormatOutIt>)
438    return _VSTD::__format::__vformat_to(
439        basic_format_parse_context{__fmt, __args.__size()},
440        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
441  else {
442    basic_string<_CharT> __str;
443    _VSTD::__format::__vformat_to(
444        basic_format_parse_context{__fmt, __args.__size()},
445        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args));
446    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
447  }
448}
449
450template <output_iterator<const char&> _OutIt>
451_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
452vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
453  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
454}
455
456#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
457template <output_iterator<const wchar_t&> _OutIt>
458_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
459vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
460  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
461}
462#endif
463
464template <output_iterator<const char&> _OutIt, class... _Args>
465_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
466format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
467  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
468                           _VSTD::make_format_args(__args...));
469}
470
471#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
472template <output_iterator<const wchar_t&> _OutIt, class... _Args>
473_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
474format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
475  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
476                           _VSTD::make_wformat_args(__args...));
477}
478#endif
479
480_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
481vformat(string_view __fmt, format_args __args) {
482  string __res;
483  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
484  return __res;
485}
486
487#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
488_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
489vformat(wstring_view __fmt, wformat_args __args) {
490  wstring __res;
491  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
492  return __res;
493}
494#endif
495
496template <class... _Args>
497_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
498format(string_view __fmt, const _Args&... __args) {
499  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
500}
501
502#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
503template <class... _Args>
504_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
505format(wstring_view __fmt, const _Args&... __args) {
506  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
507}
508#endif
509
510template <output_iterator<const char&> _OutIt, class... _Args>
511_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
512format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
513            const _Args&... __args) {
514  // TODO FMT Improve PoC: using std::string is inefficient.
515  string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
516  iter_difference_t<_OutIt> __s = __str.size();
517  iter_difference_t<_OutIt> __m =
518      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
519  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
520  return {_VSTD::move(__out_it), __s};
521}
522
523#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
524template <output_iterator<const wchar_t&> _OutIt, class... _Args>
525_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
526format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
527            const _Args&... __args) {
528  // TODO FMT Improve PoC: using std::string is inefficient.
529  wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
530  iter_difference_t<_OutIt> __s = __str.size();
531  iter_difference_t<_OutIt> __m =
532      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
533  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
534  return {_VSTD::move(__out_it), __s};
535}
536#endif
537
538template <class... _Args>
539_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
540formatted_size(string_view __fmt, const _Args&... __args) {
541  // TODO FMT Improve PoC: using std::string is inefficient.
542  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...)).size();
543}
544
545#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
546template <class... _Args>
547_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
548formatted_size(wstring_view __fmt, const _Args&... __args) {
549  // TODO FMT Improve PoC: using std::string is inefficient.
550  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...)).size();
551}
552#endif
553
554#ifndef _LIBCPP_HAS_NO_LOCALIZATION
555
556template <class _OutIt, class _CharT, class _FormatOutIt>
557requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
558    __vformat_to(
559        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
560        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
561  if constexpr (same_as<_OutIt, _FormatOutIt>)
562    return _VSTD::__format::__vformat_to(
563        basic_format_parse_context{__fmt, __args.__size()},
564        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
565                                       _VSTD::move(__loc)));
566  else {
567    basic_string<_CharT> __str;
568    _VSTD::__format::__vformat_to(
569        basic_format_parse_context{__fmt, __args.__size()},
570        _VSTD::__format_context_create(_VSTD::back_inserter(__str), __args,
571                                       _VSTD::move(__loc)));
572    return _VSTD::copy_n(__str.begin(), __str.size(), _VSTD::move(__out_it));
573  }
574}
575
576template <output_iterator<const char&> _OutIt>
577_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
578    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
579  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
580                             __args);
581}
582
583#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
584template <output_iterator<const wchar_t&> _OutIt>
585_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
586    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
587  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
588                             __args);
589}
590#endif
591
592template <output_iterator<const char&> _OutIt, class... _Args>
593_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
594    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
595  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
596                           _VSTD::make_format_args(__args...));
597}
598
599#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
600template <output_iterator<const wchar_t&> _OutIt, class... _Args>
601_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
602    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
603  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
604                           _VSTD::make_wformat_args(__args...));
605}
606#endif
607
608_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
609vformat(locale __loc, string_view __fmt, format_args __args) {
610  string __res;
611  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
612                    __args);
613  return __res;
614}
615
616#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
617_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
618vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
619  wstring __res;
620  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
621                    __args);
622  return __res;
623}
624#endif
625
626template <class... _Args>
627_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
628format(locale __loc, string_view __fmt, const _Args&... __args) {
629  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
630                        _VSTD::make_format_args(__args...));
631}
632
633#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
634template <class... _Args>
635_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
636format(locale __loc, wstring_view __fmt, const _Args&... __args) {
637  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
638                        _VSTD::make_wformat_args(__args...));
639}
640#endif
641
642template <output_iterator<const char&> _OutIt, class... _Args>
643_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
644format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
645            string_view __fmt, const _Args&... __args) {
646  // TODO FMT Improve PoC: using std::string is inefficient.
647  string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
648                                _VSTD::make_format_args(__args...));
649  iter_difference_t<_OutIt> __s = __str.size();
650  iter_difference_t<_OutIt> __m =
651      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
652  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
653  return {_VSTD::move(__out_it), __s};
654}
655
656#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
657template <output_iterator<const wchar_t&> _OutIt, class... _Args>
658_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
659format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
660            wstring_view __fmt, const _Args&... __args) {
661  // TODO FMT Improve PoC: using std::string is inefficient.
662  wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
663                                 _VSTD::make_wformat_args(__args...));
664  iter_difference_t<_OutIt> __s = __str.size();
665  iter_difference_t<_OutIt> __m =
666      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
667  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
668  return {_VSTD::move(__out_it), __s};
669}
670#endif
671
672template <class... _Args>
673_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
674formatted_size(locale __loc, string_view __fmt, const _Args&... __args) {
675  // TODO FMT Improve PoC: using std::string is inefficient.
676  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
677                        _VSTD::make_format_args(__args...))
678      .size();
679}
680
681#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
682template <class... _Args>
683_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
684formatted_size(locale __loc, wstring_view __fmt, const _Args&... __args) {
685  // TODO FMT Improve PoC: using std::string is inefficient.
686  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
687                        _VSTD::make_wformat_args(__args...))
688      .size();
689}
690#endif
691
692#endif // _LIBCPP_HAS_NO_LOCALIZATION
693
694#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
695#endif //_LIBCPP_STD_VER > 17
696
697_LIBCPP_END_NAMESPACE_STD
698
699_LIBCPP_POP_MACROS
700
701#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
702
703#endif // _LIBCPP_FORMAT
704