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