xref: /llvm-project-15.0.7/libcxx/include/format (revision 91b8d96f)
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> class basic_format_context;
18  using format_context = basic_format_context<unspecified, char>;
19  using wformat_context = basic_format_context<unspecified, wchar_t>;
20
21  // [format.args], class template basic_format_args
22  template<class Context> class basic_format_args;
23  using format_args = basic_format_args<format_context>;
24  using wformat_args = basic_format_args<wformat_context>;
25
26  // [format.functions], formatting functions
27  template<class... Args>
28    string format(string_view fmt, const Args&... args);
29  template<class... Args>
30    wstring format(wstring_view fmt, const Args&... args);
31  template<class... Args>
32    string format(const locale& loc, string_view fmt, const Args&... args);
33  template<class... Args>
34    wstring format(const locale& loc, wstring_view fmt, const Args&... args);
35
36  string vformat(string_view fmt, format_args args);
37  wstring vformat(wstring_view fmt, wformat_args args);
38  string vformat(const locale& loc, string_view fmt, format_args args);
39  wstring vformat(const locale& loc, wstring_view fmt, wformat_args args);
40
41  template<class Out, class... Args>
42    Out format_to(Out out, string_view fmt, const Args&... args);
43  template<class Out, class... Args>
44    Out format_to(Out out, wstring_view fmt, const Args&... args);
45  template<class Out, class... Args>
46    Out format_to(Out out, const locale& loc, string_view fmt, const Args&... args);
47  template<class Out, class... Args>
48    Out format_to(Out out, const locale& loc, wstring_view fmt, const Args&... args);
49
50  template<class Out>
51    Out vformat_to(Out out, string_view fmt, format_args args);
52  template<class Out>
53    Out vformat_to(Out out, wstring_view fmt, wformat_args args);
54  template<class Out>
55    Out vformat_to(Out out, const locale& loc, string_view fmt,
56                   format_args char> args);
57  template<class Out>
58    Out vformat_to(Out out, const locale& loc, wstring_view fmt,
59                   wformat_args args);
60
61  template<class Out> struct format_to_n_result {
62    Out out;
63    iter_difference_t<Out> size;
64  };
65  template<class Out, class... Args>
66    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
67                                        string_view fmt, const Args&... args);
68  template<class Out, class... Args>
69    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
70                                        wstring_view fmt, const Args&... args);
71  template<class Out, class... Args>
72    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
73                                        const locale& loc, string_view fmt,
74                                        const Args&... args);
75  template<class Out, class... Args>
76    format_to_n_result<Out> format_to_n(Out out, iter_difference_t<Out> n,
77                                        const locale& loc, wstring_view fmt,
78                                        const Args&... args);
79
80  template<class... Args>
81    size_t formatted_size(string_view fmt, const Args&... args);
82  template<class... Args>
83    size_t formatted_size(wstring_view fmt, const Args&... args);
84  template<class... Args>
85    size_t formatted_size(const locale& loc, string_view fmt, const Args&... args);
86  template<class... Args>
87    size_t formatted_size(const locale& loc, wstring_view fmt, const Args&... args);
88
89  // [format.formatter], formatter
90  template<class T, class charT = char> struct formatter;
91
92  // [format.parse.ctx], class template basic_format_parse_context
93  template<class charT> class basic_format_parse_context;
94  using format_parse_context = basic_format_parse_context<char>;
95  using wformat_parse_context = basic_format_parse_context<wchar_t>;
96
97  // [format.arguments], arguments
98  // [format.arg], class template basic_format_arg
99  template<class Context> class basic_format_arg;
100
101  template<class Visitor, class Context>
102    see below visit_format_arg(Visitor&& vis, basic_format_arg<Context> arg);
103
104  // [format.arg.store], class template format-arg-store
105  template<class Context, class... Args> struct format-arg-store;      // exposition only
106
107  template<class Context = format_context, class... Args>
108    format-arg-store<Context, Args...>
109      make_format_args(const Args&... args);
110  template<class... Args>
111    format-arg-store<wformat_context, Args...>
112      make_wformat_args(const Args&... args);
113
114  // [format.error], class format_error
115  class format_error;
116}
117
118*/
119
120#include <__assert> // all public C++ headers provide the assertion handler
121// Make sure all feature-test macros are available.
122#include <version>
123// Enable the contents of the header only when libc++ was built with LIBCXX_ENABLE_INCOMPLETE_FEATURES.
124#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
125
126#include <__algorithm/clamp.h>
127#include <__config>
128#include <__debug>
129#include <__format/buffer.h>
130#include <__format/concepts.h>
131#include <__format/enable_insertable.h>
132#include <__format/format_arg.h>
133#include <__format/format_arg_store.h>
134#include <__format/format_args.h>
135#include <__format/format_context.h>
136#include <__format/format_error.h>
137#include <__format/format_fwd.h>
138#include <__format/format_parse_context.h>
139#include <__format/format_string.h>
140#include <__format/format_to_n_result.h>
141#include <__format/formatter.h>
142#include <__format/formatter_bool.h>
143#include <__format/formatter_char.h>
144#include <__format/formatter_floating_point.h>
145#include <__format/formatter_integer.h>
146#include <__format/formatter_pointer.h>
147#include <__format/formatter_string.h>
148#include <__format/parser_std_format_spec.h>
149#include <__variant/monostate.h>
150#include <array>
151#include <concepts>
152#include <string>
153#include <string_view>
154#include <type_traits>
155
156#ifndef _LIBCPP_HAS_NO_LOCALIZATION
157#include <locale>
158#endif
159
160#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
161#  pragma GCC system_header
162#endif
163
164_LIBCPP_BEGIN_NAMESPACE_STD
165
166#if _LIBCPP_STD_VER > 17
167
168// TODO FMT Move the implementation in this file to its own granular headers.
169
170// TODO FMT Evaluate which templates should be external templates. This
171// improves the efficiency of the header. However since the header is still
172// under heavy development and not all classes are stable it makes no sense
173// to do this optimization now.
174
175using format_args = basic_format_args<format_context>;
176#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
177using wformat_args = basic_format_args<wformat_context>;
178#endif
179
180// TODO FMT This helper wrapper can probably be removed after P2418 has been
181// implemented.
182template <class _Context, class... _Args>
183_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
184__make_format_args(_Args&&... __args) {
185  return _VSTD::__format_arg_store<_Context, _Args...>(
186      _VSTD::forward<_Args>(__args)...);
187}
188
189// TODO FMT After P2418 specify the return type instead of using auto.
190template <class _Context = format_context, class... _Args>
191_LIBCPP_HIDE_FROM_ABI auto make_format_args(const _Args&... __args) {
192  return _VSTD::__make_format_args<_Context>(__args...);
193}
194
195#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
196// TODO FMT After P2418 specify the return type instead of using auto.
197template <class... _Args>
198_LIBCPP_HIDE_FROM_ABI auto make_wformat_args(const _Args&... __args) {
199  return _VSTD::make_format_args<wformat_context>(__args...);
200}
201#endif
202
203namespace __format {
204
205template <class _CharT, class _ParseCtx, class _Ctx>
206_LIBCPP_HIDE_FROM_ABI const _CharT*
207__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
208                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
209  __format::__parse_number_result __r =
210      __format::__parse_arg_id(__begin, __end, __parse_ctx);
211
212  switch (*__r.__ptr) {
213  case _CharT(':'):
214    // The arg-id has a format-specifier, advance the input to the format-spec.
215    __parse_ctx.advance_to(__r.__ptr + 1);
216    break;
217  case _CharT('}'):
218    // The arg-id has no format-specifier.
219    __parse_ctx.advance_to(__r.__ptr);
220    break;
221  default:
222    __throw_format_error(
223        "The replacement field arg-id should terminate at a ':' or '}'");
224  }
225
226  _VSTD::visit_format_arg(
227      [&](auto __arg) {
228        if constexpr (same_as<decltype(__arg), monostate>)
229          __throw_format_error("Argument index out of bounds");
230        else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
231          __arg.format(__parse_ctx, __ctx);
232        else {
233          formatter<decltype(__arg), _CharT> __formatter;
234          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
235          __ctx.advance_to(__formatter.format(__arg, __ctx));
236        }
237      },
238      __ctx.arg(__r.__value));
239
240  __begin = __parse_ctx.begin();
241  if (__begin == __end || *__begin != _CharT('}'))
242    __throw_format_error("The replacement field misses a terminating '}'");
243
244  return ++__begin;
245}
246
247template <class _ParseCtx, class _Ctx>
248_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
249__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
250  using _CharT = typename _ParseCtx::char_type;
251  static_assert(same_as<typename _Ctx::char_type, _CharT>);
252
253  const _CharT* __begin = __parse_ctx.begin();
254  const _CharT* __end = __parse_ctx.end();
255  typename _Ctx::iterator __out_it = __ctx.out();
256  while (__begin != __end) {
257    switch (*__begin) {
258    case _CharT('{'):
259      ++__begin;
260      if (__begin == __end)
261        __throw_format_error("The format string terminates at a '{'");
262
263      if (*__begin != _CharT('{')) [[likely]] {
264        __ctx.advance_to(_VSTD::move(__out_it));
265        __begin =
266            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
267        __out_it = __ctx.out();
268
269        // The output is written and __begin points to the next character. So
270        // start the next iteration.
271        continue;
272      }
273      // The string is an escape character.
274      break;
275
276    case _CharT('}'):
277      ++__begin;
278      if (__begin == __end || *__begin != _CharT('}'))
279        __throw_format_error(
280            "The format string contains an invalid escape sequence");
281
282      break;
283    }
284
285    // Copy the character to the output verbatim.
286    *__out_it++ = *__begin++;
287  }
288  return __out_it;
289}
290
291} // namespace __format
292
293template <class _OutIt, class _CharT, class _FormatOutIt>
294requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
295    __vformat_to(
296        _OutIt __out_it, basic_string_view<_CharT> __fmt,
297        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
298  if constexpr (same_as<_OutIt, _FormatOutIt>)
299    return _VSTD::__format::__vformat_to(
300        basic_format_parse_context{__fmt, __args.__size()},
301        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
302  else {
303    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
304    _VSTD::__format::__vformat_to(
305        basic_format_parse_context{__fmt, __args.__size()},
306        _VSTD::__format_context_create(__buffer.make_output_iterator(),
307                                       __args));
308    return _VSTD::move(__buffer).out();
309  }
310}
311
312// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
313// https://reviews.llvm.org/D110499#inline-1180704
314// TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
315template <output_iterator<const char&> _OutIt>
316_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
317vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
318  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
319}
320
321#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
322template <output_iterator<const wchar_t&> _OutIt>
323_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
324vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
325  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
326}
327#endif
328
329template <output_iterator<const char&> _OutIt, class... _Args>
330_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
331format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
332  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
333                           _VSTD::make_format_args(__args...));
334}
335
336#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
337template <output_iterator<const wchar_t&> _OutIt, class... _Args>
338_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
339format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
340  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
341                           _VSTD::make_wformat_args(__args...));
342}
343#endif
344
345_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
346vformat(string_view __fmt, format_args __args) {
347  string __res;
348  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
349  return __res;
350}
351
352#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
353_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
354vformat(wstring_view __fmt, wformat_args __args) {
355  wstring __res;
356  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
357  return __res;
358}
359#endif
360
361template <class... _Args>
362_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
363format(string_view __fmt, const _Args&... __args) {
364  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
365}
366
367#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
368template <class... _Args>
369_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
370format(wstring_view __fmt, const _Args&... __args) {
371  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
372}
373#endif
374
375template <class _Context, class _OutIt, class _CharT>
376_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
377                                                                basic_string_view<_CharT> __fmt,
378                                                                basic_format_args<_Context> __args) {
379  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
380  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
381                                _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
382  return _VSTD::move(__buffer).result();
383}
384
385template <output_iterator<const char&> _OutIt, class... _Args>
386_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
387format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt, const _Args&... __args) {
388  return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt, _VSTD::make_format_args(__args...));
389}
390
391#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
392template <output_iterator<const wchar_t&> _OutIt, class... _Args>
393_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
394format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt, const _Args&... __args) {
395  return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt, _VSTD::make_wformat_args(__args...));
396}
397#endif
398
399template <class _CharT>
400_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
401  __format::__formatted_size_buffer<_CharT> __buffer;
402  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
403                                _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
404  return _VSTD::move(__buffer).result();
405}
406
407template <class... _Args>
408_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(string_view __fmt,
409                                                                                              const _Args&... __args) {
410  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_format_args(__args...)});
411}
412
413#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
414template <class... _Args>
415_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(wstring_view __fmt,
416                                                                                              const _Args&... __args) {
417  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
418}
419#endif
420
421#ifndef _LIBCPP_HAS_NO_LOCALIZATION
422
423template <class _OutIt, class _CharT, class _FormatOutIt>
424requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
425    __vformat_to(
426        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
427        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
428  if constexpr (same_as<_OutIt, _FormatOutIt>)
429    return _VSTD::__format::__vformat_to(
430        basic_format_parse_context{__fmt, __args.__size()},
431        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
432                                       _VSTD::move(__loc)));
433  else {
434    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
435    _VSTD::__format::__vformat_to(
436        basic_format_parse_context{__fmt, __args.__size()},
437        _VSTD::__format_context_create(__buffer.make_output_iterator(),
438                                       __args, _VSTD::move(__loc)));
439    return _VSTD::move(__buffer).out();
440  }
441}
442
443template <output_iterator<const char&> _OutIt>
444_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
445    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
446  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
447                             __args);
448}
449
450#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
451template <output_iterator<const wchar_t&> _OutIt>
452_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
453    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
454  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
455                             __args);
456}
457#endif
458
459template <output_iterator<const char&> _OutIt, class... _Args>
460_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
461    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
462  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
463                           _VSTD::make_format_args(__args...));
464}
465
466#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
467template <output_iterator<const wchar_t&> _OutIt, class... _Args>
468_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
469    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
470  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
471                           _VSTD::make_wformat_args(__args...));
472}
473#endif
474
475_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
476vformat(locale __loc, string_view __fmt, format_args __args) {
477  string __res;
478  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
479                    __args);
480  return __res;
481}
482
483#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
484_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
485vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
486  wstring __res;
487  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
488                    __args);
489  return __res;
490}
491#endif
492
493template <class... _Args>
494_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
495format(locale __loc, string_view __fmt, const _Args&... __args) {
496  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
497                        _VSTD::make_format_args(__args...));
498}
499
500#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
501template <class... _Args>
502_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
503format(locale __loc, wstring_view __fmt, const _Args&... __args) {
504  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
505                        _VSTD::make_wformat_args(__args...));
506}
507#endif
508
509template <class _Context, class _OutIt, class _CharT>
510_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
511                                                                locale __loc, basic_string_view<_CharT> __fmt,
512                                                                basic_format_args<_Context> __args) {
513  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
514  _VSTD::__format::__vformat_to(
515      basic_format_parse_context{__fmt, __args.__size()},
516      _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
517  return _VSTD::move(__buffer).result();
518}
519
520template <output_iterator<const char&> _OutIt, class... _Args>
521_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
522format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, string_view __fmt, const _Args&... __args) {
523  return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt,
524                                               _VSTD::make_format_args(__args...));
525}
526
527#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
528template <output_iterator<const wchar_t&> _OutIt, class... _Args>
529_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
530format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wstring_view __fmt, const _Args&... __args) {
531  return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt,
532                                                _VSTD::make_wformat_args(__args...));
533}
534#endif
535
536template <class _CharT>
537_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
538  __format::__formatted_size_buffer<_CharT> __buffer;
539  _VSTD::__format::__vformat_to(
540      basic_format_parse_context{__fmt, __args.__size()},
541      _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
542  return _VSTD::move(__buffer).result();
543}
544
545template <class... _Args>
546_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
547                                                                                              string_view __fmt,
548                                                                                              const _Args&... __args) {
549  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_format_args(__args...)});
550}
551
552#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
553template <class... _Args>
554_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
555                                                                                              wstring_view __fmt,
556                                                                                              const _Args&... __args) {
557  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
558}
559#endif
560
561#endif // _LIBCPP_HAS_NO_LOCALIZATION
562
563#endif //_LIBCPP_STD_VER > 17
564
565_LIBCPP_END_NAMESPACE_STD
566
567#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
568
569#endif // _LIBCPP_FORMAT
570