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