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