xref: /llvm-project-15.0.7/libcxx/include/format (revision faef447e)
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/enable_insertable.h>
131#include <__format/format_arg.h>
132#include <__format/format_args.h>
133#include <__format/format_context.h>
134#include <__format/format_error.h>
135#include <__format/format_fwd.h>
136#include <__format/format_parse_context.h>
137#include <__format/format_string.h>
138#include <__format/format_to_n_result.h>
139#include <__format/formatter.h>
140#include <__format/formatter_bool.h>
141#include <__format/formatter_char.h>
142#include <__format/formatter_floating_point.h>
143#include <__format/formatter_integer.h>
144#include <__format/formatter_pointer.h>
145#include <__format/formatter_string.h>
146#include <__format/parser_std_format_spec.h>
147#include <__variant/monostate.h>
148#include <array>
149#include <concepts>
150#include <string>
151#include <string_view>
152#include <type_traits>
153
154#ifndef _LIBCPP_HAS_NO_LOCALIZATION
155#include <locale>
156#endif
157
158#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
159#  pragma GCC system_header
160#endif
161
162_LIBCPP_BEGIN_NAMESPACE_STD
163
164#if _LIBCPP_STD_VER > 17
165
166// TODO FMT Move the implementation in this file to its own granular headers.
167
168// TODO FMT Evaluate which templates should be external templates. This
169// improves the efficiency of the header. However since the header is still
170// under heavy development and not all classes are stable it makes no sense
171// to do this optimization now.
172
173using format_args = basic_format_args<format_context>;
174#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
175using wformat_args = basic_format_args<wformat_context>;
176#endif
177
178template <class _Context, class... _Args>
179struct _LIBCPP_TEMPLATE_VIS __format_arg_store {
180  // TODO FMT Use a built-in array.
181  array<basic_format_arg<_Context>, sizeof...(_Args)> __args;
182};
183
184template <class _Context = format_context, class... _Args>
185_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...>
186make_format_args(const _Args&... __args) {
187  return {basic_format_arg<_Context>(__args)...};
188}
189
190#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
191template <class... _Args>
192_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...>
193make_wformat_args(const _Args&... __args) {
194  return _VSTD::make_format_args<wformat_context>(__args...);
195}
196#endif
197
198namespace __format {
199
200template <class _CharT, class _ParseCtx, class _Ctx>
201_LIBCPP_HIDE_FROM_ABI const _CharT*
202__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
203                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
204  __format::__parse_number_result __r =
205      __format::__parse_arg_id(__begin, __end, __parse_ctx);
206
207  switch (*__r.__ptr) {
208  case _CharT(':'):
209    // The arg-id has a format-specifier, advance the input to the format-spec.
210    __parse_ctx.advance_to(__r.__ptr + 1);
211    break;
212  case _CharT('}'):
213    // The arg-id has no format-specifier.
214    __parse_ctx.advance_to(__r.__ptr);
215    break;
216  default:
217    __throw_format_error(
218        "The replacement field arg-id should terminate at a ':' or '}'");
219  }
220
221  _VSTD::visit_format_arg(
222      [&](auto __arg) {
223        if constexpr (same_as<decltype(__arg), monostate>)
224          __throw_format_error("Argument index out of bounds");
225        else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
226          __arg.format(__parse_ctx, __ctx);
227        else {
228          formatter<decltype(__arg), _CharT> __formatter;
229          __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
230          __ctx.advance_to(__formatter.format(__arg, __ctx));
231        }
232      },
233      __ctx.arg(__r.__value));
234
235  __begin = __parse_ctx.begin();
236  if (__begin == __end || *__begin != _CharT('}'))
237    __throw_format_error("The replacement field misses a terminating '}'");
238
239  return ++__begin;
240}
241
242template <class _ParseCtx, class _Ctx>
243_LIBCPP_HIDE_FROM_ABI typename _Ctx::iterator
244__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
245  using _CharT = typename _ParseCtx::char_type;
246  static_assert(same_as<typename _Ctx::char_type, _CharT>);
247
248  const _CharT* __begin = __parse_ctx.begin();
249  const _CharT* __end = __parse_ctx.end();
250  typename _Ctx::iterator __out_it = __ctx.out();
251  while (__begin != __end) {
252    switch (*__begin) {
253    case _CharT('{'):
254      ++__begin;
255      if (__begin == __end)
256        __throw_format_error("The format string terminates at a '{'");
257
258      if (*__begin != _CharT('{')) [[likely]] {
259        __ctx.advance_to(_VSTD::move(__out_it));
260        __begin =
261            __handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
262        __out_it = __ctx.out();
263
264        // The output is written and __begin points to the next character. So
265        // start the next iteration.
266        continue;
267      }
268      // The string is an escape character.
269      break;
270
271    case _CharT('}'):
272      ++__begin;
273      if (__begin == __end || *__begin != _CharT('}'))
274        __throw_format_error(
275            "The format string contains an invalid escape sequence");
276
277      break;
278    }
279
280    // Copy the character to the output verbatim.
281    *__out_it++ = *__begin++;
282  }
283  return __out_it;
284}
285
286} // namespace __format
287
288template <class _OutIt, class _CharT, class _FormatOutIt>
289requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
290    __vformat_to(
291        _OutIt __out_it, basic_string_view<_CharT> __fmt,
292        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
293  if constexpr (same_as<_OutIt, _FormatOutIt>)
294    return _VSTD::__format::__vformat_to(
295        basic_format_parse_context{__fmt, __args.__size()},
296        _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
297  else {
298    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
299    _VSTD::__format::__vformat_to(
300        basic_format_parse_context{__fmt, __args.__size()},
301        _VSTD::__format_context_create(__buffer.make_output_iterator(),
302                                       __args));
303    return _VSTD::move(__buffer).out();
304  }
305}
306
307template <output_iterator<const char&> _OutIt>
308_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
309vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
310  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
311}
312
313#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
314template <output_iterator<const wchar_t&> _OutIt>
315_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
316vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
317  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
318}
319#endif
320
321template <output_iterator<const char&> _OutIt, class... _Args>
322_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
323format_to(_OutIt __out_it, string_view __fmt, const _Args&... __args) {
324  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
325                           _VSTD::make_format_args(__args...));
326}
327
328#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
329template <output_iterator<const wchar_t&> _OutIt, class... _Args>
330_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
331format_to(_OutIt __out_it, wstring_view __fmt, const _Args&... __args) {
332  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt,
333                           _VSTD::make_wformat_args(__args...));
334}
335#endif
336
337_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
338vformat(string_view __fmt, format_args __args) {
339  string __res;
340  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
341  return __res;
342}
343
344#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
345_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
346vformat(wstring_view __fmt, wformat_args __args) {
347  wstring __res;
348  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
349  return __res;
350}
351#endif
352
353template <class... _Args>
354_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
355format(string_view __fmt, const _Args&... __args) {
356  return _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
357}
358
359#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
360template <class... _Args>
361_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
362format(wstring_view __fmt, const _Args&... __args) {
363  return _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
364}
365#endif
366
367template <output_iterator<const char&> _OutIt, class... _Args>
368_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
369format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
370            const _Args&... __args) {
371  // TODO FMT Improve PoC: using std::string is inefficient.
372  string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
373  iter_difference_t<_OutIt> __s = __str.size();
374  iter_difference_t<_OutIt> __m =
375      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
376  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
377  return {_VSTD::move(__out_it), __s};
378}
379
380#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
381template <output_iterator<const wchar_t&> _OutIt, class... _Args>
382_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
383format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
384            const _Args&... __args) {
385  // TODO FMT Improve PoC: using std::string is inefficient.
386  wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
387  iter_difference_t<_OutIt> __s = __str.size();
388  iter_difference_t<_OutIt> __m =
389      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
390  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
391  return {_VSTD::move(__out_it), __s};
392}
393#endif
394
395template <class _CharT>
396_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
397  __format::__formatted_size_buffer<_CharT> __buffer;
398  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
399                                _VSTD::__format_context_create(__buffer.make_output_iterator(), __args));
400  return _VSTD::move(__buffer).result();
401}
402
403template <class... _Args>
404_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(string_view __fmt,
405                                                                                              const _Args&... __args) {
406  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_format_args(__args...)});
407}
408
409#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
410template <class... _Args>
411_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(wstring_view __fmt,
412                                                                                              const _Args&... __args) {
413  return _VSTD::__vformatted_size(__fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
414}
415#endif
416
417#ifndef _LIBCPP_HAS_NO_LOCALIZATION
418
419template <class _OutIt, class _CharT, class _FormatOutIt>
420requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
421    __vformat_to(
422        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
423        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
424  if constexpr (same_as<_OutIt, _FormatOutIt>)
425    return _VSTD::__format::__vformat_to(
426        basic_format_parse_context{__fmt, __args.__size()},
427        _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
428                                       _VSTD::move(__loc)));
429  else {
430    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
431    _VSTD::__format::__vformat_to(
432        basic_format_parse_context{__fmt, __args.__size()},
433        _VSTD::__format_context_create(__buffer.make_output_iterator(),
434                                       __args, _VSTD::move(__loc)));
435    return _VSTD::move(__buffer).out();
436  }
437}
438
439template <output_iterator<const char&> _OutIt>
440_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
441    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
442  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
443                             __args);
444}
445
446#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
447template <output_iterator<const wchar_t&> _OutIt>
448_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
449    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
450  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
451                             __args);
452}
453#endif
454
455template <output_iterator<const char&> _OutIt, class... _Args>
456_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
457    _OutIt __out_it, locale __loc, string_view __fmt, const _Args&... __args) {
458  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
459                           _VSTD::make_format_args(__args...));
460}
461
462#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
463template <output_iterator<const wchar_t&> _OutIt, class... _Args>
464_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt format_to(
465    _OutIt __out_it, locale __loc, wstring_view __fmt, const _Args&... __args) {
466  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
467                           _VSTD::make_wformat_args(__args...));
468}
469#endif
470
471_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
472vformat(locale __loc, string_view __fmt, format_args __args) {
473  string __res;
474  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
475                    __args);
476  return __res;
477}
478
479#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
480_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
481vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
482  wstring __res;
483  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
484                    __args);
485  return __res;
486}
487#endif
488
489template <class... _Args>
490_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
491format(locale __loc, string_view __fmt, const _Args&... __args) {
492  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
493                        _VSTD::make_format_args(__args...));
494}
495
496#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
497template <class... _Args>
498_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
499format(locale __loc, wstring_view __fmt, const _Args&... __args) {
500  return _VSTD::vformat(_VSTD::move(__loc), __fmt,
501                        _VSTD::make_wformat_args(__args...));
502}
503#endif
504
505template <output_iterator<const char&> _OutIt, class... _Args>
506_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
507format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
508            string_view __fmt, const _Args&... __args) {
509  // TODO FMT Improve PoC: using std::string is inefficient.
510  string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
511                                _VSTD::make_format_args(__args...));
512  iter_difference_t<_OutIt> __s = __str.size();
513  iter_difference_t<_OutIt> __m =
514      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
515  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
516  return {_VSTD::move(__out_it), __s};
517}
518
519#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
520template <output_iterator<const wchar_t&> _OutIt, class... _Args>
521_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,
523            wstring_view __fmt, const _Args&... __args) {
524  // TODO FMT Improve PoC: using std::string is inefficient.
525  wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
526                                 _VSTD::make_wformat_args(__args...));
527  iter_difference_t<_OutIt> __s = __str.size();
528  iter_difference_t<_OutIt> __m =
529      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
530  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
531  return {_VSTD::move(__out_it), __s};
532}
533#endif
534
535template <class _CharT>
536_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
537  __format::__formatted_size_buffer<_CharT> __buffer;
538  _VSTD::__format::__vformat_to(
539      basic_format_parse_context{__fmt, __args.__size()},
540      _VSTD::__format_context_create(__buffer.make_output_iterator(), __args, _VSTD::move(__loc)));
541  return _VSTD::move(__buffer).result();
542}
543
544template <class... _Args>
545_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
546                                                                                              string_view __fmt,
547                                                                                              const _Args&... __args) {
548  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_format_args(__args...)});
549}
550
551#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
552template <class... _Args>
553_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t formatted_size(locale __loc,
554                                                                                              wstring_view __fmt,
555                                                                                              const _Args&... __args) {
556  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
557}
558#endif
559
560#endif // _LIBCPP_HAS_NO_LOCALIZATION
561
562#endif //_LIBCPP_STD_VER > 17
563
564_LIBCPP_END_NAMESPACE_STD
565
566#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
567
568#endif // _LIBCPP_FORMAT
569