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_FORMAT_FUNCTIONS
11#define _LIBCPP___FORMAT_FORMAT_FUNCTIONS
12
13// TODO FMT This is added to fix Apple back-deployment.
14#include <version>
15#if !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
16
17#include <__algorithm/clamp.h>
18#include <__availability>
19#include <__concepts/convertible_to.h>
20#include <__concepts/same_as.h>
21#include <__config>
22#include <__debug>
23#include <__format/buffer.h>
24#include <__format/format_arg.h>
25#include <__format/format_arg_store.h>
26#include <__format/format_args.h>
27#include <__format/format_context.h>
28#include <__format/format_error.h>
29#include <__format/format_parse_context.h>
30#include <__format/format_string.h>
31#include <__format/format_to_n_result.h>
32#include <__format/formatter.h>
33#include <__format/formatter_bool.h>
34#include <__format/formatter_char.h>
35#include <__format/formatter_floating_point.h>
36#include <__format/formatter_integer.h>
37#include <__format/formatter_pointer.h>
38#include <__format/formatter_string.h>
39#include <__format/parser_std_format_spec.h>
40#include <__iterator/back_insert_iterator.h>
41#include <__iterator/incrementable_traits.h>
42#include <__variant/monostate.h>
43#include <array>
44#include <string>
45#include <string_view>
46
47#ifndef _LIBCPP_HAS_NO_LOCALIZATION
48#include <locale>
49#endif
50
51#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
52#  pragma GCC system_header
53#endif
54
55_LIBCPP_BEGIN_NAMESPACE_STD
56
57#if _LIBCPP_STD_VER > 17
58
59// TODO FMT Evaluate which templates should be external templates. This
60// improves the efficiency of the header. However since the header is still
61// under heavy development and not all classes are stable it makes no sense
62// to do this optimization now.
63
64using format_args = basic_format_args<format_context>;
65#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
66using wformat_args = basic_format_args<wformat_context>;
67#endif
68
69template <class _Context = format_context, class... _Args>
70_LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&&... __args) {
71  return _VSTD::__format_arg_store<_Context, _Args...>(__args...);
72}
73
74#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
75template <class... _Args>
76_LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&&... __args) {
77  return _VSTD::__format_arg_store<wformat_context, _Args...>(__args...);
78}
79#endif
80
81namespace __format {
82
83/// Helper class parse and handle argument.
84///
85/// When parsing a handle which is not enabled the code is ill-formed.
86/// This helper uses the parser of the appropriate formatter for the stored type.
87template <class _CharT>
88class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
89public:
90  _LIBCPP_HIDE_FROM_ABI
91  constexpr void __parse(basic_format_parse_context<_CharT>& __parse_ctx) const { __parse_(__parse_ctx); }
92
93  template <class _Tp>
94  _LIBCPP_HIDE_FROM_ABI constexpr void __enable() {
95    __parse_ = [](basic_format_parse_context<_CharT>& __parse_ctx) {
96      formatter<_Tp, _CharT> __f;
97      __parse_ctx.advance_to(__f.parse(__parse_ctx));
98    };
99  }
100
101  // Before calling __parse the proper handler needs to be set with __enable.
102  // The default handler isn't a core constant expression.
103  _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()
104      : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {}
105
106private:
107  void (*__parse_)(basic_format_parse_context<_CharT>&);
108};
109
110// Dummy format_context only providing the parts used during constant
111// validation of the basic_format_string.
112template <class _CharT>
113struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context {
114public:
115  using char_type = _CharT;
116
117  _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(
118      const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)
119      : __args_(__args), __handles_(__handles), __size_(__size) {}
120
121  // During the compile-time validation nothing needs to be written.
122  // Therefore all operations of this iterator are a NOP.
123  struct iterator {
124    _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }
125    _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }
126    _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }
127  };
128
129  _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
130    if (__id >= __size_)
131      std::__throw_format_error("Argument index out of bounds");
132    return __args_[__id];
133  }
134
135  _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {
136    if (__id >= __size_)
137      std::__throw_format_error("Argument index out of bounds");
138    return __handles_[__id];
139  }
140
141  _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }
142  _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}
143
144private:
145  const __arg_t* __args_;
146  const __compile_time_handle<_CharT>* __handles_;
147  size_t __size_;
148};
149
150_LIBCPP_HIDE_FROM_ABI
151constexpr void __compile_time_validate_integral(__arg_t __type) {
152  switch (__type) {
153  case __arg_t::__int:
154  case __arg_t::__long_long:
155  case __arg_t::__i128:
156  case __arg_t::__unsigned:
157  case __arg_t::__unsigned_long_long:
158  case __arg_t::__u128:
159    return;
160
161  default:
162    std::__throw_format_error("Argument isn't an integral type");
163  }
164}
165
166// _HasPrecision does the formatter have a precision?
167template <class _CharT, class _Tp, bool _HasPrecision = false>
168_LIBCPP_HIDE_FROM_ABI constexpr void
169__compile_time_validate_argument(basic_format_parse_context<_CharT>& __parse_ctx,
170                                 __compile_time_basic_format_context<_CharT>& __ctx) {
171  formatter<_Tp, _CharT> __formatter;
172  __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
173  // [format.string.std]/7
174  // ... If the corresponding formatting argument is not of integral type, or
175  // its value is negative for precision or non-positive for width, an
176  // exception of type format_error is thrown.
177  //
178  // Validate whether the arguments are integrals.
179  if (__formatter.__parser_.__width_as_arg_)
180    __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__width_));
181
182  if constexpr (_HasPrecision)
183    if (__formatter.__parser_.__precision_as_arg_)
184      __format::__compile_time_validate_integral(__ctx.arg(__formatter.__parser_.__precision_));
185}
186
187// This function is not user facing, so it can directly use the non-standard types of the "variant".
188template <class _CharT>
189_LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(basic_format_parse_context<_CharT>& __parse_ctx,
190                                                                     __compile_time_basic_format_context<_CharT>& __ctx,
191                                                                     __arg_t __type) {
192  switch (__type) {
193  case __arg_t::__none:
194    std::__throw_format_error("Invalid argument");
195  case __arg_t::__boolean:
196    return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);
197  case __arg_t::__char_type:
198    return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);
199  case __arg_t::__int:
200    return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);
201  case __arg_t::__long_long:
202    return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);
203  case __arg_t::__i128:
204#      ifndef _LIBCPP_HAS_NO_INT128
205    return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);
206#      else
207    std::__throw_format_error("Invalid argument");
208#      endif
209    return;
210  case __arg_t::__unsigned:
211    return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);
212  case __arg_t::__unsigned_long_long:
213    return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);
214  case __arg_t::__u128:
215#      ifndef _LIBCPP_HAS_NO_INT128
216    return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);
217#      else
218    std::__throw_format_error("Invalid argument");
219#      endif
220    return;
221  case __arg_t::__float:
222    return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);
223  case __arg_t::__double:
224    return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);
225  case __arg_t::__long_double:
226    return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);
227  case __arg_t::__const_char_type_ptr:
228    return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);
229  case __arg_t::__string_view:
230    return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);
231  case __arg_t::__ptr:
232    return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);
233  case __arg_t::__handle:
234    std::__throw_format_error("Handle should use __compile_time_validate_handle_argument");
235  }
236  std::__throw_format_error("Invalid argument");
237}
238
239template <class _CharT, class _ParseCtx, class _Ctx>
240_LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
241__handle_replacement_field(const _CharT* __begin, const _CharT* __end,
242                           _ParseCtx& __parse_ctx, _Ctx& __ctx) {
243  __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
244
245  bool __parse = *__r.__ptr == _CharT(':');
246  switch (*__r.__ptr) {
247  case _CharT(':'):
248    // The arg-id has a format-specifier, advance the input to the format-spec.
249    __parse_ctx.advance_to(__r.__ptr + 1);
250    break;
251  case _CharT('}'):
252    // The arg-id has no format-specifier.
253    __parse_ctx.advance_to(__r.__ptr);
254    break;
255  default:
256    std::__throw_format_error("The replacement field arg-id should terminate at a ':' or '}'");
257  }
258
259  if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
260    __arg_t __type = __ctx.arg(__r.__value);
261    if (__type == __arg_t::__none)
262      std::__throw_format_error("Argument index out of bounds");
263    else if (__type == __arg_t::__handle)
264      __ctx.__handle(__r.__value).__parse(__parse_ctx);
265    else if (__parse)
266      __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
267  } else
268    _VSTD::__visit_format_arg(
269        [&](auto __arg) {
270          if constexpr (same_as<decltype(__arg), monostate>)
271            std::__throw_format_error("Argument index out of bounds");
272          else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
273            __arg.format(__parse_ctx, __ctx);
274          else {
275            formatter<decltype(__arg), _CharT> __formatter;
276            if (__parse)
277              __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
278            __ctx.advance_to(__formatter.format(__arg, __ctx));
279          }
280        },
281        __ctx.arg(__r.__value));
282
283  __begin = __parse_ctx.begin();
284  if (__begin == __end || *__begin != _CharT('}'))
285    std::__throw_format_error("The replacement field misses a terminating '}'");
286
287  return ++__begin;
288}
289
290template <class _ParseCtx, class _Ctx>
291_LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator
292__vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
293  using _CharT = typename _ParseCtx::char_type;
294  static_assert(same_as<typename _Ctx::char_type, _CharT>);
295
296  const _CharT* __begin = __parse_ctx.begin();
297  const _CharT* __end = __parse_ctx.end();
298  typename _Ctx::iterator __out_it = __ctx.out();
299  while (__begin != __end) {
300    switch (*__begin) {
301    case _CharT('{'):
302      ++__begin;
303      if (__begin == __end)
304        std::__throw_format_error("The format string terminates at a '{'");
305
306      if (*__begin != _CharT('{')) [[likely]] {
307        __ctx.advance_to(_VSTD::move(__out_it));
308        __begin =
309            __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
310        __out_it = __ctx.out();
311
312        // The output is written and __begin points to the next character. So
313        // start the next iteration.
314        continue;
315      }
316      // The string is an escape character.
317      break;
318
319    case _CharT('}'):
320      ++__begin;
321      if (__begin == __end || *__begin != _CharT('}'))
322        std::__throw_format_error("The format string contains an invalid escape sequence");
323
324      break;
325    }
326
327    // Copy the character to the output verbatim.
328    *__out_it++ = *__begin++;
329  }
330  return __out_it;
331}
332
333} // namespace __format
334
335template <class _CharT, class... _Args>
336struct _LIBCPP_TEMPLATE_VIS basic_format_string {
337  template <class _Tp>
338    requires convertible_to<const _Tp&, basic_string_view<_CharT>>
339  consteval basic_format_string(const _Tp& __str) : __str_{__str} {
340    __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
341                           _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
342  }
343
344  _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT constexpr basic_string_view<_CharT> get() const noexcept {
345    return __str_;
346  }
347
348private:
349  basic_string_view<_CharT> __str_;
350
351  using _Context = __format::__compile_time_basic_format_context<_CharT>;
352
353  static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{
354      __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};
355
356  // TODO FMT remove this work-around when the AIX ICE has been resolved.
357#    if defined(_AIX) && defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER < 1400
358  template <class _Tp>
359  static constexpr __format::__compile_time_handle<_CharT> __get_handle() {
360    __format::__compile_time_handle<_CharT> __handle;
361    if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
362      __handle.template __enable<_Tp>();
363
364    return __handle;
365  }
366
367  static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{
368      __get_handle<_Args>()...};
369#    else
370  static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {
371    using _Tp = remove_cvref_t<_Args>;
372    __format::__compile_time_handle<_CharT> __handle;
373    if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
374      __handle.template __enable<_Tp>();
375
376    return __handle;
377  }()...};
378#    endif
379};
380
381template <class... _Args>
382using format_string = basic_format_string<char, type_identity_t<_Args>...>;
383
384#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
385template <class... _Args>
386using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>;
387#endif
388
389template <class _OutIt, class _CharT, class _FormatOutIt>
390requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
391    __vformat_to(
392        _OutIt __out_it, basic_string_view<_CharT> __fmt,
393        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
394  if constexpr (same_as<_OutIt, _FormatOutIt>)
395    return _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
396                                         _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
397  else {
398    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
399    _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
400                                  _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
401    return _VSTD::move(__buffer).__out_it();
402  }
403}
404
405// The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
406// https://reviews.llvm.org/D110499#inline-1180704
407// TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
408template <output_iterator<const char&> _OutIt>
409_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
410vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
411  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
412}
413
414#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
415template <output_iterator<const wchar_t&> _OutIt>
416_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
417vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
418  return _VSTD::__vformat_to(_VSTD::move(__out_it), __fmt, __args);
419}
420#endif
421
422template <output_iterator<const char&> _OutIt, class... _Args>
423_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
424format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) {
425  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(),
426                           _VSTD::make_format_args(__args...));
427}
428
429#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
430template <output_iterator<const wchar_t&> _OutIt, class... _Args>
431_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
432format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {
433  return _VSTD::vformat_to(_VSTD::move(__out_it), __fmt.get(),
434                           _VSTD::make_wformat_args(__args...));
435}
436#endif
437
438_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
439vformat(string_view __fmt, format_args __args) {
440  string __res;
441  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
442  return __res;
443}
444
445#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
446_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
447vformat(wstring_view __fmt, wformat_args __args) {
448  wstring __res;
449  _VSTD::vformat_to(_VSTD::back_inserter(__res), __fmt, __args);
450  return __res;
451}
452#endif
453
454template <class... _Args>
455_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(format_string<_Args...> __fmt,
456                                                                                      _Args&&... __args) {
457  return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...));
458}
459
460#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
461template <class... _Args>
462_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
463format(wformat_string<_Args...> __fmt, _Args&&... __args) {
464  return _VSTD::vformat(__fmt.get(), _VSTD::make_wformat_args(__args...));
465}
466#endif
467
468template <class _Context, class _OutIt, class _CharT>
469_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
470                                                                basic_string_view<_CharT> __fmt,
471                                                                basic_format_args<_Context> __args) {
472  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
473  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
474                                _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
475  return _VSTD::move(__buffer).__result();
476}
477
478template <output_iterator<const char&> _OutIt, class... _Args>
479_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
480format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) {
481  return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_format_args(__args...));
482}
483
484#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
485template <output_iterator<const wchar_t&> _OutIt, class... _Args>
486_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
487format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt,
488            _Args&&... __args) {
489  return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, __fmt.get(), _VSTD::make_wformat_args(__args...));
490}
491#endif
492
493template <class _CharT>
494_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
495  __format::__formatted_size_buffer<_CharT> __buffer;
496  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
497                                _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
498  return _VSTD::move(__buffer).__result();
499}
500
501template <class... _Args>
502_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
503formatted_size(format_string<_Args...> __fmt, _Args&&... __args) {
504  return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)});
505}
506
507#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
508template <class... _Args>
509_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
510formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) {
511  return _VSTD::__vformatted_size(__fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)});
512}
513#endif
514
515#ifndef _LIBCPP_HAS_NO_LOCALIZATION
516
517template <class _OutIt, class _CharT, class _FormatOutIt>
518requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
519    __vformat_to(
520        _OutIt __out_it, locale __loc, basic_string_view<_CharT> __fmt,
521        basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
522  if constexpr (same_as<_OutIt, _FormatOutIt>)
523    return _VSTD::__format::__vformat_to(
524        basic_format_parse_context{__fmt, __args.__size()},
525        _VSTD::__format_context_create(_VSTD::move(__out_it), __args, _VSTD::move(__loc)));
526  else {
527    __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
528    _VSTD::__format::__vformat_to(
529        basic_format_parse_context{__fmt, __args.__size()},
530        _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
531    return _VSTD::move(__buffer).__out_it();
532  }
533}
534
535template <output_iterator<const char&> _OutIt>
536_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
537    _OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
538  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
539                             __args);
540}
541
542#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
543template <output_iterator<const wchar_t&> _OutIt>
544_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt vformat_to(
545    _OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
546  return _VSTD::__vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt,
547                             __args);
548}
549#endif
550
551template <output_iterator<const char&> _OutIt, class... _Args>
552_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
553format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
554  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(),
555                           _VSTD::make_format_args(__args...));
556}
557
558#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
559template <output_iterator<const wchar_t&> _OutIt, class... _Args>
560_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT _OutIt
561format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
562  return _VSTD::vformat_to(_VSTD::move(__out_it), _VSTD::move(__loc), __fmt.get(),
563                           _VSTD::make_wformat_args(__args...));
564}
565#endif
566
567_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string
568vformat(locale __loc, string_view __fmt, format_args __args) {
569  string __res;
570  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
571                    __args);
572  return __res;
573}
574
575#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
576_LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
577vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
578  wstring __res;
579  _VSTD::vformat_to(_VSTD::back_inserter(__res), _VSTD::move(__loc), __fmt,
580                    __args);
581  return __res;
582}
583#endif
584
585template <class... _Args>
586_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT string format(locale __loc,
587                                                                                      format_string<_Args...> __fmt,
588                                                                                      _Args&&... __args) {
589  return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(),
590                        _VSTD::make_format_args(__args...));
591}
592
593#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
594template <class... _Args>
595_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT wstring
596format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
597  return _VSTD::vformat(_VSTD::move(__loc), __fmt.get(),
598                        _VSTD::make_wformat_args(__args...));
599}
600#endif
601
602template <class _Context, class _OutIt, class _CharT>
603_LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n,
604                                                                locale __loc, basic_string_view<_CharT> __fmt,
605                                                                basic_format_args<_Context> __args) {
606  __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
607  _VSTD::__format::__vformat_to(
608      basic_format_parse_context{__fmt, __args.__size()},
609      _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
610  return _VSTD::move(__buffer).__result();
611}
612
613template <output_iterator<const char&> _OutIt, class... _Args>
614_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
615format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt,
616            _Args&&... __args) {
617  return _VSTD::__vformat_to_n<format_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(),
618                                               _VSTD::make_format_args(__args...));
619}
620
621#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
622template <output_iterator<const wchar_t&> _OutIt, class... _Args>
623_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
624format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt,
625            _Args&&... __args) {
626  return _VSTD::__vformat_to_n<wformat_context>(_VSTD::move(__out_it), __n, _VSTD::move(__loc), __fmt.get(),
627                                                _VSTD::make_wformat_args(__args...));
628}
629#endif
630
631template <class _CharT>
632_LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
633  __format::__formatted_size_buffer<_CharT> __buffer;
634  _VSTD::__format::__vformat_to(
635      basic_format_parse_context{__fmt, __args.__size()},
636      _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
637  return _VSTD::move(__buffer).__result();
638}
639
640template <class... _Args>
641_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
642formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
643  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_format_args(__args...)});
644}
645
646#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
647template <class... _Args>
648_LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT size_t
649formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
650  return _VSTD::__vformatted_size(_VSTD::move(__loc), __fmt.get(), basic_format_args{_VSTD::make_wformat_args(__args...)});
651}
652#endif
653
654#endif // _LIBCPP_HAS_NO_LOCALIZATION
655
656
657#endif //_LIBCPP_STD_VER > 17
658
659_LIBCPP_END_NAMESPACE_STD
660
661#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)
662
663#endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS
664