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