xref: /llvm-project/libcxx/include/__format/format_functions.h (revision 14b44179cb61dd551c911dea54de57b588621005)
100798e50SMark de Wever // -*- C++ -*-
200798e50SMark de Wever //===----------------------------------------------------------------------===//
300798e50SMark de Wever //
400798e50SMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
500798e50SMark de Wever // See https://llvm.org/LICENSE.txt for license information.
600798e50SMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
700798e50SMark de Wever //
800798e50SMark de Wever //===----------------------------------------------------------------------===//
900798e50SMark de Wever 
1000798e50SMark de Wever #ifndef _LIBCPP___FORMAT_FORMAT_FUNCTIONS
1100798e50SMark de Wever #define _LIBCPP___FORMAT_FORMAT_FUNCTIONS
1200798e50SMark de Wever 
1300798e50SMark de Wever #include <__algorithm/clamp.h>
1400798e50SMark de Wever #include <__concepts/convertible_to.h>
1500798e50SMark de Wever #include <__concepts/same_as.h>
1600798e50SMark de Wever #include <__config>
1700798e50SMark de Wever #include <__format/buffer.h>
1800798e50SMark de Wever #include <__format/format_arg.h>
1900798e50SMark de Wever #include <__format/format_arg_store.h>
2000798e50SMark de Wever #include <__format/format_args.h>
2100798e50SMark de Wever #include <__format/format_context.h>
2200798e50SMark de Wever #include <__format/format_error.h>
2300798e50SMark de Wever #include <__format/format_parse_context.h>
2400798e50SMark de Wever #include <__format/format_string.h>
2500798e50SMark de Wever #include <__format/format_to_n_result.h>
2600798e50SMark de Wever #include <__format/formatter.h>
2700798e50SMark de Wever #include <__format/formatter_bool.h>
2800798e50SMark de Wever #include <__format/formatter_char.h>
2900798e50SMark de Wever #include <__format/formatter_floating_point.h>
3000798e50SMark de Wever #include <__format/formatter_integer.h>
3100798e50SMark de Wever #include <__format/formatter_pointer.h>
3200798e50SMark de Wever #include <__format/formatter_string.h>
3300798e50SMark de Wever #include <__format/parser_std_format_spec.h>
341562e514SLouis Dionne #include <__iterator/concepts.h>
3500798e50SMark de Wever #include <__iterator/incrementable_traits.h>
36d5ce68afSIan Anderson #include <__iterator/iterator_traits.h> // iter_value_t
3700798e50SMark de Wever #include <__variant/monostate.h>
3800798e50SMark de Wever #include <array>
3933fe4dc9SIan Anderson #include <string>
4000798e50SMark de Wever #include <string_view>
4100798e50SMark de Wever 
42c6f3b7bcSNikolas Klauser #if _LIBCPP_HAS_LOCALIZATION
435bcb7814SNikolas Klauser #  include <__locale>
4400798e50SMark de Wever #endif
4500798e50SMark de Wever 
4600798e50SMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
4700798e50SMark de Wever #  pragma GCC system_header
4800798e50SMark de Wever #endif
4900798e50SMark de Wever 
507b462251SLouis Dionne _LIBCPP_PUSH_MACROS
517b462251SLouis Dionne #include <__undef_macros>
527b462251SLouis Dionne 
5300798e50SMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD
5400798e50SMark de Wever 
554f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20
5600798e50SMark de Wever 
5700798e50SMark de Wever // TODO FMT Evaluate which templates should be external templates. This
5800798e50SMark de Wever // improves the efficiency of the header. However since the header is still
5900798e50SMark de Wever // under heavy development and not all classes are stable it makes no sense
6000798e50SMark de Wever // to do this optimization now.
6100798e50SMark de Wever 
6200798e50SMark de Wever using format_args = basic_format_args<format_context>;
63c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
6400798e50SMark de Wever using wformat_args = basic_format_args<wformat_context>;
6500798e50SMark de Wever #  endif
6600798e50SMark de Wever 
6700798e50SMark de Wever template <class _Context = format_context, class... _Args>
6883bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<_Context, _Args...> make_format_args(_Args&... __args) {
69683bc94eSLouis Dionne   return std::__format_arg_store<_Context, _Args...>(__args...);
7000798e50SMark de Wever }
7100798e50SMark de Wever 
72c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
7300798e50SMark de Wever template <class... _Args>
7483bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __format_arg_store<wformat_context, _Args...> make_wformat_args(_Args&... __args) {
75683bc94eSLouis Dionne   return std::__format_arg_store<wformat_context, _Args...>(__args...);
7600798e50SMark de Wever }
7700798e50SMark de Wever #  endif
7800798e50SMark de Wever 
7900798e50SMark de Wever namespace __format {
8000798e50SMark de Wever 
8100798e50SMark de Wever /// Helper class parse and handle argument.
8200798e50SMark de Wever ///
8300798e50SMark de Wever /// When parsing a handle which is not enabled the code is ill-formed.
8400798e50SMark de Wever /// This helper uses the parser of the appropriate formatter for the stored type.
8500798e50SMark de Wever template <class _CharT>
8600798e50SMark de Wever class _LIBCPP_TEMPLATE_VIS __compile_time_handle {
8700798e50SMark de Wever public:
88b51e8acdSMark de Wever   template <class _ParseContext>
89b51e8acdSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void __parse(_ParseContext& __ctx) const {
90b51e8acdSMark de Wever     __parse_(__ctx);
91b51e8acdSMark de Wever   }
9200798e50SMark de Wever 
9300798e50SMark de Wever   template <class _Tp>
9400798e50SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void __enable() {
95b51e8acdSMark de Wever     __parse_ = [](basic_format_parse_context<_CharT>& __ctx) {
9600798e50SMark de Wever       formatter<_Tp, _CharT> __f;
97b51e8acdSMark de Wever       __ctx.advance_to(__f.parse(__ctx));
9800798e50SMark de Wever     };
9900798e50SMark de Wever   }
10000798e50SMark de Wever 
10100798e50SMark de Wever   // Before calling __parse the proper handler needs to be set with __enable.
10200798e50SMark de Wever   // The default handler isn't a core constant expression.
10300798e50SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr __compile_time_handle()
104c1905b1cSMark de Wever       : __parse_([](basic_format_parse_context<_CharT>&) { std::__throw_format_error("Not a handle"); }) {}
10500798e50SMark de Wever 
10600798e50SMark de Wever private:
10700798e50SMark de Wever   void (*__parse_)(basic_format_parse_context<_CharT>&);
10800798e50SMark de Wever };
10900798e50SMark de Wever 
11000798e50SMark de Wever // Dummy format_context only providing the parts used during constant
11100798e50SMark de Wever // validation of the basic_format_string.
11200798e50SMark de Wever template <class _CharT>
11300798e50SMark de Wever struct _LIBCPP_TEMPLATE_VIS __compile_time_basic_format_context {
11400798e50SMark de Wever public:
11500798e50SMark de Wever   using char_type = _CharT;
11600798e50SMark de Wever 
11700798e50SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr explicit __compile_time_basic_format_context(
11800798e50SMark de Wever       const __arg_t* __args, const __compile_time_handle<_CharT>* __handles, size_t __size)
11900798e50SMark de Wever       : __args_(__args), __handles_(__handles), __size_(__size) {}
12000798e50SMark de Wever 
12100798e50SMark de Wever   // During the compile-time validation nothing needs to be written.
12200798e50SMark de Wever   // Therefore all operations of this iterator are a NOP.
12300798e50SMark de Wever   struct iterator {
12400798e50SMark de Wever     _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator=(_CharT) { return *this; }
12500798e50SMark de Wever     _LIBCPP_HIDE_FROM_ABI constexpr iterator& operator*() { return *this; }
12600798e50SMark de Wever     _LIBCPP_HIDE_FROM_ABI constexpr iterator operator++(int) { return *this; }
12700798e50SMark de Wever   };
12800798e50SMark de Wever 
12900798e50SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr __arg_t arg(size_t __id) const {
13000798e50SMark de Wever     if (__id >= __size_)
131402eb2efSMark de Wever       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
13200798e50SMark de Wever     return __args_[__id];
13300798e50SMark de Wever   }
13400798e50SMark de Wever 
13500798e50SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr const __compile_time_handle<_CharT>& __handle(size_t __id) const {
13600798e50SMark de Wever     if (__id >= __size_)
137402eb2efSMark de Wever       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
13800798e50SMark de Wever     return __handles_[__id];
13900798e50SMark de Wever   }
14000798e50SMark de Wever 
14100798e50SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr iterator out() { return {}; }
14200798e50SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(iterator) {}
14300798e50SMark de Wever 
14400798e50SMark de Wever private:
14500798e50SMark de Wever   const __arg_t* __args_;
14600798e50SMark de Wever   const __compile_time_handle<_CharT>* __handles_;
14700798e50SMark de Wever   size_t __size_;
14800798e50SMark de Wever };
14900798e50SMark de Wever 
150d8516518SMark de Wever // [format.string.std]/8
151d8516518SMark de Wever // If { arg-idopt } is used in a width or precision, the value of the
152d8516518SMark de Wever // corresponding formatting argument is used in its place. If the
153d8516518SMark de Wever // corresponding formatting argument is not of standard signed or unsigned
154d8516518SMark de Wever // integer type, or its value is negative for precision or non-positive for
155d8516518SMark de Wever // width, an exception of type format_error is thrown.
156d8516518SMark de Wever //
157d8516518SMark de Wever // _HasPrecision does the formatter have a precision?
158d8516518SMark de Wever template <class _CharT, class _Tp, bool _HasPrecision = false>
159d8516518SMark de Wever _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_validate_argument(
160d8516518SMark de Wever     basic_format_parse_context<_CharT>& __parse_ctx, __compile_time_basic_format_context<_CharT>& __ctx) {
161d8516518SMark de Wever   auto __validate_type = [](__arg_t __type) {
162d8516518SMark de Wever     // LWG3720 originally allowed "signed or unsigned integer types", however
163d8516518SMark de Wever     // the final version explicitly changed it to "*standard* signed or unsigned
164d8516518SMark de Wever     // integer types". It's trivial to use 128-bit integrals in libc++'s
165d8516518SMark de Wever     // implementation, but other implementations may not implement it.
166d8516518SMark de Wever     // (Using a width or precision, that does not fit in 64-bits, sounds very
167d8516518SMark de Wever     // unlikely in real world code.)
16800798e50SMark de Wever     switch (__type) {
16900798e50SMark de Wever     case __arg_t::__int:
17000798e50SMark de Wever     case __arg_t::__long_long:
17100798e50SMark de Wever     case __arg_t::__unsigned:
17200798e50SMark de Wever     case __arg_t::__unsigned_long_long:
17300798e50SMark de Wever       return;
17400798e50SMark de Wever 
17500798e50SMark de Wever     default:
176d8516518SMark de Wever       std::__throw_format_error("Replacement argument isn't a standard signed or unsigned integer type");
17700798e50SMark de Wever     }
178d8516518SMark de Wever   };
17900798e50SMark de Wever 
18000798e50SMark de Wever   formatter<_Tp, _CharT> __formatter;
18100798e50SMark de Wever   __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
18200798e50SMark de Wever   if (__formatter.__parser_.__width_as_arg_)
183d8516518SMark de Wever     __validate_type(__ctx.arg(__formatter.__parser_.__width_));
18400798e50SMark de Wever 
18500798e50SMark de Wever   if constexpr (_HasPrecision)
18600798e50SMark de Wever     if (__formatter.__parser_.__precision_as_arg_)
187d8516518SMark de Wever       __validate_type(__ctx.arg(__formatter.__parser_.__precision_));
18800798e50SMark de Wever }
18900798e50SMark de Wever 
190e948cab0SMark de Wever // This function is not user facing, so it can directly use the non-standard types of the "variant".
19100798e50SMark de Wever template <class _CharT>
1929783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr void __compile_time_visit_format_arg(
1939783f28cSLouis Dionne     basic_format_parse_context<_CharT>& __parse_ctx,
19400798e50SMark de Wever     __compile_time_basic_format_context<_CharT>& __ctx,
19500798e50SMark de Wever     __arg_t __type) {
19600798e50SMark de Wever   switch (__type) {
19700798e50SMark de Wever   case __arg_t::__none:
198c1905b1cSMark de Wever     std::__throw_format_error("Invalid argument");
19900798e50SMark de Wever   case __arg_t::__boolean:
20000798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, bool>(__parse_ctx, __ctx);
20100798e50SMark de Wever   case __arg_t::__char_type:
20200798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, _CharT>(__parse_ctx, __ctx);
20300798e50SMark de Wever   case __arg_t::__int:
20400798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, int>(__parse_ctx, __ctx);
20500798e50SMark de Wever   case __arg_t::__long_long:
20600798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, long long>(__parse_ctx, __ctx);
20700798e50SMark de Wever   case __arg_t::__i128:
208ba87515fSNikolas Klauser #  if _LIBCPP_HAS_INT128
20900798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, __int128_t>(__parse_ctx, __ctx);
21000798e50SMark de Wever #  else
211c1905b1cSMark de Wever     std::__throw_format_error("Invalid argument");
21200798e50SMark de Wever #  endif
21300798e50SMark de Wever     return;
21400798e50SMark de Wever   case __arg_t::__unsigned:
21500798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, unsigned>(__parse_ctx, __ctx);
21600798e50SMark de Wever   case __arg_t::__unsigned_long_long:
21700798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, unsigned long long>(__parse_ctx, __ctx);
21800798e50SMark de Wever   case __arg_t::__u128:
219ba87515fSNikolas Klauser #  if _LIBCPP_HAS_INT128
22000798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, __uint128_t>(__parse_ctx, __ctx);
22100798e50SMark de Wever #  else
222c1905b1cSMark de Wever     std::__throw_format_error("Invalid argument");
22300798e50SMark de Wever #  endif
22400798e50SMark de Wever     return;
22500798e50SMark de Wever   case __arg_t::__float:
22600798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, float, true>(__parse_ctx, __ctx);
22700798e50SMark de Wever   case __arg_t::__double:
22800798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, double, true>(__parse_ctx, __ctx);
22900798e50SMark de Wever   case __arg_t::__long_double:
23000798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, long double, true>(__parse_ctx, __ctx);
23100798e50SMark de Wever   case __arg_t::__const_char_type_ptr:
23200798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, const _CharT*, true>(__parse_ctx, __ctx);
23300798e50SMark de Wever   case __arg_t::__string_view:
23400798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, basic_string_view<_CharT>, true>(__parse_ctx, __ctx);
23500798e50SMark de Wever   case __arg_t::__ptr:
23600798e50SMark de Wever     return __format::__compile_time_validate_argument<_CharT, const void*>(__parse_ctx, __ctx);
23700798e50SMark de Wever   case __arg_t::__handle:
238c1905b1cSMark de Wever     std::__throw_format_error("Handle should use __compile_time_validate_handle_argument");
23900798e50SMark de Wever   }
240c1905b1cSMark de Wever   std::__throw_format_error("Invalid argument");
24100798e50SMark de Wever }
24200798e50SMark de Wever 
2431562e514SLouis Dionne template <contiguous_iterator _Iterator, class _ParseCtx, class _Ctx>
2441562e514SLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr _Iterator
2459783f28cSLouis Dionne __handle_replacement_field(_Iterator __begin, _Iterator __end, _ParseCtx& __parse_ctx, _Ctx& __ctx) {
2461562e514SLouis Dionne   using _CharT                        = iter_value_t<_Iterator>;
247261b5abfSMark de Wever   __format::__parse_number_result __r = __format::__parse_arg_id(__begin, __end, __parse_ctx);
24800798e50SMark de Wever 
2498930d04dSMark de Wever   if (__r.__last == __end)
2508930d04dSMark de Wever     std::__throw_format_error("The argument index should end with a ':' or a '}'");
2518930d04dSMark de Wever 
2521562e514SLouis Dionne   bool __parse = *__r.__last == _CharT(':');
2531562e514SLouis Dionne   switch (*__r.__last) {
25400798e50SMark de Wever   case _CharT(':'):
25500798e50SMark de Wever     // The arg-id has a format-specifier, advance the input to the format-spec.
2561562e514SLouis Dionne     __parse_ctx.advance_to(__r.__last + 1);
25700798e50SMark de Wever     break;
25800798e50SMark de Wever   case _CharT('}'):
25900798e50SMark de Wever     // The arg-id has no format-specifier.
2601562e514SLouis Dionne     __parse_ctx.advance_to(__r.__last);
26100798e50SMark de Wever     break;
26200798e50SMark de Wever   default:
263402eb2efSMark de Wever     std::__throw_format_error("The argument index should end with a ':' or a '}'");
26400798e50SMark de Wever   }
26500798e50SMark de Wever 
26600798e50SMark de Wever   if constexpr (same_as<_Ctx, __compile_time_basic_format_context<_CharT>>) {
26700798e50SMark de Wever     __arg_t __type = __ctx.arg(__r.__value);
268ac44dadcSMark de Wever     if (__type == __arg_t::__none)
269402eb2efSMark de Wever       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
270ac44dadcSMark de Wever     else if (__type == __arg_t::__handle)
27100798e50SMark de Wever       __ctx.__handle(__r.__value).__parse(__parse_ctx);
272ac44dadcSMark de Wever     else if (__parse)
27300798e50SMark de Wever       __format::__compile_time_visit_format_arg(__parse_ctx, __ctx, __type);
27400798e50SMark de Wever   } else
27577a00c0dSLouis Dionne     std::__visit_format_arg(
27600798e50SMark de Wever         [&](auto __arg) {
27700798e50SMark de Wever           if constexpr (same_as<decltype(__arg), monostate>)
278402eb2efSMark de Wever             std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
27900798e50SMark de Wever           else if constexpr (same_as<decltype(__arg), typename basic_format_arg<_Ctx>::handle>)
28000798e50SMark de Wever             __arg.format(__parse_ctx, __ctx);
28100798e50SMark de Wever           else {
28200798e50SMark de Wever             formatter<decltype(__arg), _CharT> __formatter;
28300798e50SMark de Wever             if (__parse)
28400798e50SMark de Wever               __parse_ctx.advance_to(__formatter.parse(__parse_ctx));
28500798e50SMark de Wever             __ctx.advance_to(__formatter.format(__arg, __ctx));
28600798e50SMark de Wever           }
28700798e50SMark de Wever         },
28800798e50SMark de Wever         __ctx.arg(__r.__value));
28900798e50SMark de Wever 
29000798e50SMark de Wever   __begin = __parse_ctx.begin();
29100798e50SMark de Wever   if (__begin == __end || *__begin != _CharT('}'))
292c1905b1cSMark de Wever     std::__throw_format_error("The replacement field misses a terminating '}'");
29300798e50SMark de Wever 
29400798e50SMark de Wever   return ++__begin;
29500798e50SMark de Wever }
29600798e50SMark de Wever 
29700798e50SMark de Wever template <class _ParseCtx, class _Ctx>
2989783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr typename _Ctx::iterator __vformat_to(_ParseCtx&& __parse_ctx, _Ctx&& __ctx) {
29900798e50SMark de Wever   using _CharT = typename _ParseCtx::char_type;
30000798e50SMark de Wever   static_assert(same_as<typename _Ctx::char_type, _CharT>);
30100798e50SMark de Wever 
3021562e514SLouis Dionne   auto __begin                     = __parse_ctx.begin();
3031562e514SLouis Dionne   auto __end                       = __parse_ctx.end();
30400798e50SMark de Wever   typename _Ctx::iterator __out_it = __ctx.out();
30500798e50SMark de Wever   while (__begin != __end) {
30600798e50SMark de Wever     switch (*__begin) {
30700798e50SMark de Wever     case _CharT('{'):
30800798e50SMark de Wever       ++__begin;
30900798e50SMark de Wever       if (__begin == __end)
310c1905b1cSMark de Wever         std::__throw_format_error("The format string terminates at a '{'");
31100798e50SMark de Wever 
31200798e50SMark de Wever       if (*__begin != _CharT('{')) [[likely]] {
31377a00c0dSLouis Dionne         __ctx.advance_to(std::move(__out_it));
3149783f28cSLouis Dionne         __begin  = __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
31500798e50SMark de Wever         __out_it = __ctx.out();
31600798e50SMark de Wever 
31700798e50SMark de Wever         // The output is written and __begin points to the next character. So
31800798e50SMark de Wever         // start the next iteration.
31900798e50SMark de Wever         continue;
32000798e50SMark de Wever       }
32100798e50SMark de Wever       // The string is an escape character.
32200798e50SMark de Wever       break;
32300798e50SMark de Wever 
32400798e50SMark de Wever     case _CharT('}'):
32500798e50SMark de Wever       ++__begin;
32600798e50SMark de Wever       if (__begin == __end || *__begin != _CharT('}'))
327c1905b1cSMark de Wever         std::__throw_format_error("The format string contains an invalid escape sequence");
32800798e50SMark de Wever 
32900798e50SMark de Wever       break;
33000798e50SMark de Wever     }
33100798e50SMark de Wever 
33200798e50SMark de Wever     // Copy the character to the output verbatim.
33300798e50SMark de Wever     *__out_it++ = *__begin++;
33400798e50SMark de Wever   }
33500798e50SMark de Wever   return __out_it;
33600798e50SMark de Wever }
33700798e50SMark de Wever 
33800798e50SMark de Wever } // namespace __format
33900798e50SMark de Wever 
34092d9f232SMark de Wever #  if _LIBCPP_STD_VER >= 26
34192d9f232SMark de Wever template <class _CharT>
34292d9f232SMark de Wever struct _LIBCPP_TEMPLATE_VIS __runtime_format_string {
34392d9f232SMark de Wever private:
34492d9f232SMark de Wever   basic_string_view<_CharT> __str_;
34592d9f232SMark de Wever 
34692d9f232SMark de Wever   template <class _Cp, class... _Args>
34792d9f232SMark de Wever   friend struct _LIBCPP_TEMPLATE_VIS basic_format_string;
34892d9f232SMark de Wever 
34992d9f232SMark de Wever public:
35092d9f232SMark de Wever   _LIBCPP_HIDE_FROM_ABI __runtime_format_string(basic_string_view<_CharT> __s) noexcept : __str_(__s) {}
35192d9f232SMark de Wever 
35292d9f232SMark de Wever   __runtime_format_string(const __runtime_format_string&)            = delete;
35392d9f232SMark de Wever   __runtime_format_string& operator=(const __runtime_format_string&) = delete;
35492d9f232SMark de Wever };
35592d9f232SMark de Wever 
35692d9f232SMark de Wever _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<char> runtime_format(string_view __fmt) noexcept { return __fmt; }
357c6f3b7bcSNikolas Klauser #    if _LIBCPP_HAS_WIDE_CHARACTERS
35892d9f232SMark de Wever _LIBCPP_HIDE_FROM_ABI inline __runtime_format_string<wchar_t> runtime_format(wstring_view __fmt) noexcept {
35992d9f232SMark de Wever   return __fmt;
36092d9f232SMark de Wever }
36192d9f232SMark de Wever #    endif
36292d9f232SMark de Wever #  endif // _LIBCPP_STD_VER >= 26
36392d9f232SMark de Wever 
36400798e50SMark de Wever template <class _CharT, class... _Args>
36500798e50SMark de Wever struct _LIBCPP_TEMPLATE_VIS basic_format_string {
36600798e50SMark de Wever   template <class _Tp>
36700798e50SMark de Wever     requires convertible_to<const _Tp&, basic_string_view<_CharT>>
36800798e50SMark de Wever   consteval basic_format_string(const _Tp& __str) : __str_{__str} {
36900798e50SMark de Wever     __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
37000798e50SMark de Wever                            _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
37100798e50SMark de Wever   }
37200798e50SMark de Wever 
3739783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI constexpr basic_string_view<_CharT> get() const noexcept { return __str_; }
37492d9f232SMark de Wever #  if _LIBCPP_STD_VER >= 26
37592d9f232SMark de Wever   _LIBCPP_HIDE_FROM_ABI basic_format_string(__runtime_format_string<_CharT> __s) noexcept : __str_(__s.__str_) {}
37692d9f232SMark de Wever #  endif
37700798e50SMark de Wever 
37800798e50SMark de Wever private:
37900798e50SMark de Wever   basic_string_view<_CharT> __str_;
38000798e50SMark de Wever 
381f6958523SNikolas Klauser   using _Context _LIBCPP_NODEBUG = __format::__compile_time_basic_format_context<_CharT>;
38200798e50SMark de Wever 
38300798e50SMark de Wever   static constexpr array<__format::__arg_t, sizeof...(_Args)> __types_{
38400798e50SMark de Wever       __format::__determine_arg_t<_Context, remove_cvref_t<_Args>>()...};
38500798e50SMark de Wever 
38600798e50SMark de Wever   static constexpr array<__format::__compile_time_handle<_CharT>, sizeof...(_Args)> __handles_{[] {
38700798e50SMark de Wever     using _Tp = remove_cvref_t<_Args>;
38800798e50SMark de Wever     __format::__compile_time_handle<_CharT> __handle;
38900798e50SMark de Wever     if (__format::__determine_arg_t<_Context, _Tp>() == __format::__arg_t::__handle)
39000798e50SMark de Wever       __handle.template __enable<_Tp>();
39100798e50SMark de Wever 
39200798e50SMark de Wever     return __handle;
39300798e50SMark de Wever   }()...};
39400798e50SMark de Wever };
39500798e50SMark de Wever 
39600798e50SMark de Wever template <class... _Args>
39700798e50SMark de Wever using format_string = basic_format_string<char, type_identity_t<_Args>...>;
39800798e50SMark de Wever 
399c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
40000798e50SMark de Wever template <class... _Args>
40100798e50SMark de Wever using wformat_string = basic_format_string<wchar_t, type_identity_t<_Args>...>;
40200798e50SMark de Wever #  endif
40300798e50SMark de Wever 
40400798e50SMark de Wever template <class _OutIt, class _CharT, class _FormatOutIt>
4059783f28cSLouis Dionne   requires(output_iterator<_OutIt, const _CharT&>)
4069783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(_OutIt __out_it,
4079783f28cSLouis Dionne                                           basic_string_view<_CharT> __fmt,
40800798e50SMark de Wever                                           basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
40900798e50SMark de Wever   if constexpr (same_as<_OutIt, _FormatOutIt>)
4109783f28cSLouis Dionne     return std::__format::__vformat_to(
4119783f28cSLouis Dionne         basic_format_parse_context{__fmt, __args.__size()}, std::__format_context_create(std::move(__out_it), __args));
41200798e50SMark de Wever   else {
413*14b44179SMark de Wever     typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)};
41477a00c0dSLouis Dionne     std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
41577a00c0dSLouis Dionne                                 std::__format_context_create(__buffer.__make_output_iterator(), __args));
41677a00c0dSLouis Dionne     return std::move(__buffer).__out_it();
41700798e50SMark de Wever   }
41800798e50SMark de Wever }
41900798e50SMark de Wever 
42000798e50SMark de Wever // The function is _LIBCPP_ALWAYS_INLINE since the compiler is bad at inlining
42100798e50SMark de Wever // https://reviews.llvm.org/D110499#inline-1180704
42200798e50SMark de Wever // TODO FMT Evaluate whether we want to file a Clang bug report regarding this.
42300798e50SMark de Wever template <output_iterator<const char&> _OutIt>
4249783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt vformat_to(_OutIt __out_it, string_view __fmt, format_args __args) {
42577a00c0dSLouis Dionne   return std::__vformat_to(std::move(__out_it), __fmt, __args);
42600798e50SMark de Wever }
42700798e50SMark de Wever 
428c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
42900798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt>
4303d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
43100798e50SMark de Wever vformat_to(_OutIt __out_it, wstring_view __fmt, wformat_args __args) {
43277a00c0dSLouis Dionne   return std::__vformat_to(std::move(__out_it), __fmt, __args);
43300798e50SMark de Wever }
43400798e50SMark de Wever #  endif
43500798e50SMark de Wever 
43600798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args>
4373d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
43800798e50SMark de Wever format_to(_OutIt __out_it, format_string<_Args...> __fmt, _Args&&... __args) {
4399783f28cSLouis Dionne   return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_format_args(__args...));
44000798e50SMark de Wever }
44100798e50SMark de Wever 
442c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
44300798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args>
4443d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
44500798e50SMark de Wever format_to(_OutIt __out_it, wformat_string<_Args...> __fmt, _Args&&... __args) {
4469783f28cSLouis Dionne   return std::vformat_to(std::move(__out_it), __fmt.get(), std::make_wformat_args(__args...));
44700798e50SMark de Wever }
44800798e50SMark de Wever #  endif
44900798e50SMark de Wever 
4503d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
4513d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563.
4523d334df5SLouis Dionne template <class = void>
45383bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string vformat(string_view __fmt, format_args __args) {
454*14b44179SMark de Wever   __format::__allocating_buffer<char> __buffer;
455*14b44179SMark de Wever   std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args);
456*14b44179SMark de Wever   return string{__buffer.__view()};
45700798e50SMark de Wever }
45800798e50SMark de Wever 
459c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
4603d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
4613d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563.
4623d334df5SLouis Dionne template <class = void>
46383bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
46400798e50SMark de Wever vformat(wstring_view __fmt, wformat_args __args) {
465*14b44179SMark de Wever   __format::__allocating_buffer<wchar_t> __buffer;
466*14b44179SMark de Wever   std::vformat_to(__buffer.__make_output_iterator(), __fmt, __args);
467*14b44179SMark de Wever   return wstring{__buffer.__view()};
46800798e50SMark de Wever }
46900798e50SMark de Wever #  endif
47000798e50SMark de Wever 
47100798e50SMark de Wever template <class... _Args>
47283bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string
4739c053e69SMark de Wever format(format_string<_Args...> __fmt, _Args&&... __args) {
47477a00c0dSLouis Dionne   return std::vformat(__fmt.get(), std::make_format_args(__args...));
47500798e50SMark de Wever }
47600798e50SMark de Wever 
477c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
47800798e50SMark de Wever template <class... _Args>
47983bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring
48000798e50SMark de Wever format(wformat_string<_Args...> __fmt, _Args&&... __args) {
48177a00c0dSLouis Dionne   return std::vformat(__fmt.get(), std::make_wformat_args(__args...));
48200798e50SMark de Wever }
48300798e50SMark de Wever #  endif
48400798e50SMark de Wever 
48500798e50SMark de Wever template <class _Context, class _OutIt, class _CharT>
4869783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
4879783f28cSLouis Dionne __vformat_to_n(_OutIt __out_it,
4889783f28cSLouis Dionne                iter_difference_t<_OutIt> __n,
48900798e50SMark de Wever                basic_string_view<_CharT> __fmt,
49000798e50SMark de Wever                basic_format_args<_Context> __args) {
49177a00c0dSLouis Dionne   __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n};
49277a00c0dSLouis Dionne   std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
49377a00c0dSLouis Dionne                               std::__format_context_create(__buffer.__make_output_iterator(), __args));
49477a00c0dSLouis Dionne   return std::move(__buffer).__result();
49500798e50SMark de Wever }
49600798e50SMark de Wever 
49700798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args>
4983d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
49900798e50SMark de Wever format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, format_string<_Args...> __fmt, _Args&&... __args) {
50077a00c0dSLouis Dionne   return std::__vformat_to_n<format_context>(std::move(__out_it), __n, __fmt.get(), std::make_format_args(__args...));
50100798e50SMark de Wever }
50200798e50SMark de Wever 
503c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
50400798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args>
5053d334df5SLouis Dionne _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt>
5069783f28cSLouis Dionne format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wformat_string<_Args...> __fmt, _Args&&... __args) {
50777a00c0dSLouis Dionne   return std::__vformat_to_n<wformat_context>(std::move(__out_it), __n, __fmt.get(), std::make_wformat_args(__args...));
50800798e50SMark de Wever }
50900798e50SMark de Wever #  endif
51000798e50SMark de Wever 
51100798e50SMark de Wever template <class _CharT>
51200798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
51300798e50SMark de Wever   __format::__formatted_size_buffer<_CharT> __buffer;
51477a00c0dSLouis Dionne   std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
51577a00c0dSLouis Dionne                               std::__format_context_create(__buffer.__make_output_iterator(), __args));
51677a00c0dSLouis Dionne   return std::move(__buffer).__result();
51700798e50SMark de Wever }
51800798e50SMark de Wever 
51900798e50SMark de Wever template <class... _Args>
52083bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
52100798e50SMark de Wever formatted_size(format_string<_Args...> __fmt, _Args&&... __args) {
52277a00c0dSLouis Dionne   return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_format_args(__args...)});
52300798e50SMark de Wever }
52400798e50SMark de Wever 
525c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_WIDE_CHARACTERS
52600798e50SMark de Wever template <class... _Args>
52783bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
52800798e50SMark de Wever formatted_size(wformat_string<_Args...> __fmt, _Args&&... __args) {
52977a00c0dSLouis Dionne   return std::__vformatted_size(__fmt.get(), basic_format_args{std::make_wformat_args(__args...)});
53000798e50SMark de Wever }
53100798e50SMark de Wever #  endif
53200798e50SMark de Wever 
533c6f3b7bcSNikolas Klauser #  if _LIBCPP_HAS_LOCALIZATION
53400798e50SMark de Wever 
53500798e50SMark de Wever template <class _OutIt, class _CharT, class _FormatOutIt>
5369783f28cSLouis Dionne   requires(output_iterator<_OutIt, const _CharT&>)
5379783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _OutIt __vformat_to(
5389783f28cSLouis Dionne     _OutIt __out_it,
5399783f28cSLouis Dionne     locale __loc,
5409783f28cSLouis Dionne     basic_string_view<_CharT> __fmt,
54100798e50SMark de Wever     basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
54200798e50SMark de Wever   if constexpr (same_as<_OutIt, _FormatOutIt>)
5439783f28cSLouis Dionne     return std::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
54477a00c0dSLouis Dionne                                        std::__format_context_create(std::move(__out_it), __args, std::move(__loc)));
54500798e50SMark de Wever   else {
546*14b44179SMark de Wever     typename __format::__buffer_selector<_OutIt, _CharT>::type __buffer{std::move(__out_it)};
54777a00c0dSLouis Dionne     std::__format::__vformat_to(
548261b5abfSMark de Wever         basic_format_parse_context{__fmt, __args.__size()},
54977a00c0dSLouis Dionne         std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));
55077a00c0dSLouis Dionne     return std::move(__buffer).__out_it();
55100798e50SMark de Wever   }
55200798e50SMark de Wever }
55300798e50SMark de Wever 
55400798e50SMark de Wever template <output_iterator<const char&> _OutIt>
5559783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
5569783f28cSLouis Dionne vformat_to(_OutIt __out_it, locale __loc, string_view __fmt, format_args __args) {
5579783f28cSLouis Dionne   return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args);
55800798e50SMark de Wever }
55900798e50SMark de Wever 
560c6f3b7bcSNikolas Klauser #    if _LIBCPP_HAS_WIDE_CHARACTERS
56100798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt>
5629783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
5639783f28cSLouis Dionne vformat_to(_OutIt __out_it, locale __loc, wstring_view __fmt, wformat_args __args) {
5649783f28cSLouis Dionne   return std::__vformat_to(std::move(__out_it), std::move(__loc), __fmt, __args);
56500798e50SMark de Wever }
56600798e50SMark de Wever #    endif
56700798e50SMark de Wever 
56800798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args>
5693d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
57000798e50SMark de Wever format_to(_OutIt __out_it, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
5719783f28cSLouis Dionne   return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_format_args(__args...));
57200798e50SMark de Wever }
57300798e50SMark de Wever 
574c6f3b7bcSNikolas Klauser #    if _LIBCPP_HAS_WIDE_CHARACTERS
57500798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args>
5763d334df5SLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI _OutIt
57700798e50SMark de Wever format_to(_OutIt __out_it, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
5789783f28cSLouis Dionne   return std::vformat_to(std::move(__out_it), std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));
57900798e50SMark de Wever }
58000798e50SMark de Wever #    endif
58100798e50SMark de Wever 
5823d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
5833d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563.
5843d334df5SLouis Dionne template <class = void>
58583bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI string
58600798e50SMark de Wever vformat(locale __loc, string_view __fmt, format_args __args) {
587*14b44179SMark de Wever   __format::__allocating_buffer<char> __buffer;
588*14b44179SMark de Wever   std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args);
589*14b44179SMark de Wever   return string{__buffer.__view()};
59000798e50SMark de Wever }
59100798e50SMark de Wever 
592c6f3b7bcSNikolas Klauser #    if _LIBCPP_HAS_WIDE_CHARACTERS
5933d334df5SLouis Dionne // TODO FMT This needs to be a template or std::to_chars(floating-point) availability markup
5943d334df5SLouis Dionne // fires too eagerly, see http://llvm.org/PR61563.
5953d334df5SLouis Dionne template <class = void>
59683bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE inline _LIBCPP_HIDE_FROM_ABI wstring
59700798e50SMark de Wever vformat(locale __loc, wstring_view __fmt, wformat_args __args) {
598*14b44179SMark de Wever   __format::__allocating_buffer<wchar_t> __buffer;
599*14b44179SMark de Wever   std::vformat_to(__buffer.__make_output_iterator(), std::move(__loc), __fmt, __args);
600*14b44179SMark de Wever   return wstring{__buffer.__view()};
60100798e50SMark de Wever }
60200798e50SMark de Wever #    endif
60300798e50SMark de Wever 
60400798e50SMark de Wever template <class... _Args>
60583bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI string
6069c053e69SMark de Wever format(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
6079783f28cSLouis Dionne   return std::vformat(std::move(__loc), __fmt.get(), std::make_format_args(__args...));
60800798e50SMark de Wever }
60900798e50SMark de Wever 
610c6f3b7bcSNikolas Klauser #    if _LIBCPP_HAS_WIDE_CHARACTERS
61100798e50SMark de Wever template <class... _Args>
61283bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI wstring
61300798e50SMark de Wever format(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
6149783f28cSLouis Dionne   return std::vformat(std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));
61500798e50SMark de Wever }
61600798e50SMark de Wever #    endif
61700798e50SMark de Wever 
61800798e50SMark de Wever template <class _Context, class _OutIt, class _CharT>
6199783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(
6209783f28cSLouis Dionne     _OutIt __out_it,
6219783f28cSLouis Dionne     iter_difference_t<_OutIt> __n,
6229783f28cSLouis Dionne     locale __loc,
6239783f28cSLouis Dionne     basic_string_view<_CharT> __fmt,
62400798e50SMark de Wever     basic_format_args<_Context> __args) {
62577a00c0dSLouis Dionne   __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{std::move(__out_it), __n};
62677a00c0dSLouis Dionne   std::__format::__vformat_to(
627261b5abfSMark de Wever       basic_format_parse_context{__fmt, __args.__size()},
62877a00c0dSLouis Dionne       std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));
62977a00c0dSLouis Dionne   return std::move(__buffer).__result();
63000798e50SMark de Wever }
63100798e50SMark de Wever 
63200798e50SMark de Wever template <output_iterator<const char&> _OutIt, class... _Args>
6339783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(
6349783f28cSLouis Dionne     _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
6359783f28cSLouis Dionne   return std::__vformat_to_n<format_context>(
6369783f28cSLouis Dionne       std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_format_args(__args...));
63700798e50SMark de Wever }
63800798e50SMark de Wever 
639c6f3b7bcSNikolas Klauser #    if _LIBCPP_HAS_WIDE_CHARACTERS
64000798e50SMark de Wever template <output_iterator<const wchar_t&> _OutIt, class... _Args>
6419783f28cSLouis Dionne _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> format_to_n(
6429783f28cSLouis Dionne     _OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
6439783f28cSLouis Dionne   return std::__vformat_to_n<wformat_context>(
6449783f28cSLouis Dionne       std::move(__out_it), __n, std::move(__loc), __fmt.get(), std::make_wformat_args(__args...));
64500798e50SMark de Wever }
64600798e50SMark de Wever #    endif
64700798e50SMark de Wever 
64800798e50SMark de Wever template <class _CharT>
64900798e50SMark de Wever _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
65000798e50SMark de Wever   __format::__formatted_size_buffer<_CharT> __buffer;
65177a00c0dSLouis Dionne   std::__format::__vformat_to(
652261b5abfSMark de Wever       basic_format_parse_context{__fmt, __args.__size()},
65377a00c0dSLouis Dionne       std::__format_context_create(__buffer.__make_output_iterator(), __args, std::move(__loc)));
65477a00c0dSLouis Dionne   return std::move(__buffer).__result();
65500798e50SMark de Wever }
65600798e50SMark de Wever 
65700798e50SMark de Wever template <class... _Args>
65883bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
65900798e50SMark de Wever formatted_size(locale __loc, format_string<_Args...> __fmt, _Args&&... __args) {
66077a00c0dSLouis Dionne   return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_format_args(__args...)});
66100798e50SMark de Wever }
66200798e50SMark de Wever 
663c6f3b7bcSNikolas Klauser #    if _LIBCPP_HAS_WIDE_CHARACTERS
66400798e50SMark de Wever template <class... _Args>
66583bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_ALWAYS_INLINE _LIBCPP_HIDE_FROM_ABI size_t
66600798e50SMark de Wever formatted_size(locale __loc, wformat_string<_Args...> __fmt, _Args&&... __args) {
66777a00c0dSLouis Dionne   return std::__vformatted_size(std::move(__loc), __fmt.get(), basic_format_args{std::make_wformat_args(__args...)});
66800798e50SMark de Wever }
66900798e50SMark de Wever #    endif
67000798e50SMark de Wever 
671c6f3b7bcSNikolas Klauser #  endif // _LIBCPP_HAS_LOCALIZATION
67200798e50SMark de Wever 
6734f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20
67400798e50SMark de Wever 
67500798e50SMark de Wever _LIBCPP_END_NAMESPACE_STD
67600798e50SMark de Wever 
6777b462251SLouis Dionne _LIBCPP_POP_MACROS
6787b462251SLouis Dionne 
67900798e50SMark de Wever #endif // _LIBCPP___FORMAT_FORMAT_FUNCTIONS
680